5 #define PY_SSIZE_T_CLEAN 6 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION 9 #include <numpy/arrayobject.h> 10 #include "structmember.h" 19 #define strcasecmp _stricmp 59 throw std::runtime_error(
"Umtx is NULL");
61 *store_ref = (PyArrayObject*)PyArray_FROM_OTF(Umtx_arg, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
63 throw std::runtime_error(
"Failed to convert Umtx");
65 if (!PyArray_IS_C_CONTIGUOUS(*store_ref)) {
66 std::cout <<
"Warning: Umtx is not memory contiguous" << std::endl;
76 throw std::runtime_error(
"matrix argument is NULL");
79 int requested_type = NPY_COMPLEX128;
80 if (PyArray_Check(matrix_arg) && PyArray_TYPE(reinterpret_cast<PyArrayObject*>(matrix_arg)) == NPY_COMPLEX64) {
81 requested_type = NPY_COMPLEX64;
84 *store_ref = (PyArrayObject*)PyArray_FROM_OTF(matrix_arg, requested_type, NPY_ARRAY_IN_ARRAY);
86 throw std::runtime_error(
"Failed to convert matrix argument");
88 if (!PyArray_IS_C_CONTIGUOUS(*store_ref)) {
89 std::cout <<
"Warning: matrix argument is not memory contiguous" << std::endl;
92 is_float32 = PyArray_TYPE(*store_ref) == NPY_COMPLEX64;
105 if (!parameters_arg) {
106 throw std::runtime_error(
"parameters argument is NULL");
109 int requested_type = NPY_FLOAT64;
110 if (PyArray_Check(parameters_arg) && PyArray_TYPE(reinterpret_cast<PyArrayObject*>(parameters_arg)) == NPY_FLOAT32) {
111 requested_type = NPY_FLOAT32;
114 *store_ref = (PyArrayObject*)PyArray_FROM_OTF(parameters_arg, requested_type, NPY_ARRAY_IN_ARRAY);
116 throw std::runtime_error(
"Failed to convert parameters argument");
119 is_float32 = PyArray_TYPE(*store_ref) == NPY_FLOAT32;
130 for (
int row=0; row<parameters32.
rows; row++) {
131 for (
int col=0; col<parameters32.
cols; col++) {
132 int idx = row*parameters32.
stride + col;
133 parameters64[idx] =
static_cast<double>(parameters32[idx]);
143 if (!initial_guess || initial_guess == Py_None) {
147 PyObject* guess_str_obj = PyObject_Str(initial_guess);
148 if (!guess_str_obj) {
149 throw std::runtime_error(
"Failed to convert initial guess to string");
151 const char* guess_str = PyUnicode_AsUTF8(guess_str_obj);
153 throw std::runtime_error(
"Failed to convert initial guess to string");
156 if (strcasecmp(
"zeros", guess_str) == 0)
return ZEROS;
157 if (strcasecmp(
"random", guess_str) == 0)
return RANDOM;
158 if (strcasecmp(
"close_to_zero", guess_str) == 0)
return CLOSE_TO_ZERO;
159 std::cout <<
"Warning: Unknown guess '" << guess_str <<
"', using RANDOM" << std::endl;
161 Py_XDECREF(guess_str_obj);
169 std::vector<matrix_base<int>>
result;
170 if (!topology || topology == Py_None) {
173 if (!PyList_Check(topology)) {
174 throw std::runtime_error(
"Topology must be a list");
176 Py_ssize_t
n = PyList_Size(topology);
177 for (Py_ssize_t i = 0; i <
n; i++) {
178 PyObject* item = PyList_GetItem(topology, i);
179 if (!PyTuple_Check(item)) {
180 throw std::runtime_error(
"Topology elements must be tuples");
183 pair[0] = PyLong_AsLong(PyTuple_GetItem(item, 0));
184 pair[1] = PyLong_AsLong(PyTuple_GetItem(item, 1));
185 result.push_back(pair);
194 std::map<std::string, Config_Element>
config;
195 if (!config_arg || config_arg == Py_None) {
198 if (!PyDict_Check(config_arg)) {
199 throw std::runtime_error(
"Config must be a dictionary");
201 PyObject *
key, *value;
203 while (PyDict_Next(config_arg, &pos, &key, &value)) {
204 std::string key_str = PyUnicode_AsUTF8(key);
206 if (PyBool_Check(value)) {
208 }
else if (PyLong_Check(value)) {
209 element.
set_property(key_str, PyLong_AsLongLong(value));
210 }
else if (PyFloat_Check(value)) {
213 config[key_str] = element;
219 bool use_float =
false;
220 if (config.count(
"use_float") > 0) {
221 config[
"use_float"].get_property(use_float);
231 static char* kwlist[] = {
232 (
char*)
"Umtx", (
char*)
"qbit_num", (
char*)
"optimize_layer_num",
233 (
char*)
"initial_guess", (
char*)
"config", NULL
236 PyObject *Umtx_arg = NULL, *initial_guess = NULL, *config_arg = NULL;
238 bool optimize_layer_num =
false;
240 if (!PyArg_ParseTupleAndKeywords(
241 args, kwds,
"O|ibOO", kwlist,
242 &Umtx_arg, &qbit_num, &optimize_layer_num, &initial_guess, &config_arg)
250 bool Umtx_is_float32 =
false;
253 if (qbit_num == -1) {
254 qbit_num = (
int)std::round(std::log2(Umtx_is_float32 ? Umtx_mtx_float.
rows : Umtx_mtx.
rows));
260 if (use_float_constructor && !Umtx_is_float32) {
264 if (use_float_constructor) {
272 }
catch (
const std::exception& e) {
273 PyErr_SetString(PyExc_Exception, e.what());
281 static char* kwlist[] = {
282 (
char*)
"Umtx", (
char*)
"qbit_num", (
char*)
"level_limit_max",
283 (
char*)
"level_limit_min", (
char*)
"topology", (
char*)
"config",
284 (
char*)
"accelerator_num", NULL
286 PyObject *Umtx_arg = NULL, *
topology = NULL, *config_arg = NULL;
287 int qbit_num = -1, level_limit = 8, level_limit_min = 0, accelerator_num = 0;
289 if (!PyArg_ParseTupleAndKeywords(
290 args, kwds,
"O|iiiOOi", kwlist,
291 &Umtx_arg, &qbit_num, &level_limit, &level_limit_min, &topology, &config_arg, &accelerator_num)
299 bool Umtx_is_float32 =
false;
301 const int Umtx_rows = Umtx_is_float32 ? Umtx_mtx_float.
rows : Umtx_mtx.
rows;
302 const int Umtx_cols = Umtx_is_float32 ? Umtx_mtx_float.
cols : Umtx_mtx.
cols;
307 if (Umtx_cols == 1 && qbit_num > 0) {
309 qbit_num = (
int)std::round(std::log2(Umtx_rows));
310 level_limit = level_limit_max_in;
314 if (qbit_num == -1) {
315 qbit_num = (
int)std::round(std::log2(Umtx_rows));
322 if (use_float_constructor && !Umtx_is_float32) {
326 if (use_float_constructor) {
328 Umtx_mtx_float, qbit_num, level_limit, level_limit_min,
329 topology_cpp,
config, accelerator_num
334 Umtx_mtx, qbit_num, level_limit, level_limit_min,
335 topology_cpp,
config, accelerator_num
340 }
catch (
const std::exception& e) {
341 PyErr_SetString(PyExc_Exception, e.what());
349 static char* kwlist[] = {
350 (
char*)
"Umtx", (
char*)
"qbit_num", (
char*)
"initial_guess",
351 (
char*)
"config", (
char*)
"accelerator_num", NULL
354 PyObject *Umtx_arg = NULL, *initial_guess = NULL, *config_arg = NULL;
355 int qbit_num = -1, accelerator_num = 0;
357 if (!PyArg_ParseTupleAndKeywords(
358 args, kwds,
"O|iOOi", kwlist,
359 &Umtx_arg, &qbit_num, &initial_guess, &config_arg, &accelerator_num)
367 bool Umtx_is_float32 =
false;
370 if (qbit_num == -1) {
371 qbit_num = (
int)std::round(std::log2(Umtx_is_float32 ? Umtx_mtx_float.
rows : Umtx_mtx.
rows));
377 if (use_float_constructor && !Umtx_is_float32) {
381 if (use_float_constructor) {
389 }
catch (
const std::exception& e) {
390 PyErr_SetString(PyExc_Exception, e.what());
395 template<
typename DecompT>
398 static char* kwlist[] = {
399 (
char*)
"Umtx", (
char*)
"qbit_num", (
char*)
"topology",
400 (
char*)
"config", (
char*)
"accelerator_num", NULL
403 PyObject *Umtx_arg = NULL, *
topology = NULL, *config_arg = NULL;
404 int qbit_num = -1, accelerator_num = 0;
406 if (!PyArg_ParseTupleAndKeywords(
407 args, kwds,
"O|iOOi", kwlist,
408 &Umtx_arg, &qbit_num, &topology, &config_arg, &accelerator_num)
416 bool Umtx_is_float32 =
false;
419 if (qbit_num == -1) {
420 qbit_num = (
int)std::round(std::log2(Umtx_is_float32 ? Umtx_mtx_float.
rows : Umtx_mtx.
rows));
426 if (use_float_constructor && !Umtx_is_float32) {
430 if (use_float_constructor) {
431 self->decomp =
new DecompT(Umtx_mtx_float, qbit_num, topology_cpp,
config, accelerator_num);
434 self->decomp =
new DecompT(Umtx_mtx, qbit_num, topology_cpp,
config, accelerator_num);
438 }
catch (
const std::exception& e) {
439 PyErr_SetString(PyExc_Exception, e.what());
446 return search_wrapper_init<N_Qubit_Decomposition_Tree_Search>(
self,
args,
kwds);
451 return search_wrapper_init<N_Qubit_Decomposition_Tabu_Search>(
self,
args,
kwds);
457 template<
typename DecompT>
459 if (instance != NULL) {
470 if (self->decomp != NULL) {
475 if (self->Umtx != NULL) {
477 Py_DECREF(self->Umtx);
480 Py_TYPE(
self)->tp_free((PyObject *)
self);
496 return (PyObject *)
self;
510 static char *kwlist[] = {NULL};
513 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|", kwlist))
518 p->start_decomposition();
522 p->start_decomposition();
526 p->start_decomposition();
530 p->start_decomposition();
534 p->start_decomposition();
538 PyErr_SetString(PyExc_TypeError,
"Unknown decomposition type");
550 int ret =
self->decomp->get_gate_num();
561 if (self->decomp->get_use_float()) {
562 Matrix_real_float parameters_mtx =
self->decomp->get_optimized_parameters_float();
567 Matrix_real parameters_mtx =
self->decomp->get_optimized_parameters();
573 return parameter_arr;
583 PyObject* qgd_Circuit = PyImport_ImportModule(
"squander.gates.qgd_Circuit");
584 if ( qgd_Circuit == NULL ) {
585 PyErr_SetString(PyExc_Exception,
"Module import error: squander.gates.qgd_Circuit" );
593 PyObject* qgd_circuit_Dict = PyModule_GetDict( qgd_Circuit );
596 PyObject* py_circuit_class = PyDict_GetItemString( qgd_circuit_Dict,
"qgd_Circuit");
602 PyObject* py_circuit = PyObject_CallObject(py_circuit_class, circuit_input);
606 delete( py_circuit_C->
gate );
619 self->decomp->list_gates(0);
631 PyObject* max_layer_num;
633 if (!PyArg_ParseTuple(args,
"O", &max_layer_num)) {
637 if (!PyDict_Check(max_layer_num)) {
638 PyErr_SetString(PyExc_TypeError,
"Input must be dictionary");
642 PyObject *
key = NULL, *value = NULL;
646 while (PyDict_Next(max_layer_num, &pos, &key, &value)) {
648 if (!PyLong_Check(value)) {
649 PyErr_SetString(PyExc_TypeError,
"Dictionary values must be integers");
652 int value_int = (
int)PyLong_AsLong(value);
655 if (!PyLong_Check(key)) {
656 PyErr_SetString(PyExc_TypeError,
"Dictionary keys must be integers");
659 int key_int = (
int)PyLong_AsLong(key);
662 self->decomp->set_max_layer_num(key_int, value_int);
665 }
catch (std::exception& e) {
666 PyErr_SetString(PyExc_Exception, e.what());
681 if (!PyArg_ParseTuple(args,
"O", &iteration_loops)) {
685 if (!PyDict_Check(iteration_loops)) {
686 PyErr_SetString(PyExc_TypeError,
"Input must be dictionary");
690 PyObject *
key = NULL, *value = NULL;
694 while (PyDict_Next(iteration_loops, &pos, &key, &value)) {
696 if (!PyLong_Check(value)) {
697 PyErr_SetString(PyExc_TypeError,
"Dictionary values must be integers");
700 int value_int = (
int)PyLong_AsLong(value);
703 if (!PyLong_Check(key)) {
704 PyErr_SetString(PyExc_TypeError,
"Dictionary keys must be integers");
707 int key_int = (
int)PyLong_AsLong(key);
709 self->decomp->set_iteration_loops(key_int, value_int);
712 }
catch (std::exception& e) {
713 PyErr_SetString(PyExc_Exception, e.what());
726 if (!PyArg_ParseTuple(args,
"i", &verbose)) {
730 self->decomp->set_verbose(verbose);
732 }
catch (std::exception& e) {
733 PyErr_SetString(PyExc_Exception, e.what());
745 PyObject* debugfile = NULL;
746 if (!PyArg_ParseTuple(args,
"O", &debugfile)) {
750 PyObject* debugfile_string = PyObject_Str(debugfile);
751 PyObject* debugfile_string_unicode = PyUnicode_AsEncodedString(debugfile_string,
"utf-8",
"~E~");
752 const char* debugfile_C = PyBytes_AS_STRING(debugfile_string_unicode);
753 Py_XDECREF(debugfile_string);
754 Py_XDECREF(debugfile_string_unicode);
756 Py_ssize_t string_length = PyBytes_Size(debugfile_string_unicode);
757 std::string debugfile_Cpp(debugfile_C, string_length);
760 self->decomp->set_debugfile(debugfile_Cpp);
762 }
catch (std::exception& e) {
763 PyErr_SetString(PyExc_Exception, e.what());
776 if (!PyArg_ParseTuple(args,
"O", &qbit_list)) {
779 bool is_list = PyList_Check(qbit_list), is_tuple = PyTuple_Check(qbit_list);
780 if (!is_list && !is_tuple) {
781 PyErr_SetString(PyExc_TypeError,
"Input must be tuple or list");
784 Py_ssize_t element_num;
786 element_num = PyTuple_GET_SIZE(qbit_list);
788 element_num = PyList_GET_SIZE(qbit_list);
791 std::vector<int> qbit_list_C((
int)element_num);
792 for (Py_ssize_t idx = 0; idx < element_num; idx++) {
794 qbit_list_C[(
int) idx] = (
int) PyLong_AsLong( PyTuple_GetItem(qbit_list, idx) );
797 qbit_list_C[(
int) idx] = (
int) PyLong_AsLong( PyList_GetItem(qbit_list, idx) );
802 self->decomp->reorder_qubits(qbit_list_C);
804 }
catch (std::exception& e) {
805 PyErr_SetString(PyExc_Exception, e.what());
818 if (!PyArg_ParseTuple(args,
"d", &tolerance)) {
822 self->decomp->set_optimization_tolerance(tolerance);
824 }
catch (std::exception& e) {
825 PyErr_SetString(PyExc_Exception, e.what());
838 if (!PyArg_ParseTuple(args,
"d", &threshold)) {
842 self->decomp->set_convergence_threshold(threshold);
844 }
catch (std::exception& e) {
845 PyErr_SetString(PyExc_Exception, e.what());
857 int optimization_blocks;
858 if (!PyArg_ParseTuple(args,
"i", &optimization_blocks)) {
862 self->decomp->set_optimization_blocks(optimization_blocks);
864 }
catch (std::exception& e) {
865 PyErr_SetString(PyExc_Exception, e.what());
877 self->decomp->add_finalyzing_layer();
879 catch (std::string err) {
880 PyErr_SetString(PyExc_Exception, err.c_str());
884 std::string err(
"Invalid pointer to decomposition class");
885 PyErr_SetString(PyExc_Exception, err.c_str());
902 PyObject* gate_structure_py = NULL;
905 if (!PyArg_ParseTuple(args,
"|O", &gate_structure_py)) {
909 if (gate_structure_py == NULL) {
910 PyErr_SetString(PyExc_TypeError,
"set_Gate_Structure requires a circuit argument");
915 if (PyDict_Check(gate_structure_py)) {
916 PyObject *
key = NULL, *value = NULL;
920 while (PyDict_Next(gate_structure_py, &pos, &key, &value)) {
922 if (!PyLong_Check(key)) {
923 PyErr_SetString(PyExc_TypeError,
"Dictionary keys must be integers");
926 int key_int = (
int)PyLong_AsLong(key);
929 gate_structure.insert(std::pair<int, Gates_block*>(key_int, qgd_op_block->
gate));
934 if (base_decomp != NULL) {
938 }
catch (std::string err) {
939 PyErr_SetString(PyExc_Exception, err.c_str());
941 }
catch (std::exception& e) {
942 PyErr_SetString(PyExc_Exception, e.what());
945 std::string err(
"Invalid pointer to decomposition class");
946 PyErr_SetString(PyExc_Exception, err.c_str());
950 PyErr_SetString(PyExc_AttributeError,
"Dictionary-based set_Gate_Structure is only available for N_Qubit_Decomposition");
956 self->decomp->set_custom_gate_structure(qgd_op_block->
gate);
958 }
catch (std::string err) {
959 PyErr_SetString(PyExc_Exception, err.c_str());
961 }
catch (std::exception& e) {
962 PyErr_SetString(PyExc_Exception, e.what());
965 std::string err(
"Invalid pointer to decomposition class");
966 PyErr_SetString(PyExc_Exception, err.c_str());
990 PyObject* parameters_obj = NULL;
991 PyArrayObject* parameters_arr = NULL;
993 if (!PyArg_ParseTuple(args,
"|O", ¶meters_obj )) {
999 bool parameters_is_float32 =
false;
1001 extract_parameters_any(parameters_obj, ¶meters_arr, parameters_mtx, parameters_mtx_float, parameters_is_float32);
1002 if (parameters_is_float32) {
1005 self->decomp->set_optimized_parameters(parameters_mtx.
get_data(), parameters_mtx.
size());
1007 catch (std::string err ) {
1008 PyErr_SetString(PyExc_Exception, err.c_str());
1012 std::string err(
"Invalid pointer to decomposition class");
1013 PyErr_SetString(PyExc_Exception, err.c_str());
1016 Py_DECREF(parameters_arr);
1028 int number_of_iters =
self->decomp->get_num_iters();
1044 if (!PyArg_ParseTuple(args,
"|O", &filename)) {
1047 PyObject* filename_string = PyObject_Str(filename);
1048 PyObject* filename_unicode = PyUnicode_AsEncodedString(filename_string,
"utf-8",
"~E~");
1049 const char* filename_C = PyBytes_AS_STRING(filename_unicode);
1050 std::string filename_str(filename_C);
1052 self->decomp->export_unitary(filename_str);
1066 if (!PyArg_ParseTuple(args,
"|O", &filename) || filename == NULL) {
1067 PyErr_SetString(PyExc_TypeError,
"export_Gate_Structure_to_Binary requires a filename argument");
1071 PyObject* filename_string = PyObject_Str(filename);
1072 if (filename_string == NULL) {
1075 PyObject* filename_unicode = PyUnicode_AsEncodedString(filename_string,
"utf-8",
"~E~");
1076 Py_DECREF(filename_string);
1077 if (filename_unicode == NULL) {
1080 const char* filename_C = PyBytes_AS_STRING(filename_unicode);
1081 std::string filename_str(filename_C);
1084 Matrix_real parameters_mtx =
self->decomp->get_optimized_parameters();
1087 catch (std::string err) {
1088 Py_DECREF(filename_unicode);
1089 PyErr_SetString(PyExc_Exception, err.c_str());
1092 catch (std::exception& e) {
1093 Py_DECREF(filename_unicode);
1094 PyErr_SetString(PyExc_Exception, e.what());
1098 Py_DECREF(filename_unicode);
1099 PyErr_SetString(PyExc_Exception,
"export_Gate_Structure_to_Binary: failed to export circuit");
1103 Py_DECREF(filename_unicode);
1116 std::string
project_name =
self->decomp->get_project_name();
1117 return PyUnicode_FromString(project_name.c_str());
1118 }
catch (std::exception& e) {
1119 PyErr_SetString(PyExc_Exception, e.what());
1134 PyObject* project_name_new = NULL;
1136 if (!PyArg_ParseTuple(args,
"|O", &project_name_new)) {
1139 PyObject* project_name_new_string = PyObject_Str(project_name_new);
1140 PyObject* project_name_new_unicode = PyUnicode_AsEncodedString(project_name_new_string,
"utf-8",
"~E~");
1141 const char* project_name_new_C = PyBytes_AS_STRING(project_name_new_unicode);
1142 std::string project_name_new_str(project_name_new_C);
1144 self->decomp->set_project_name(project_name_new_str);
1156 QGD_Complex16 global_phase_factor_C =
self->decomp->get_global_phase_factor();
1157 PyObject* global_phase = PyFloat_FromDouble(std::atan2(global_phase_factor_C.
imag, global_phase_factor_C.
real));
1158 return global_phase;
1171 if (!PyArg_ParseTuple(args,
"d", &phase_angle)) {
1175 self->decomp->set_global_phase(phase_angle);
1177 }
catch (std::exception& e) {
1178 PyErr_SetString(PyExc_Exception, e.what());
1192 self->decomp->apply_global_phase_factor();
1194 }
catch (std::exception& e) {
1195 PyErr_SetString(PyExc_Exception, e.what());
1208 if (self->decomp->get_use_float()) {
1211 Unitary_mtx =
self->decomp->get_Umtx_float().
copy();
1213 catch (std::string err) {
1214 PyErr_SetString(PyExc_Exception, err.c_str());
1218 std::string err(
"Invalid pointer to decomposition class");
1219 PyErr_SetString(PyExc_Exception, err.c_str());
1228 Unitary_mtx =
self->decomp->get_Umtx().
copy();
1230 catch (std::string err) {
1231 PyErr_SetString(PyExc_Exception, err.c_str());
1235 std::string err(
"Invalid pointer to decomposition class");
1236 PyErr_SetString(PyExc_Exception, err.c_str());
1256 static char *kwlist[] = {(
char*)
"optimizer", NULL};
1258 PyObject* optimizer_arg = NULL;
1261 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|O", kwlist, &optimizer_arg)) {
1262 std::string err(
"Unsuccessful argument parsing");
1263 PyErr_SetString(PyExc_Exception, err.c_str());
1267 if (optimizer_arg == NULL) {
1268 std::string err(
"optimizer argument not set");
1269 PyErr_SetString(PyExc_Exception, err.c_str());
1273 PyObject* optimizer_string = PyObject_Str(optimizer_arg);
1274 PyObject* optimizer_string_unicode = PyUnicode_AsEncodedString(optimizer_string,
"utf-8",
"~E~");
1275 const char* optimizer_C = PyBytes_AS_STRING(optimizer_string_unicode);
1278 if (strcmp(
"bfgs", optimizer_C) == 0 || strcmp(
"BFGS", optimizer_C) == 0) {
1279 qgd_optimizer =
BFGS;
1281 else if (strcmp(
"adam", optimizer_C) == 0 || strcmp(
"ADAM", optimizer_C) == 0) {
1282 qgd_optimizer =
ADAM;
1284 else if (strcmp(
"grad_descend", optimizer_C) == 0 || strcmp(
"GRAD_DESCEND", optimizer_C) == 0) {
1287 else if (strcmp(
"adam_batched", optimizer_C) == 0 || strcmp(
"ADAM_BATCHED", optimizer_C) == 0) {
1290 else if (strcmp(
"bfgs2", optimizer_C) == 0 || strcmp(
"BFGS2", optimizer_C) == 0) {
1291 qgd_optimizer =
BFGS2;
1293 else if (strcmp(
"agents", optimizer_C) == 0 || strcmp(
"AGENTS", optimizer_C) == 0) {
1296 else if (strcmp(
"cosine", optimizer_C) == 0 || strcmp(
"COSINE", optimizer_C) == 0) {
1299 else if (strcmp(
"grad_descend_phase_shift_rule", optimizer_C) == 0 || strcmp(
"GRAD_DESCEND_PARAMETER_SHIFT_RULE", optimizer_C) == 0) {
1302 else if (strcmp(
"agents_combined", optimizer_C) == 0 || strcmp(
"AGENTS_COMBINED", optimizer_C) == 0) {
1305 else if (strcmp(
"bayes_opt", optimizer_C) == 0 || strcmp(
"BAYES_OPT", optimizer_C) == 0) {
1309 std::cout <<
"Wrong optimizer: " << optimizer_C <<
". Using default: BFGS" << std::endl;
1310 qgd_optimizer =
BFGS;
1314 self->decomp->set_optimizer(qgd_optimizer);
1316 catch (std::string err) {
1317 PyErr_SetString(PyExc_Exception, err.c_str());
1318 std::cout << err << std::endl;
1322 std::string err(
"Invalid pointer to decomposition class");
1323 PyErr_SetString(PyExc_Exception, err.c_str());
1339 if (!PyArg_ParseTuple(args,
"i", &max_iterations)) {
1343 self->decomp->set_max_inner_iterations(max_iterations);
1345 }
catch (std::exception& e) {
1346 PyErr_SetString(PyExc_Exception, e.what());
1361 PyObject* parameters_obj = NULL;
1362 PyArrayObject* parameters_arr = NULL;
1365 if (!PyArg_ParseTuple(args,
"|O", ¶meters_obj))
1370 bool parameters_is_float32 =
false;
1372 extract_parameters_any(parameters_obj, ¶meters_arr, parameters_mtx, parameters_mtx_float, parameters_is_float32);
1374 catch (std::exception& e) {
1375 PyErr_SetString(PyExc_Exception, e.what());
1379 PyObject *unitary_py = NULL;
1380 if (parameters_is_float32 || self->decomp->get_use_float()) {
1381 if (!parameters_is_float32) {
1383 for (
int row=0; row<parameters_mtx.
rows; row++) {
1384 for (
int col=0; col<parameters_mtx.
cols; col++) {
1385 int idx = row*parameters_mtx.
stride + col;
1386 parameters_mtx_float[idx] =
static_cast<float>(parameters_mtx[idx]);
1390 Matrix_float unitary_mtx =
self->decomp->get_matrix(parameters_mtx_float);
1395 Matrix unitary_mtx =
self->decomp->get_matrix(parameters_mtx);
1400 Py_DECREF(parameters_arr);
1416 static char *kwlist[] = {(
char*)
"costfnc", NULL};
1418 int costfnc_arg = 0;
1421 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|i", kwlist, &costfnc_arg)) {
1422 std::string err(
"Unsuccessful argument parsing");
1423 PyErr_SetString(PyExc_Exception, err.c_str());
1430 self->decomp->set_cost_function_variant(qgd_costfnc);
1432 catch (std::string err) {
1433 PyErr_SetString(PyExc_Exception, err.c_str());
1434 std::cout << err << std::endl;
1438 std::string err(
"Invalid pointer to decomposition class");
1439 PyErr_SetString(PyExc_Exception, err.c_str());
1454 PyObject* parameters_obj = NULL;
1455 PyArrayObject* parameters_arg = NULL;
1458 if (!PyArg_ParseTuple(args,
"|O", ¶meters_obj)) {
1459 std::string err(
"Unsuccessful argument parsing not ");
1460 PyErr_SetString(PyExc_Exception, err.c_str());
1466 bool parameters_is_float32 =
false;
1470 extract_parameters_any(parameters_obj, ¶meters_arg, parameters_mtx, parameters_mtx_float, parameters_is_float32);
1471 if (parameters_is_float32) {
1474 f0 =
self->decomp->optimization_problem(parameters_mtx);
1476 catch (std::exception& e) {
1477 PyErr_SetString(PyExc_Exception, e.what());
1480 catch (std::string err) {
1481 PyErr_SetString(PyExc_Exception, err.c_str());
1485 std::string err(
"Invalid pointer to decomposition class");
1486 PyErr_SetString(PyExc_Exception, err.c_str());
1490 Py_DECREF(parameters_arg);
1504 PyObject* parameters_obj = NULL;
1505 PyArrayObject* parameters_arg = NULL;
1508 if (!PyArg_ParseTuple(args,
"|O", ¶meters_obj)) {
1509 std::string err(
"Unsuccessful argument parsing not ");
1510 PyErr_SetString(PyExc_Exception, err.c_str());
1516 bool parameters_is_float32 =
false;
1518 std::vector<Matrix> Umtx_deriv;
1521 extract_parameters_any(parameters_obj, ¶meters_arg, parameters_mtx, parameters_mtx_float, parameters_is_float32);
1522 if (parameters_is_float32) {
1525 self->decomp->optimization_problem_combined_unitary(parameters_mtx, Umtx, Umtx_deriv);
1527 catch (std::exception& e) {
1528 PyErr_SetString(PyExc_Exception, e.what());
1531 catch (std::string err) {
1532 PyErr_SetString(PyExc_Exception, err.c_str());
1536 std::string err(
"Invalid pointer to decomposition class");
1537 PyErr_SetString(PyExc_Exception, err.c_str());
1544 PyObject* graduni_py = PyList_New(Umtx_deriv.size());
1545 for (
size_t i = 0; i < Umtx_deriv.size(); i++) {
1546 Umtx_deriv[i].set_owner(
false);
1550 Py_DECREF(parameters_arg);
1552 PyObject* p =
Py_BuildValue(
"(OO)", unitary_py, graduni_py);
1553 Py_DECREF(unitary_py);
1554 Py_DECREF(graduni_py);
1567 PyObject* parameters_obj = NULL;
1568 PyArrayObject* parameters_arg = NULL;
1571 if (!PyArg_ParseTuple(args,
"|O", ¶meters_obj)) {
1572 std::string err(
"Unsuccessful argument parsing not ");
1573 PyErr_SetString(PyExc_Exception, err.c_str());
1579 bool parameters_is_float32 =
false;
1583 extract_parameters_any(parameters_obj, ¶meters_arg, parameters_mtx, parameters_mtx_float, parameters_is_float32);
1584 if (parameters_is_float32) {
1588 self->decomp->optimization_problem_grad(parameters_mtx, self->decomp, grad_mtx);
1590 catch (std::exception& e) {
1591 PyErr_SetString(PyExc_Exception, e.what());
1594 catch (std::string err) {
1595 PyErr_SetString(PyExc_Exception, err.c_str());
1599 std::string err(
"Invalid pointer to decomposition class");
1600 PyErr_SetString(PyExc_Exception, err.c_str());
1605 PyObject *grad_py = NULL;
1606 if (parameters_is_float32 || self->decomp->get_use_float()) {
1608 for (
int row=0; row<grad_mtx.rows; row++) {
1609 for (
int col=0; col<grad_mtx.cols; col++) {
1610 int idx = row*grad_mtx.stride + col;
1611 grad_float[idx] =
static_cast<float>(grad_mtx[idx]);
1618 grad_mtx.set_owner(
false);
1622 Py_DECREF(parameters_arg);
1636 PyObject* parameters_obj = NULL;
1637 PyArrayObject* parameters_arg = NULL;
1640 if (!PyArg_ParseTuple(args,
"|O", ¶meters_obj)) {
1641 std::string err(
"Unsuccessful argument parsing not ");
1642 PyErr_SetString(PyExc_Exception, err.c_str());
1648 bool parameters_is_float32 =
false;
1653 extract_parameters_any(parameters_obj, ¶meters_arg, parameters_mtx, parameters_mtx_float, parameters_is_float32);
1654 if (parameters_is_float32) {
1658 self->decomp->optimization_problem_combined(parameters_mtx, &f0, grad_mtx);
1660 catch (std::exception& e) {
1661 PyErr_SetString(PyExc_Exception, e.what());
1664 catch (std::string err) {
1665 PyErr_SetString(PyExc_Exception, err.c_str());
1669 std::string err(
"Invalid pointer to decomposition class");
1670 PyErr_SetString(PyExc_Exception, err.c_str());
1675 PyObject *grad_py = NULL;
1676 if (parameters_is_float32 || self->decomp->get_use_float()) {
1678 for (
int row=0; row<grad_mtx.rows; row++) {
1679 for (
int col=0; col<grad_mtx.cols; col++) {
1680 int idx = row*grad_mtx.stride + col;
1681 grad_float[idx] =
static_cast<float>(grad_mtx[idx]);
1688 grad_mtx.set_owner(
false);
1692 Py_DECREF(parameters_arg);
1708 PyObject* parameters_obj = NULL;
1709 PyArrayObject* parameters_arg = NULL;
1712 if (!PyArg_ParseTuple(args,
"|O", ¶meters_obj)) {
1713 std::string err(
"Unsuccessful argument parsing not ");
1714 PyErr_SetString(PyExc_Exception, err.c_str());
1720 bool parameters_is_float32 =
false;
1724 extract_parameters_any(parameters_obj, ¶meters_arg, parameters_mtx, parameters_mtx_float, parameters_is_float32);
1725 if (parameters_is_float32) {
1728 std::vector<Matrix_real> parameters_vec;
1729 parameters_vec.resize(parameters_mtx.
rows);
1730 for (
int row_idx = 0; row_idx < parameters_mtx.
rows; row_idx++) {
1733 result_mtx =
self->decomp->optimization_problem_batched(parameters_vec);
1735 catch (std::exception& e) {
1736 PyErr_SetString(PyExc_Exception, e.what());
1739 catch (std::string err) {
1740 PyErr_SetString(PyExc_Exception, err.c_str());
1744 std::string err(
"Invalid pointer to decomposition class");
1745 PyErr_SetString(PyExc_Exception, err.c_str());
1750 PyObject *result_py = NULL;
1751 if (parameters_is_float32 || self->decomp->get_use_float()) {
1753 for (
int row=0; row<result_mtx.
rows; row++) {
1754 for (
int col=0; col<result_mtx.
cols; col++) {
1755 int idx = row*result_mtx.
stride + col;
1756 result_float[idx] =
static_cast<float>(result_mtx[idx]);
1767 Py_DECREF(parameters_arg);
1782 self->decomp->upload_Umtx_to_DFE();
1784 }
catch (std::string err) {
1785 PyErr_SetString(PyExc_Exception, err.c_str());
1787 }
catch (std::exception& e) {
1788 PyErr_SetString(PyExc_Exception, e.what());
1791 std::string err(
"Invalid pointer to decomposition class");
1792 PyErr_SetString(PyExc_Exception, err.c_str());
1796 PyErr_SetString(PyExc_NotImplementedError,
"upload_Umtx_to_DFE is only available when compiled with DFE support");
1810 int trace_offset =
self->decomp->get_trace_offset();
1812 }
catch (std::string err) {
1813 PyErr_SetString(PyExc_Exception, err.c_str());
1815 }
catch (std::exception& e) {
1816 PyErr_SetString(PyExc_Exception, e.what());
1819 std::string err(
"Invalid pointer to decomposition class");
1820 PyErr_SetString(PyExc_Exception, err.c_str());
1834 static char *kwlist[] = {(
char*)
"trace_offset", NULL};
1836 int trace_offset = 0;
1837 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|i", kwlist, &trace_offset)) {
1838 std::string err(
"Invalid arguments: expected (trace_offset: int)");
1839 PyErr_SetString(PyExc_Exception, err.c_str());
1844 self->decomp->set_trace_offset(trace_offset);
1846 }
catch (std::string err) {
1847 PyErr_SetString(PyExc_Exception, err.c_str());
1849 }
catch (std::exception& e) {
1850 PyErr_SetString(PyExc_Exception, e.what());
1853 std::string err(
"Invalid pointer to decomposition class");
1854 PyErr_SetString(PyExc_Exception, err.c_str());
1868 double error =
self->decomp->get_decomposition_error();
1870 }
catch (std::string err) {
1871 PyErr_SetString(PyExc_Exception, err.c_str());
1873 }
catch (std::exception& e) {
1874 PyErr_SetString(PyExc_Exception, e.what());
1877 std::string err(
"Invalid pointer to decomposition class");
1878 PyErr_SetString(PyExc_Exception, err.c_str());
1892 PyObject *parameters_obj = NULL, *input_state_obj = NULL;
1893 PyArrayObject *parameters_arr = NULL, *input_state_arg = NULL;
1894 PyObject *qubit_list_arg = NULL;
1897 if (!PyArg_ParseTuple(args,
"|OOO", ¶meters_obj, &input_state_obj, &qubit_list_arg)) {
1903 bool parameters_is_float32 =
false;
1905 extract_parameters_any(parameters_obj, ¶meters_arr, parameters_mtx, parameters_mtx_float, parameters_is_float32);
1906 if (parameters_is_float32) {
1910 catch (std::exception& e) {
1911 PyErr_SetString(PyExc_Exception, e.what());
1916 if (input_state_obj == NULL) {
1917 PyErr_SetString(PyExc_Exception,
"Input matrix was not given");
1923 bool input_state_is_float32 =
false;
1925 extract_matrix_any(input_state_obj, &input_state_arg, input_state_mtx, input_state_mtx_float, input_state_is_float32);
1926 if (input_state_is_float32) {
1927 input_state_mtx = input_state_mtx_float.
to_float64();
1930 catch (std::exception& e) {
1931 PyErr_SetString(PyExc_Exception, e.what());
1936 if (!PyArray_IS_C_CONTIGUOUS(input_state_arg)) {
1937 PyErr_SetString(PyExc_Exception,
"Input matrix is not memory contiguous");
1942 if (qubit_list_arg == NULL || !PyList_Check(qubit_list_arg)) {
1943 PyErr_SetString(PyExc_Exception,
"qubit_list should be a list");
1947 Py_ssize_t reduced_qbit_num = PyList_Size(qubit_list_arg);
1950 for (
int idx = 0; idx < reduced_qbit_num; idx++) {
1951 PyObject* item = PyList_GET_ITEM(qubit_list_arg, idx);
1952 qbit_list_mtx[idx] = (
int)PyLong_AsLong(item);
1958 entropy =
self->decomp->get_second_Renyi_entropy(parameters_mtx, input_state_mtx, qbit_list_mtx);
1959 }
catch (std::string err) {
1960 PyErr_SetString(PyExc_Exception, err.c_str());
1962 }
catch (std::exception& e) {
1963 PyErr_SetString(PyExc_Exception, e.what());
1966 std::string err(
"Invalid pointer to decomposition class");
1967 PyErr_SetString(PyExc_Exception, err.c_str());
1972 Py_DECREF(parameters_arr);
1973 Py_DECREF(input_state_arg);
1988 int qbit_num =
self->decomp->get_qbit_num();
1990 }
catch (std::string err) {
1991 PyErr_SetString(PyExc_Exception, err.c_str());
1993 }
catch (std::exception& e) {
1994 PyErr_SetString(PyExc_Exception, e.what());
1997 std::string err(
"Invalid pointer to decomposition class");
1998 PyErr_SetString(PyExc_Exception, err.c_str());
2012 PyObject* identical_blocks_dict;
2013 if (!PyArg_ParseTuple(args,
"O", &identical_blocks_dict)) {
2016 if (!PyDict_Check(identical_blocks_dict)) {
2017 PyErr_SetString(PyExc_TypeError,
"Expected dictionary argument");
2022 if (base_decomp == NULL) {
2023 PyErr_SetString(PyExc_AttributeError,
"set_identical_blocks is only available for N_Qubit_Decomposition");
2026 std::map<int, int> identical_blocks_map;
2027 PyObject *
key, *value;
2029 while (PyDict_Next(identical_blocks_dict, &pos, &key, &value)) {
2030 if (!PyLong_Check(key) || !PyLong_Check(value)) {
2031 PyErr_SetString(PyExc_TypeError,
"Dictionary keys and values must be integers");
2034 int qubit_idx = PyLong_AsLong(key);
2035 int blocks = PyLong_AsLong(value);
2036 identical_blocks_map[qubit_idx] = blocks;
2040 }
catch (std::exception& e) {
2041 PyErr_SetString(PyExc_Exception, e.what());
2055 if (adaptive_decomp == NULL) {
2056 PyErr_SetString(PyExc_AttributeError,
"get_initial_circuit is only available for N_Qubit_Decomposition_adaptive");
2061 }
catch (std::exception& e) {
2062 PyErr_SetString(PyExc_Exception, e.what());
2076 if (adaptive_decomp == NULL) {
2077 PyErr_SetString(PyExc_AttributeError,
"compress_circuit is only available for N_Qubit_Decomposition_adaptive");
2082 }
catch (std::exception& e) {
2083 PyErr_SetString(PyExc_Exception, e.what());
2097 if (adaptive_decomp == NULL) {
2098 PyErr_SetString(PyExc_AttributeError,
"Remove_Trivial_CRY_Gates is only available for N_Qubit_Decomposition_adaptive");
2103 }
catch (std::string& err) {
2104 PyErr_SetString(PyExc_Exception, err.c_str());
2106 }
catch (std::exception& e) {
2107 PyErr_SetString(PyExc_Exception, e.what());
2121 if (adaptive_decomp == NULL) {
2122 PyErr_SetString(PyExc_AttributeError,
"finalize_circuit is only available for N_Qubit_Decomposition_adaptive");
2127 }
catch (std::exception& e) {
2128 PyErr_SetString(PyExc_Exception, e.what());
2141 PyObject* filename_py=NULL;
2143 if (!PyArg_ParseTuple(args,
"|O", &filename_py )) {
2147 PyObject* filename_string = PyObject_Str(filename_py);
2148 PyObject* filename_string_unicode = PyUnicode_AsEncodedString(filename_string,
"utf-8",
"~E~");
2149 const char* filename_C = PyBytes_AS_STRING(filename_string_unicode);
2150 std::string filename_str( filename_C );
2153 if (adaptive_decomp == NULL) {
2154 std::string err(
"set_Gate_Structure_From_Binary is only available for adaptive decomposition");
2155 PyErr_SetString(PyExc_Exception, err.c_str());
2160 catch (std::string err ) {
2161 PyErr_SetString(PyExc_Exception, err.c_str());
2165 std::string err(
"Invalid pointer to decomposition class");
2166 PyErr_SetString(PyExc_Exception, err.c_str());
2181 PyObject* filename_py = NULL;
2183 if (!PyArg_ParseTuple(args,
"|O", &filename_py)) {
2187 PyObject* filename_string = PyObject_Str(filename_py);
2188 PyObject* filename_string_unicode = PyUnicode_AsEncodedString(filename_string,
"utf-8",
"~E~");
2189 const char* filename_C = PyBytes_AS_STRING(filename_string_unicode);
2190 std::string filename_str(filename_C);
2193 if (adaptive_decomp == NULL) {
2194 PyErr_SetString(PyExc_AttributeError,
"add_Gate_Structure_From_Binary is only available for N_Qubit_Decomposition_adaptive");
2199 catch (std::string err) {
2200 PyErr_SetString(PyExc_Exception, err.c_str());
2204 std::string err(
"Invalid pointer to decomposition class");
2205 PyErr_SetString(PyExc_Exception, err.c_str());
2219 PyObject* filename_py = NULL;
2221 if (!PyArg_ParseTuple(args,
"|O", &filename_py)) {
2225 PyObject* filename_string = PyObject_Str(filename_py);
2226 PyObject* filename_string_unicode = PyUnicode_AsEncodedString(filename_string,
"utf-8",
"~E~");
2227 const char* filename_C = PyBytes_AS_STRING(filename_string_unicode);
2228 std::string filename_str(filename_C);
2231 if (adaptive_decomp == NULL) {
2232 PyErr_SetString(PyExc_AttributeError,
"set_Unitary_From_Binary is only available for N_Qubit_Decomposition_adaptive");
2237 catch (std::string err) {
2238 PyErr_SetString(PyExc_Exception, err.c_str());
2242 std::string err(
"Invalid pointer to decomposition class");
2243 PyErr_SetString(PyExc_Exception, err.c_str());
2257 if (adaptive_decomp == NULL) {
2258 PyErr_SetString(PyExc_AttributeError,
"add_Adaptive_Layers is only available for N_Qubit_Decomposition_adaptive");
2273 if (adaptive_decomp == NULL) {
2274 PyErr_SetString(PyExc_AttributeError,
"add_Layer_To_Imported_Gate_Structure is only available for N_Qubit_Decomposition_adaptive");
2290 if (adaptive_decomp == NULL) {
2291 PyErr_SetString(PyExc_AttributeError,
"apply_Imported_Gate_Structure is only available for N_Qubit_Decomposition_adaptive");
2296 catch (std::string err) {
2297 PyErr_SetString(PyExc_Exception, err.c_str());
2301 std::string err(
"Invalid pointer to decomposition class");
2302 PyErr_SetString(PyExc_Exception, err.c_str());
2319 if ( self->Umtx != NULL ) {
2321 Py_DECREF(self->Umtx);
2325 PyObject *Umtx_obj = NULL;
2327 if (!PyArg_ParseTuple(args,
"|O", &Umtx_obj )) {
2332 if ( Umtx_obj == NULL ) {
2333 PyErr_SetString(PyExc_Exception,
"Umtx argument in empty");
2339 bool Umtx_is_float32 =
false;
2341 extract_matrix_any(Umtx_obj, &self->Umtx, Umtx_mtx, Umtx_mtx_float, Umtx_is_float32);
2343 catch (std::exception& e) {
2344 PyErr_SetString(PyExc_Exception, e.what());
2350 if (Umtx_is_float32) {
2351 p->set_unitary(Umtx_mtx_float);
2354 p->set_unitary(Umtx_mtx);
2359 if (Umtx_is_float32) {
2360 p->set_unitary(Umtx_mtx_float);
2363 p->set_unitary(Umtx_mtx);
2368 if (Umtx_is_float32) {
2369 p->set_unitary(Umtx_mtx_float);
2372 p->set_unitary(Umtx_mtx);
2377 PyErr_SetString(PyExc_TypeError,
"set_unitary not available for this decomposition type");
2391 std::vector<Gate*>&& gates =
self->decomp->get_gates();
2392 Matrix_real&& params =
self->decomp->get_optimized_parameters();
2394 PyObject* gates_list = PyList_New(0);
2395 if (!gates_list)
return NULL;
2397 for (
size_t idx = 0; idx < gates.size(); idx++) {
2399 if (!gate)
continue;
2401 PyObject* gate_dict = PyDict_New();
2403 Py_DECREF(gates_list);
2408 const char* type_str =
nullptr;
2447 default: type_str =
"UNKNOWN";
break;
2449 PyDict_SetItemString(gate_dict,
"type", PyUnicode_FromString(type_str));
2451 PyDict_SetItemString(gate_dict,
"target_qbit", PyLong_FromLong(gate->
get_target_qbit()));
2454 if (control_qbit >= 0) {
2455 PyDict_SetItemString(gate_dict,
"control_qbit", PyLong_FromLong(control_qbit));
2461 if (pnum > 0 && pstart >= 0 && (pstart + pnum) <= (
int)params.
size()) {
2463 PyDict_SetItemString(gate_dict,
"Theta", PyFloat_FromDouble(params[pstart]));
2464 PyDict_SetItemString(gate_dict,
"Phi", PyFloat_FromDouble(params[pstart + 1]));
2465 PyDict_SetItemString(gate_dict,
"Lambda", PyFloat_FromDouble(params[pstart + 2]));
2467 PyDict_SetItemString(gate_dict,
"Theta", PyFloat_FromDouble(params[pstart]));
2469 PyDict_SetItemString(gate_dict,
"Phi", PyFloat_FromDouble(params[pstart]));
2473 PyList_Append(gates_list, gate_dict);
2474 Py_DECREF(gate_dict);
2487 PyObject* qiskit_io_module = PyImport_ImportModule(
"squander.IO_interfaces.Qiskit_IO");
2488 if (!qiskit_io_module) {
2489 PyErr_SetString(PyExc_ImportError,
"Failed to import squander.IO_interfaces.Qiskit_IO");
2494 PyObject* get_qiskit_func = PyObject_GetAttrString(qiskit_io_module,
"get_Qiskit_Circuit");
2495 Py_DECREF(qiskit_io_module);
2496 if (!get_qiskit_func) {
2497 PyErr_SetString(PyExc_AttributeError,
"get_Qiskit_Circuit not found in Qiskit_IO");
2504 Py_DECREF(get_qiskit_func);
2509 Py_DECREF(get_qiskit_func);
2515 PyObject*
args = PyTuple_Pack(2, circuit, parameters);
2516 PyObject*
result = PyObject_CallObject(get_qiskit_func, args);
2519 Py_DECREF(parameters);
2521 Py_DECREF(get_qiskit_func);
2531 #define CIRQ_ADD_SINGLE_QUBIT_GATE(name) do { \ 2532 PyObject* gate_func = PyObject_GetAttrString(cirq_module, #name); \ 2533 PyObject* gate_args = PyTuple_Pack(1, target_qubit); \ 2534 PyObject* cirq_gate = PyObject_CallObject(gate_func, gate_args); \ 2535 Py_DECREF(gate_args); Py_DECREF(gate_func); \ 2537 PyObject* append_args = PyTuple_Pack(1, cirq_gate); \ 2538 PyObject_CallObject(append_func, append_args); \ 2539 Py_DECREF(append_args); Py_DECREF(cirq_gate); \ 2544 #define CIRQ_ADD_TWO_QUBIT_GATE(name) do { \ 2545 PyObject* control_qbit_obj = PyDict_GetItemString(gate, "control_qbit"); \ 2546 if (!control_qbit_obj) continue; \ 2547 long control_idx = qbit_num - 1 - PyLong_AsLong(control_qbit_obj); \ 2548 PyObject* control_qubit = PyList_GetItem(qubits, control_idx); \ 2549 PyObject* gate_func = PyObject_GetAttrString(cirq_module, #name); \ 2550 PyObject* gate_args = PyTuple_Pack(2, control_qubit, target_qubit); \ 2551 PyObject* cirq_gate = PyObject_CallObject(gate_func, gate_args); \ 2552 Py_DECREF(gate_args); Py_DECREF(gate_func); \ 2554 PyObject* append_args = PyTuple_Pack(1, cirq_gate); \ 2555 PyObject_CallObject(append_func, append_args); \ 2556 Py_DECREF(append_args); Py_DECREF(cirq_gate); \ 2560 #define CIRQ_ADD_ROTATION_GATE(name, param) do { \ 2561 PyObject* param_obj = PyDict_GetItemString(gate, param); \ 2562 if (!param_obj) continue; \ 2563 PyObject* gate_func = PyObject_GetAttrString(cirq_module, #name); \ 2564 PyObject* gate_args = PyTuple_Pack(1, param_obj); \ 2565 PyObject* cirq_gate = PyObject_CallObject(gate_func, gate_args); \ 2566 Py_DECREF(gate_args); Py_DECREF(gate_func); \ 2568 PyObject* on_method = PyObject_GetAttrString(cirq_gate, "on"); \ 2569 PyObject* on_args = PyTuple_Pack(1, target_qubit); \ 2570 PyObject* gate_op = PyObject_CallObject(on_method, on_args); \ 2571 Py_DECREF(on_args); Py_DECREF(on_method); Py_DECREF(cirq_gate); \ 2573 PyObject* append_args = PyTuple_Pack(1, gate_op); \ 2574 PyObject_CallObject(append_func, append_args); \ 2575 Py_DECREF(append_args); Py_DECREF(gate_op); \ 2583 PyObject* cirq_module = PyImport_ImportModule(
"cirq");
2585 PyErr_SetString(PyExc_ImportError,
"Failed to import cirq. Please install cirq package.");
2589 PyObject* cirq_circuit_class = PyObject_GetAttrString(cirq_module,
"Circuit");
2590 if (!cirq_circuit_class) {
2591 Py_DECREF(cirq_module);
2595 PyObject* cirq_circuit_obj = PyObject_CallObject(cirq_circuit_class, NULL);
2596 Py_DECREF(cirq_circuit_class);
2597 if (!cirq_circuit_obj) {
2598 Py_DECREF(cirq_module);
2603 PyObject* cirq_line_qubit_class = PyObject_GetAttrString(cirq_module,
"LineQubit");
2604 if (!cirq_line_qubit_class) {
2605 Py_DECREF(cirq_circuit_obj);
2606 Py_DECREF(cirq_module);
2609 PyObject* range_func = PyObject_GetAttrString(cirq_line_qubit_class,
"range");
2610 Py_DECREF(cirq_line_qubit_class);
2612 Py_DECREF(cirq_circuit_obj);
2613 Py_DECREF(cirq_module);
2617 int qbit_num =
self->decomp->get_qbit_num();
2618 PyObject* range_args = PyTuple_Pack(1, PyLong_FromLong(qbit_num));
2619 PyObject*
qubits = PyObject_CallObject(range_func, range_args);
2620 Py_DECREF(range_args); Py_DECREF(range_func);
2622 Py_DECREF(cirq_circuit_obj);
2623 Py_DECREF(cirq_module);
2630 Py_DECREF(cirq_circuit_obj);
2631 Py_DECREF(cirq_module);
2635 PyObject* append_func = PyObject_GetAttrString(cirq_circuit_obj,
"append");
2637 Py_DECREF(gates_list); Py_DECREF(qubits); Py_DECREF(cirq_circuit_obj); Py_DECREF(cirq_module);
2641 PyObject* cirq_google_module = PyObject_GetAttrString(cirq_module,
"google");
2644 Py_ssize_t num_gates = PyList_Size(gates_list);
2645 for (Py_ssize_t idx = num_gates - 1; idx >= 0; idx--) {
2646 PyObject*
gate = PyList_GetItem(gates_list, idx);
2647 if (!gate)
continue;
2649 PyObject*
gate_type = PyDict_GetItemString(gate,
"type");
2650 if (!gate_type)
continue;
2651 const char* gate_type_str = PyUnicode_AsUTF8(gate_type);
2652 if (!gate_type_str)
continue;
2654 PyObject* target_qbit_obj = PyDict_GetItemString(gate,
"target_qbit");
2655 if (!target_qbit_obj)
continue;
2657 long target_idx = qbit_num - 1 - PyLong_AsLong(target_qbit_obj);
2658 PyObject* target_qubit = PyList_GetItem(qubits, target_idx);
2659 if (!target_qubit)
continue;
2664 else if (strcmp(gate_type_str,
"SYC") == 0 && cirq_google_module) {
2665 PyObject* control_qbit_obj = PyDict_GetItemString(gate,
"control_qbit");
2666 if (control_qbit_obj) {
2667 long control_idx = qbit_num - 1 - PyLong_AsLong(control_qbit_obj);
2668 PyObject* control_qubit = PyList_GetItem(qubits, control_idx);
2670 PyObject* syc_func = PyObject_GetAttrString(cirq_google_module,
"SYC");
2671 PyObject* syc_args = PyTuple_Pack(2, control_qubit, target_qubit);
2672 PyObject* cirq_gate = PyObject_CallObject(syc_func, syc_args);
2673 Py_DECREF(syc_args);
2674 Py_DECREF(syc_func);
2676 PyObject* append_args = PyTuple_Pack(1, cirq_gate);
2677 PyObject_CallObject(append_func, append_args);
2678 Py_DECREF(append_args);
2679 Py_DECREF(cirq_gate);
2683 else if (strcmp(gate_type_str,
"CRY") == 0) {
2684 printf(
"CRY gate needs to be implemented\n");
2686 else if (strcmp(gate_type_str,
"U3") == 0) {
2687 printf(
"Unsupported gate in the Cirq export: U3 gate\n");
2688 Py_XDECREF(cirq_google_module);
2689 Py_DECREF(append_func);
2690 Py_DECREF(gates_list);
2692 Py_DECREF(cirq_circuit_obj);
2693 Py_DECREF(cirq_module);
2705 Py_XDECREF(cirq_google_module);
2706 Py_DECREF(append_func);
2707 Py_DECREF(gates_list);
2709 Py_DECREF(cirq_module);
2711 return cirq_circuit_obj;
2714 #undef CIRQ_ADD_SINGLE_QUBIT_GATE 2715 #undef CIRQ_ADD_TWO_QUBIT_GATE 2716 #undef CIRQ_ADD_ROTATION_GATE 2727 PyObject* qiskit_io_module = PyImport_ImportModule(
"squander.IO_interfaces.Qiskit_IO");
2728 if (!qiskit_io_module) {
2729 PyErr_SetString(PyExc_ImportError,
"Failed to import squander.IO_interfaces.Qiskit_IO");
2734 PyObject* convert_func = PyObject_GetAttrString(qiskit_io_module,
"convert_Qiskit_to_Squander");
2735 Py_DECREF(qiskit_io_module);
2736 if (!convert_func) {
2737 PyErr_SetString(PyExc_AttributeError,
"convert_Qiskit_to_Squander not found in Qiskit_IO");
2741 PyObject* convert_args = PyTuple_Pack(1, qc_in);
2742 PyObject* convert_result = PyObject_CallObject(convert_func, convert_args);
2743 Py_DECREF(convert_args);
2744 Py_DECREF(convert_func);
2745 if (!convert_result || !PyTuple_Check(convert_result) || PyTuple_Size(convert_result) != 2) {
2746 Py_XDECREF(convert_result);
2747 PyErr_SetString(PyExc_ValueError,
"convert_Qiskit_to_Squander should return (circuit, parameters)");
2754 PyObject* set_gate_args = PyTuple_Pack(1, circuit_squander);
2756 Py_DECREF(set_gate_args);
2757 if (!set_gate_result) {
2758 Py_DECREF(convert_result);
2761 Py_DECREF(set_gate_result);
2764 PyObject* set_params_args = PyTuple_Pack(1,
parameters);
2766 Py_DECREF(set_params_args);
2767 Py_DECREF(convert_result);
2768 if (!set_params_result) {
2771 Py_DECREF(set_params_result);
2785 PyObject* qiskit_module = PyImport_ImportModule(
"qiskit");
2786 if (!qiskit_module) {
2787 PyErr_SetString(PyExc_ImportError,
"Failed to import qiskit");
2791 PyObject* transpile_func = PyObject_GetAttrString(qiskit_module,
"transpile");
2792 Py_DECREF(qiskit_module);
2793 if (!transpile_func) {
2794 PyErr_SetString(PyExc_AttributeError,
"transpile not found in qiskit");
2799 PyObject* basis_gates = PyList_New(2);
2800 PyList_SetItem(basis_gates, 0, PyUnicode_FromString(
"cz"));
2801 PyList_SetItem(basis_gates, 1, PyUnicode_FromString(
"u3"));
2803 PyObject* kwargs = PyDict_New();
2804 PyDict_SetItemString(kwargs,
"optimization_level", PyLong_FromLong(0));
2805 PyDict_SetItemString(kwargs,
"basis_gates", basis_gates);
2806 PyDict_SetItemString(kwargs,
"layout_method", PyUnicode_FromString(
"sabre"));
2808 PyObject* transpile_args = PyTuple_Pack(1, qc_in);
2809 PyObject*
qc = PyObject_Call(transpile_func, transpile_args, kwargs);
2811 Py_DECREF(transpile_args);
2813 Py_DECREF(basis_gates);
2814 Py_DECREF(transpile_func);
2820 PyObject* count_ops_func = PyObject_GetAttrString(qc,
"count_ops");
2821 if (count_ops_func) {
2822 PyObject* count_ops_result = PyObject_CallObject(count_ops_func, NULL);
2823 Py_DECREF(count_ops_func);
2824 if (count_ops_result) {
2825 printf(
"Gate counts in the imported Qiskit transpiled quantum circuit: ");
2826 PyObject_Print(count_ops_result, stdout, 0);
2828 Py_DECREF(count_ops_result);
2833 PyObject* qc_data_attr = PyObject_GetAttrString(qc,
"data");
2834 PyObject* qc_qubits_attr = PyObject_GetAttrString(qc,
"qubits");
2835 PyObject* qc_num_qubits_attr = PyObject_GetAttrString(qc,
"num_qubits");
2836 if (!qc_data_attr || !qc_qubits_attr || !qc_num_qubits_attr) {
2837 Py_XDECREF(qc_data_attr);
2838 Py_XDECREF(qc_qubits_attr);
2839 Py_XDECREF(qc_num_qubits_attr);
2844 int register_size = PyLong_AsLong(qc_num_qubits_attr);
2845 Py_DECREF(qc_num_qubits_attr);
2848 PyObject* circuit_wrapper_module = PyImport_ImportModule(
"squander.gates.qgd_Circuit_Wrapper");
2849 if (!circuit_wrapper_module) {
2850 Py_DECREF(qc_data_attr);
2851 Py_DECREF(qc_qubits_attr);
2856 PyObject* circuit_wrapper_class = PyObject_GetAttrString(circuit_wrapper_module,
"qgd_Circuit_Wrapper");
2857 Py_DECREF(circuit_wrapper_module);
2858 if (!circuit_wrapper_class) {
2859 Py_DECREF(qc_data_attr);
2860 Py_DECREF(qc_qubits_attr);
2866 PyObject* circuit_ret_args = PyTuple_Pack(1, PyLong_FromLong(register_size));
2867 PyObject* Circuit_ret_result = PyObject_CallObject(circuit_wrapper_class, circuit_ret_args);
2868 Py_DECREF(circuit_ret_args);
2869 Py_DECREF(circuit_wrapper_class);
2870 if (!Circuit_ret_result) {
2871 Py_DECREF(qc_data_attr);
2872 Py_DECREF(qc_qubits_attr);
2878 PyObject* single_qubit_gates = PyDict_New();
2879 for (
int idx = 0; idx < register_size; idx++) {
2880 PyObject*
key = PyLong_FromLong(idx);
2881 PyObject* value = PyList_New(0);
2882 PyDict_SetItem(single_qubit_gates, key, value);
2887 PyObject* optimized_parameters = PyList_New(0);
2890 Py_ssize_t qc_data_attr_size = PyList_Size(qc_data_attr);
2891 for (Py_ssize_t i = 0; i < qc_data_attr_size; i++) {
2892 PyObject*
gate = PyList_GetItem(qc_data_attr, i);
2893 PyObject* gate_operation = PyObject_GetAttrString(gate,
"operation");
2894 PyObject* gate_qubits = PyObject_GetAttrString(gate,
"qubits");
2895 if (!gate_operation || !gate_qubits) {
2896 Py_XDECREF(gate_operation);
2897 Py_XDECREF(gate_qubits);
2901 PyObject* gate_operation_name_attr = PyObject_GetAttrString(gate_operation,
"name");
2902 const char* name = PyUnicode_AsUTF8(gate_operation_name_attr);
2904 if (strcmp(name,
"u3") == 0) {
2906 PyObject* index_func = PyObject_GetAttrString(qc_qubits_attr,
"index");
2908 PyObject* index_args = PyTuple_Pack(1, PyList_GetItem(gate_qubits, 0));
2909 PyObject* index_result = PyObject_CallObject(index_func, index_args);
2910 Py_DECREF(index_func);
2911 Py_DECREF(index_args);
2913 long qubit = PyLong_AsLong(index_result);
2914 Py_DECREF(index_result);
2917 PyObject* gate_info_dict = PyDict_New();
2918 PyObject* gate_operation_params_attr = PyObject_GetAttrString(gate_operation,
"params");
2919 PyDict_SetItemString(gate_info_dict,
"params", gate_operation_params_attr);
2920 PyDict_SetItemString(gate_info_dict,
"type", PyUnicode_FromString(
"u3"));
2921 Py_DECREF(gate_operation_params_attr);
2923 PyObject*
qubit_list = PyDict_GetItem(single_qubit_gates, PyLong_FromLong(qubit));
2924 PyList_Append(qubit_list, gate_info_dict);
2925 Py_DECREF(gate_info_dict);
2926 }
else if (strcmp(name,
"cz") == 0) {
2928 PyObject* index_func = PyObject_GetAttrString(qc_qubits_attr,
"index");
2930 PyObject* index_args0 = PyTuple_Pack(1, PyList_GetItem(gate_qubits, 0));
2931 PyObject* index_args0_result = PyObject_CallObject(index_func, index_args0);
2932 Py_DECREF(index_args0);
2934 PyObject* index_args1 = PyTuple_Pack(1, PyList_GetItem(gate_qubits, 1));
2935 PyObject* index_args1_result = PyObject_CallObject(index_func, index_args1);
2936 Py_DECREF(index_args1);
2937 Py_DECREF(index_func);
2939 long qubit0 = PyLong_AsLong(index_args0_result);
2940 long qubit1 = PyLong_AsLong(index_args1_result);
2941 Py_DECREF(index_args0_result);
2942 Py_DECREF(index_args1_result);
2945 PyObject* layer_args = PyTuple_Pack(1, PyLong_FromLong(register_size));
2946 PyObject* circuit_wrapper_module2 = PyImport_ImportModule(
"squander.gates.qgd_Circuit_Wrapper");
2947 PyObject* circuit_wrapper_class2 = PyObject_GetAttrString(circuit_wrapper_module2,
"qgd_Circuit_Wrapper");
2948 Py_DECREF(circuit_wrapper_module2);
2950 PyObject*
Layer = PyObject_CallObject(circuit_wrapper_class2, layer_args);
2951 Py_DECREF(layer_args);
2952 Py_DECREF(circuit_wrapper_class2);
2955 PyObject* qubit0_list = PyDict_GetItem(single_qubit_gates, PyLong_FromLong(qubit0));
2956 if (qubit0_list && PyList_Size(qubit0_list) > 0) {
2957 PyObject* gate0 = PyList_GetItem(qubit0_list, 0);
2958 PyList_SetSlice(qubit0_list, 0, 1, NULL);
2960 PyObject* add_u3_func = PyObject_GetAttrString(Layer,
"add_U3");
2961 PyObject* add_u3_args =
Py_BuildValue(
"(iOOO)", qubit0, Py_True, Py_True, Py_True);
2962 PyObject_CallObject(add_u3_func, add_u3_args);
2963 Py_DECREF(add_u3_func);
2964 Py_DECREF(add_u3_args);
2967 PyObject* params = PyDict_GetItemString(gate0,
"params");
2968 PyObject* reversed_params = PyList_New(0);
2969 for (Py_ssize_t j = PyList_Size(params) - 1; j >= 0; j--) {
2970 PyList_Append(reversed_params, PyList_GetItem(params, j));
2972 for (Py_ssize_t j = 0; j < PyList_Size(reversed_params); j++) {
2973 PyList_Append(optimized_parameters, PyList_GetItem(reversed_params, j));
2975 Py_DECREF(reversed_params);
2978 Py_ssize_t last_idx = PyList_Size(optimized_parameters) - 1;
2979 PyObject* last_param = PyList_GetItem(optimized_parameters, last_idx);
2980 double val = PyFloat_AsDouble(last_param) / 2.0;
2981 PyList_SetItem(optimized_parameters, last_idx, PyFloat_FromDouble(val));
2985 PyObject* qubit1_list = PyDict_GetItem(single_qubit_gates, PyLong_FromLong(qubit1));
2986 if (qubit1_list && PyList_Size(qubit1_list) > 0) {
2987 PyObject* gate1 = PyList_GetItem(qubit1_list, 0);
2988 PyList_SetSlice(qubit1_list, 0, 1, NULL);
2990 PyObject* add_u3_func = PyObject_GetAttrString(Layer,
"add_U3");
2991 PyObject* u3_args =
Py_BuildValue(
"(iOOO)", qubit1, Py_True, Py_True, Py_True);
2992 PyObject_CallObject(add_u3_func, u3_args);
2993 Py_DECREF(add_u3_func);
2996 PyObject* params = PyDict_GetItemString(gate1,
"params");
2997 PyObject* reversed_params = PyList_New(0);
2998 for (Py_ssize_t j = PyList_Size(params) - 1; j >= 0; j--) {
2999 PyList_Append(reversed_params, PyList_GetItem(params, j));
3001 for (Py_ssize_t j = 0; j < PyList_Size(reversed_params); j++) {
3002 PyList_Append(optimized_parameters, PyList_GetItem(reversed_params, j));
3004 Py_DECREF(reversed_params);
3006 Py_ssize_t last_idx = PyList_Size(optimized_parameters) - 1;
3007 PyObject* last_param = PyList_GetItem(optimized_parameters, last_idx);
3008 double val = PyFloat_AsDouble(last_param) / 2.0;
3009 PyList_SetItem(optimized_parameters, last_idx, PyFloat_FromDouble(val));
3013 PyObject* qubit0_obj = PyLong_FromLong(qubit0);
3014 PyObject* qubit1_obj = PyLong_FromLong(qubit1);
3016 PyObject* add_rx_func = PyObject_GetAttrString(Layer,
"add_RX");
3017 PyObject* add_rx_arg = PyTuple_Pack(1, qubit0_obj);
3018 PyObject_CallObject(add_rx_func, add_rx_arg);
3019 Py_DECREF(add_rx_func);
3020 Py_DECREF(add_rx_arg);
3022 PyObject* add_adaptive_func = PyObject_GetAttrString(Layer,
"add_adaptive");
3023 PyObject* add_adaptive_args = PyTuple_Pack(2, qubit0_obj, qubit1_obj);
3024 PyObject_CallObject(add_adaptive_func, add_adaptive_args);
3025 Py_DECREF(add_adaptive_func);
3026 Py_DECREF(add_adaptive_args);
3028 PyObject* add_rz_func = PyObject_GetAttrString(Layer,
"add_RZ");
3029 PyObject* add_rz_arg = PyTuple_Pack(1, qubit1_obj);
3030 PyObject_CallObject(add_rz_func, add_rz_arg);
3031 Py_DECREF(add_rz_func);
3032 Py_DECREF(add_rz_arg);
3034 PyObject* add_rx_func_2 = PyObject_GetAttrString(Layer,
"add_RX");
3035 PyObject* add_rx_arg_2 = PyTuple_Pack(1, qubit0_obj);
3036 PyObject_CallObject(add_rx_func_2, add_rx_arg_2);
3037 Py_DECREF(add_rx_func_2);
3038 Py_DECREF(add_rx_arg_2);
3040 Py_DECREF(qubit0_obj);
3041 Py_DECREF(qubit1_obj);
3044 PyList_Append(optimized_parameters, PyFloat_FromDouble(
M_PI / 4.0));
3045 PyList_Append(optimized_parameters, PyFloat_FromDouble(
M_PI / 2.0));
3046 PyList_Append(optimized_parameters, PyFloat_FromDouble(-
M_PI / 2.0));
3047 PyList_Append(optimized_parameters, PyFloat_FromDouble(-
M_PI / 4.0));
3050 PyObject* add_circuit_func = PyObject_GetAttrString(Circuit_ret_result,
"add_Circuit");
3051 PyObject* add_circuit_args = PyTuple_Pack(1, Layer);
3052 PyObject_CallObject(add_circuit_func, add_circuit_args);
3053 Py_DECREF(add_circuit_func);
3054 Py_DECREF(add_circuit_args);
3057 Py_DECREF(gate_operation_name_attr);
3058 Py_DECREF(gate_operation);
3059 Py_DECREF(gate_qubits);
3063 PyObject* circuit_module = PyImport_ImportModule(
"squander.gates.qgd_Circuit");
3064 PyObject* circuit_class = PyObject_GetAttrString(circuit_module,
"qgd_Circuit");
3065 Py_DECREF(circuit_module);
3067 PyObject* final_layer_args = PyTuple_Pack(1, PyLong_FromLong(register_size));
3068 PyObject* final_layer_result = PyObject_CallObject(circuit_class, final_layer_args);
3069 Py_DECREF(circuit_class);
3070 Py_DECREF(final_layer_args);
3072 for (
int qubit = 0; qubit < register_size; qubit++) {
3073 PyObject* gates_list = PyDict_GetItem(single_qubit_gates, PyLong_FromLong(qubit));
3074 Py_ssize_t gates_list_size = PyList_Size(gates_list);
3076 for (Py_ssize_t j = 0; j < gates_list_size; j++) {
3077 PyObject* gate_obj = PyList_GetItem(gates_list, j);
3078 PyObject* gate_obj_type = PyDict_GetItemString(gate_obj,
"type");
3079 const char* gate_obj_type_str = PyUnicode_AsUTF8(gate_obj_type);
3081 if (strcmp(gate_obj_type_str,
"u3") == 0) {
3082 PyObject* add_u3_func = PyObject_GetAttrString(final_layer_result,
"add_U3");
3083 PyObject* add_u3_args =
Py_BuildValue(
"(iOOO)", qubit, Py_True, Py_True, Py_True);
3084 PyObject_CallObject(add_u3_func, add_u3_args);
3085 Py_DECREF(add_u3_func);
3086 Py_DECREF(add_u3_args);
3088 PyObject* gate_obj_params = PyDict_GetItemString(gate_obj,
"params");
3089 PyObject* reversed_params = PyList_New(0);
3090 for (Py_ssize_t
k = PyList_Size(gate_obj_params) - 1;
k >= 0;
k--) {
3091 PyList_Append(reversed_params, PyList_GetItem(gate_obj_params,
k));
3095 for (Py_ssize_t
k = 0;
k < PyList_Size(reversed_params);
k++) {
3096 PyObject* param = PyList_GetItem(reversed_params,
k);
3097 PyObject* param_float = PyFloat_FromDouble(PyFloat_AsDouble(param));
3098 PyList_Append(optimized_parameters, param_float);
3099 Py_DECREF(param_float);
3101 Py_DECREF(reversed_params);
3104 Py_ssize_t optimized_parameters_last_idx = PyList_Size(optimized_parameters) - 1;
3105 PyObject* optimized_parameters_last_param = PyList_GetItem(optimized_parameters, optimized_parameters_last_idx);
3106 double val = PyFloat_AsDouble(optimized_parameters_last_param) / 2.0;
3107 PyList_SetItem(optimized_parameters, optimized_parameters_last_idx, PyFloat_FromDouble(val));
3112 PyObject* add_final_circuit_func = PyObject_GetAttrString(Circuit_ret_result,
"add_Circuit");
3113 PyObject* add_final_circuit_args = PyTuple_Pack(1, final_layer_result);
3114 PyObject_CallObject(add_final_circuit_func, add_final_circuit_args);
3115 Py_DECREF(add_final_circuit_func);
3116 Py_DECREF(add_final_circuit_args);
3117 Py_DECREF(final_layer_result);
3120 PyObject* numpy_module = PyImport_ImportModule(
"numpy");
3121 PyObject* numpy_asarray_func = PyObject_GetAttrString(numpy_module,
"asarray");
3122 PyObject* numpy_flip_func = PyObject_GetAttrString(numpy_module,
"flip");
3123 Py_DECREF(numpy_module);
3125 PyObject* dtype_dict = PyDict_New();
3126 PyDict_SetItemString(dtype_dict,
"dtype", (PyObject*)&PyFloat_Type);
3127 PyObject* numpy_asarray_args = PyTuple_Pack(1, optimized_parameters);
3128 PyObject* numpy_asarray_result = PyObject_Call(numpy_asarray_func, numpy_asarray_args, dtype_dict);
3129 Py_DECREF(numpy_asarray_func);
3130 Py_DECREF(numpy_asarray_args);
3131 Py_DECREF(dtype_dict);
3133 PyObject* numpt_flip_args = PyTuple_Pack(2, numpy_asarray_result, PyLong_FromLong(0));
3134 PyObject* numpt_flip_result = PyObject_CallObject(numpy_flip_func, numpt_flip_args);
3135 Py_DECREF(numpy_flip_func);
3136 Py_DECREF(numpt_flip_args);
3137 Py_DECREF(numpy_asarray_result);
3140 PyObject* set_gate_structure_args = PyTuple_Pack(2, Circuit_ret_result, numpt_flip_result);
3142 Py_DECREF(set_gate_structure_args);
3143 Py_DECREF(Circuit_ret_result);
3144 Py_DECREF(numpt_flip_result);
3145 Py_DECREF(optimized_parameters);
3146 Py_DECREF(single_qubit_gates);
3147 Py_DECREF(qc_data_attr);
3148 Py_DECREF(qc_qubits_attr);
3150 if (!set_gate_structure_result) {
3153 Py_DECREF(set_gate_structure_result);
3166 PyObject* qc_in = NULL;
3167 if (!PyArg_ParseTuple(args,
"O", &qc_in)) {
3191 #define DECOMPOSITION_WRAPPER_BASE_METHODS \ 3192 {"Start_Decomposition", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_Start_Decomposition, METH_VARARGS | METH_KEYWORDS, \ 3193 "Method to start the decomposition"}, \ 3194 {"get_Gate_Num", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Gate_Num, METH_NOARGS, \ 3195 "Method to get the number of decomposing gates"}, \ 3196 {"get_Optimized_Parameters", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Optimized_Parameters, METH_NOARGS, \ 3197 "Method to get the array of optimized parameters"}, \ 3198 {"get_Circuit", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Circuit, METH_NOARGS, \ 3199 "Method to get the incorporated circuit"}, \ 3200 {"List_Gates", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_List_Gates, METH_NOARGS, \ 3201 "Call to print the decomposing unitaries on standard output"}, \ 3202 {"set_Max_Layer_Num", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Max_Layer_Num, METH_VARARGS, \ 3203 "Set the maximal number of layers used in the subdecomposition"}, \ 3204 {"set_Iteration_Loops", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Iteration_Loops, METH_VARARGS, \ 3205 "Set the number of iteration loops during the subdecomposition"}, \ 3206 {"set_Verbose", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Verbose, METH_VARARGS, \ 3207 "Set the verbosity of the decomposition class"}, \ 3208 {"set_Debugfile", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Debugfile, METH_VARARGS, \ 3209 "Set the debugfile name of the decomposition class"}, \ 3210 {"Reorder_Qubits", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_Reorder_Qubits, METH_VARARGS, \ 3211 "Method to reorder the qubits in the decomposition class"}, \ 3212 {"set_Optimization_Tolerance", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Optimization_Tolerance, METH_VARARGS, \ 3213 "Wrapper method to set the optimization tolerance"}, \ 3214 {"set_Convergence_Threshold", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Convergence_Threshold, METH_VARARGS, \ 3215 "Wrapper method to set the threshold of convergence"}, \ 3216 {"set_Optimization_Blocks", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Optimization_Blocks, METH_VARARGS, \ 3217 "Wrapper method to set the number of gate blocks to be optimized"}, \ 3218 {"get_Parameter_Num", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Parameter_Num, METH_NOARGS, \ 3219 "Get the number of free parameters"}, \ 3220 {"set_Optimized_Parameters", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Optimized_Parameters, METH_VARARGS, \ 3221 "Set the optimized parameters"}, \ 3222 {"get_Num_of_Iters", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Num_of_Iters, METH_NOARGS, \ 3223 "Get the number of iterations"}, \ 3224 {"export_Unitary", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_export_Unitary, METH_VARARGS, \ 3225 "Export unitary matrix"}, \ 3226 {"export_Gate_Structure_to_Binary", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_export_Gate_Structure_to_Binary, METH_VARARGS, \ 3227 "Export the current gate structure and optimized parameters into Squander binary format"}, \ 3228 {"get_Project_Name", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Project_Name, METH_NOARGS, \ 3229 "Get the name of SQUANDER project"}, \ 3230 {"set_Project_Name", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Project_Name, METH_VARARGS, \ 3231 "Set the name of SQUANDER project"}, \ 3232 {"get_Global_Phase", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Global_Phase, METH_NOARGS, \ 3233 "Call to get global phase"}, \ 3234 {"set_Global_Phase", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Global_Phase, METH_VARARGS, \ 3235 "Set global phase"}, \ 3236 {"apply_Global_Phase_Factor", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_apply_Global_Phase_Factor, METH_NOARGS, \ 3237 "Apply global phase factor"}, \ 3238 {"get_Unitary", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Unitary, METH_NOARGS, \ 3239 "Get Unitary Matrix"}, \ 3240 {"set_Optimizer", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Optimizer, METH_VARARGS | METH_KEYWORDS, \ 3241 "Set the optimizer method"}, \ 3242 {"set_Max_Iterations", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Max_Iterations, METH_VARARGS | METH_KEYWORDS, \ 3243 "Set the number of maximum iterations"}, \ 3244 {"get_Matrix", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Matrix, METH_VARARGS | METH_KEYWORDS, \ 3245 "Method to retrieve the unitary of the circuit"}, \ 3246 {"set_Cost_Function_Variant", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Cost_Function_Variant, METH_VARARGS | METH_KEYWORDS, \ 3247 "Set the cost function variant"}, \ 3248 {"Optimization_Problem", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_Optimization_Problem, METH_VARARGS, \ 3249 "Optimization problem method"}, \ 3250 {"Optimization_Problem_Combined_Unitary", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_Optimization_Problem_Combined_Unitary, METH_VARARGS, \ 3251 "Optimization problem combined unitary method"}, \ 3252 {"Optimization_Problem_Grad", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_Optimization_Problem_Grad, METH_VARARGS, \ 3253 "Optimization problem gradient method"}, \ 3254 {"Optimization_Problem_Combined", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_Optimization_Problem_Combined, METH_VARARGS, \ 3255 "Optimization problem combined method"}, \ 3256 {"Optimization_Problem_Batch", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_Optimization_Problem_Batch, METH_VARARGS, \ 3257 "Optimization problem batch method"}, \ 3258 {"Upload_Umtx_to_DFE", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_Upload_Umtx_to_DFE, METH_NOARGS, \ 3259 "Upload unitary matrix to DFE"}, \ 3260 {"get_Trace_Offset", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Trace_Offset, METH_NOARGS, \ 3261 "Get trace offset"}, \ 3262 {"set_Trace_Offset", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Trace_Offset, METH_VARARGS | METH_KEYWORDS, \ 3263 "Set trace offset"}, \ 3264 {"get_Decomposition_Error", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Decomposition_Error, METH_NOARGS, \ 3265 "Get decomposition error"}, \ 3266 {"get_Second_Renyi_Entropy", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Second_Renyi_Entropy, METH_VARARGS, \ 3267 "Get second Renyi entropy"}, \ 3268 {"get_Qbit_Num", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Qbit_Num, METH_NOARGS, \ 3269 "Get the number of qubits"}, \ 3270 {"set_Gate_Structure", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Gate_Structure, METH_VARARGS, \ 3271 "Set custom gate structure for decomposition: set_Gate_Structure(circuit)"}, \ 3272 {"add_Finalyzing_Layer_To_Gate_Structure", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_add_Finalyzing_Layer_To_Gate_Structure, METH_NOARGS, \ 3273 "Add finalizing layer to gate structure"}, \ 3274 {"get_Gates", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Gates, METH_NOARGS, \ 3275 "Get gates as a list of dictionaries"}, \ 3276 {"get_Qiskit_Circuit", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Qiskit_Circuit, METH_NOARGS, \ 3277 "Export decomposition to Qiskit QuantumCircuit format"}, \ 3278 {"get_Cirq_Circuit", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Cirq_Circuit, METH_NOARGS, \ 3279 "Export decomposition to Cirq Circuit format"}, \ 3280 {"import_Qiskit_Circuit", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_import_Qiskit_Circuit, METH_VARARGS, \ 3281 "Import Qiskit QuantumCircuit"}, \ 3290 "Set the number of identical successive blocks during subdecomposition"},
3300 "Method to get initial circuit in decomposition"},
3302 "Method to compress gate structure"},
3304 "Method to remove blocks containing a trivial CRY gate (near identity); U3 gates are merged with subsequent gates"},
3306 "Method to finalize the decomposition"},
3308 "Set gate structure from binary"},
3310 "Add gate structure from binary"},
3312 "Set unitary from binary"},
3314 "Call to add adaptive layers to the gate structure"},
3316 "Add layer to imported gate structure"},
3318 "Apply imported gate structure"},
3320 "Call to set unitary matrix"},
3338 "Call to set unitary matrix"},
3348 "Call to set unitary matrix"},
3352 #define decomposition_wrapper_type_template(decomp_class) \ 3353 static PyTypeObject qgd_##decomp_class##_Wrapper_Type = { \ 3354 PyVarObject_HEAD_INIT(NULL, 0) \ 3355 "qgd_N_Qubit_Decomposition_Wrapper." #decomp_class, \ 3356 sizeof(qgd_N_Qubit_Decomposition_Wrapper), \ 3358 (destructor) qgd_N_Qubit_Decomposition_Wrapper_dealloc, \ 3373 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, \ 3374 #decomp_class " decomposition wrapper", \ 3381 qgd_##decomp_class##_methods, \ 3389 (initproc) qgd_##decomp_class##_Wrapper_init, \ 3391 (newfunc) qgd_N_Qubit_Decomposition_Wrapper_new, \ 3416 static PyModuleDef qgd_N_Qubit_Decompositions_Wrapper_Module = {
3417 PyModuleDef_HEAD_INIT,
3418 "qgd_N_Qubit_Decompositions_Wrapper",
3419 "Python binding for N-Qubit Decompositions wrapper module",
3428 #define Py_INCREF_template(decomp_name) \ 3429 Py_INCREF(&qgd_##decomp_name##_Wrapper_Type); \ 3430 if (PyModule_AddObject(m, "qgd_" #decomp_name, (PyObject *) &qgd_##decomp_name##_Wrapper_Type) < 0) { \ 3431 Py_DECREF(&qgd_##decomp_name##_Wrapper_Type); \ 3447 if (PyType_Ready(&qgd_N_Qubit_Decomposition_Wrapper_Type) < 0 ||
3448 PyType_Ready(&qgd_N_Qubit_Decomposition_adaptive_Wrapper_Type) < 0 ||
3449 PyType_Ready(&qgd_N_Qubit_Decomposition_custom_Wrapper_Type) < 0 ||
3450 PyType_Ready(&qgd_N_Qubit_Decomposition_Tree_Search_Wrapper_Type) < 0 ||
3451 PyType_Ready(&qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Type) < 0) {
3455 m = PyModule_Create(&qgd_N_Qubit_Decompositions_Wrapper_Module);
Gates_block * get_flat_circuit()
Method to generate a flat circuit.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Max_Layer_Num(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Set the maximal number of layers used in the subdecomposition of the qbit-th qubit.
parameter_num
[set adaptive gate structure]
Class to store single-precision real arrays and properties.
Matrix_float to_float32() const
Convert to single precision.
void release_decomposition(DecompT *instance)
Deallocate decomposition instance.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_List_Gates(qgd_N_Qubit_Decomposition_Wrapper *self)
Call to list the gates decomposing the unitary.
void add_adaptive_layers()
Call to add adaptive layers to the gate structure stored by the class.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Optimization_Blocks(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Wrapper method to set the number of gate blocks to be optimized.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_apply_Global_Phase_Factor(qgd_N_Qubit_Decomposition_Wrapper *self)
Apply global phase factor to the unitary matrix.
int stride
The column stride of the array. (The array elements in one row are a_0, a_1, ... a_{cols-1}, 0, 0, 0, 0. The number of zeros is stride-cols)
Matrix to_float64() const
Convert to double precision.
A base class to determine the decomposition of an N-qubit unitary into a sequence of CNOT and U3 gate...
return Py_BuildValue("i", 0)
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_import_Qiskit_Circuit_adaptive(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *qc_in)
Method to import Qiskit circuit (adaptive-specific version with custom CZ decomposition) ...
Matrix_real numpy2matrix_real(PyArrayObject *arr)
Call to create a PIC matrix_real representation of a numpy array.
static int qgd_N_Qubit_Decomposition_custom_Wrapper_init(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args, PyObject *kwds)
#define DECOMPOSITION_WRAPPER_BASE_METHODS
Base methods shared by all decomposition types These methods are available for all decomposition clas...
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_get_Num_of_Iters(qgd_N_Qubit_Decomposition_Wrapper *self)
Get the number of free parameters in the gate structure used for the decomposition.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_add_Gate_Structure_From_Binary(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Wrapper function to append custom layers to the gate structure from binary file.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Optimized_Parameters(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Extract the optimized parameters.
virtual void remove_trivial_CRY_gates()
Remove blocks containing a trivial CRY gate from the circuit stored by the class. ...
PyMODINIT_FUNC PyInit_qgd_N_Qubit_Decompositions_Wrapper(void)
Method called when the Python module is initialized.
Header file for a class responsible for grouping gates into subcircuits. (Subcircuits can be nested) ...
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_Optimization_Problem(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Call to evaluate the optimization problem (cost function)
PyObject * matrix_real_to_numpy(Matrix_real &mtx)
Call to make a numpy array from an instance of matrix class.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Iteration_Loops(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Set the number of iteration loops during the subdecomposition of the qbit-th qubit.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_get_Unitary(qgd_N_Qubit_Decomposition_Wrapper *self)
Call to get the unitary matrix.
U3 RX RZ H Y SX S T CNOT CH SYC CRZ PyObject PyObject * kwds
A class describing a universal configuration element.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_get_Trace_Offset(qgd_N_Qubit_Decomposition_Wrapper *self)
Get trace offset of the compression.
#define Py_INCREF_template(decomp_name)
Optimization_Interface * decomp
An object to decompose the unitary.
Matrix_real_float numpy2matrix_real_float(PyArrayObject *arr)
Call to create a PIC matrix_real_float representation of a numpy array.
Matrix_real parameters_float_to_double(Matrix_real_float ¶meters32)
A base class to determine the decomposition of an N-qubit unitary into a sequence of CNOT and U3 gate...
scalar * get_data() const
Call to get the pointer to the stored data.
static int qgd_N_Qubit_Decomposition_adaptive_Wrapper_init(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args, PyObject *kwds)
guess_type extract_guess_type(PyObject *initial_guess)
Extract guess_type from Python string/object.
static PyMethodDef qgd_N_Qubit_Decomposition_Tree_Search_methods[]
Method table for N_Qubit_Decomposition_Tree_Search.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_get_Global_Phase(qgd_N_Qubit_Decomposition_Wrapper *self)
Call to get the global phase factor (returns the angle of the global phase)
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_add_Layer_To_Imported_Gate_Structure(qgd_N_Qubit_Decomposition_Wrapper *self)
Wrapper method to add layer to imported gate structure.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Project_Name(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Call to set the project name.
A class representing a CZ operation.
optimization_aglorithms
implemented optimization strategies
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Gate_Structure(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Wrapper function to set custom gate structure for the decomposition.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Trace_Offset(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args, PyObject *kwds)
Set trace offset for the compression.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Identical_Blocks(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Set the number of identical successive blocks (N_Qubit_Decomposition only)
A base class to determine the decomposition of an N-qubit unitary into a sequence of CNOT and U3 gate...
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_get_Matrix(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args, PyObject *kwds)
Call to get the matrix representation of the circuit with given parameters.
static int qgd_N_Qubit_Decomposition_Tree_Search_Wrapper_init(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args, PyObject *kwds)
U3 RX RZ H Y SX S T CNOT CH SYC CRZ PyObject * args
int rows
The number of rows.
A class representing a CH operation.
int cols
The number of columns.
PyObject_HEAD Gates_block * gate
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_Start_Decomposition(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args, PyObject *kwds)
Wrapper function to call the start_decomposition method of C++ class N_Qubit_Decomposition.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_add_Finalyzing_Layer_To_Gate_Structure(qgd_N_Qubit_Decomposition_Wrapper *self)
Wrapper function to add finalyzing layer (single qubit rotations on all qubits) to the gate structure...
void apply_imported_gate_structure()
Call to apply the imported gate structure on the unitary.
void set_custom_gate_structure(std::map< int, Gates_block *> gate_structure_in)
Call to set custom layers to the gate structure that are intended to be used in the subdecomposition...
void set_unitary_from_file(std::string filename)
Set unitary matrix from file.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_Remove_Trivial_CRY_Gates(qgd_N_Qubit_Decomposition_Wrapper *self)
Call to remove blocks containing a trivial CRY gate (near identity); U3 gates are merged with subsequ...
PyObject * matrix_real_float_to_numpy(Matrix_real_float &mtx)
Call to make a numpy array from an instance of matrix_real_float class.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_import_Qiskit_Circuit_standard(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *qc_in)
Method to import Qiskit circuit (standard version for non-adaptive decompositions) ...
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_Finalize_Circuit(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args, PyObject *kwds)
Call to finalize circuit.
void set_adaptive_gate_structure(std::string filename)
Call to set custom layers to the gate structure that are intended to be used in the decomposition...
static int qgd_N_Qubit_Decomposition_Wrapper_init(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args, PyObject *kwds)
static PyMethodDef qgd_N_Qubit_Decomposition_Tabu_Search_methods[]
Method table for N_Qubit_Decomposition_Tabu_Search.
std::map< std::string, Config_Element > extract_config(PyObject *config_arg)
Extract config dictionary.
gate_type get_type()
Call to get the type of the operation.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_get_Gate_Num(qgd_N_Qubit_Decomposition_Wrapper *self)
Call to get the number of gates.
Umtx
The unitary to be decomposed.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_Optimization_Problem_Grad(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Call to evaluate the gradient of the optimization problem.
A base class to determine the decomposition of an N-qubit unitary into a sequence of CNOT and U3 gate...
Header file for a class implementing the adaptive gate decomposition algorithm of arXiv:2203...
static PyMethodDef qgd_N_Qubit_Decomposition_adaptive_methods[]
Method table for N_Qubit_Decomposition_adaptive.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_get_Initial_Circuit(qgd_N_Qubit_Decomposition_Wrapper *self)
Call to get initial circuit.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_Optimization_Problem_Combined_Unitary(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Call to evaluate the optimization problem with unitary and derivatives.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Global_Phase(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Call to set the global phase.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_Reorder_Qubits(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Method to reorder the qubits in the decomposition class.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_get_Cirq_Circuit(qgd_N_Qubit_Decomposition_Wrapper *self)
int get_parameter_start_idx()
Call to get the starting index of the parameters in the parameter array corresponding to the circuit ...
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Max_Iterations(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Set the number of maximum iterations for optimization.
static int search_wrapper_init(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args, PyObject *kwds)
virtual void compress_circuit()
Compress the circuit.
#define CIRQ_ADD_TWO_QUBIT_GATE(name)
void set_owner(bool owner_in)
Call to set the current class instance to be (or not to be) the owner of the stored data array...
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Unitary_From_Binary(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Wrapper function to set unitary from binary file.
Structure type representing complex numbers in the SQUANDER package.
A class representing a CNOT operation.
void add_adaptive_gate_structure(std::string filename)
Call to append custom layers to the gate structure that are intended to be used in the decomposition...
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_apply_Imported_Gate_Structure(qgd_N_Qubit_Decomposition_Wrapper *self)
Wrapper function to apply the imported gate structure on the unitary.
A base class to determine the decomposition of an N-qubit unitary into a sequence of CNOT and U3 gate...
virtual void get_initial_circuit()
get initial circuit
Matrix copy() const
Call to create a copy of the matrix.
PyObject_HEAD PyArrayObject * Umtx
pointer to the unitary to be decomposed to keep it alive
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_get_Project_Name(qgd_N_Qubit_Decomposition_Wrapper *self)
Call to get the project name.
static void qgd_N_Qubit_Decomposition_Wrapper_dealloc(qgd_N_Qubit_Decomposition_Wrapper *self)
Called when Python object is destroyed.
Double-precision complex matrix (float64).
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Cost_Function_Variant(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args, PyObject *kwds)
Call to set the cost function variant.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Debugfile(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Set the debugfile name of the decomposition class.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_Optimization_Problem_Combined(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Call to evaluate the optimization problem with cost and gradient combined.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_get_Circuit(qgd_N_Qubit_Decomposition_Wrapper *self)
Call to get the incorporated circuit.
int size() const
Call to get the number of the allocated elements.
Matrix_float numpy2matrix_float(PyArrayObject *arr)
Call to create a PIC matrix_float representation of a numpy array.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Allocate memory for new Python object.
virtual int get_parameter_num()
Call to get the number of free parameters.
cost_function_type
Type definition of the different types of the cost function.
A class responsible for grouping two-qubit (CNOT,CZ,CH) and one-qubit gates into layers.
Header file for a class implementing the adaptive gate decomposition algorithm of arXiv:2203...
virtual void finalize_circuit()
Finalize the circuit.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_get_Qiskit_Circuit(qgd_N_Qubit_Decomposition_Wrapper *self)
Method to get Qiskit circuit representation.
Single-precision complex matrix (float32).
guess_type
Type definition of the types of the initial guess.
void add_layer_to_imported_gate_structure()
Call to add an adaptive layer to the gate structure previously imported gate structure.
#define CIRQ_ADD_SINGLE_QUBIT_GATE(name)
Method to get Cirq circuit representation.
int get_target_qbit()
Call to get the index of the target qubit.
static bool config_requests_float(std::map< std::string, Config_Element > &config)
void set_property(std::string name_, double val_)
Call to set a double value.
dictionary gate_structure
static int qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_init(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args, PyObject *kwds)
Base class for the representation of general gate operations.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Optimization_Tolerance(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Wrapper method to set the optimization tolerance.
PyObject * matrix_float_to_numpy(Matrix_float &mtx)
Call to make a numpy array from an instance of matrix_float class.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_get_Decomposition_Error(qgd_N_Qubit_Decomposition_Wrapper *self)
Get the error of the decomposition.
std::vector< matrix_base< int > > extract_topology(PyObject *topology)
Extract topology list from Python.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_Compress_Circuit(qgd_N_Qubit_Decomposition_Wrapper *self)
Call to compress circuit.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Verbose(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Set the verbosity of the decomposition class.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_export_Gate_Structure_to_Binary(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Export the current gate structure and optimized parameters into Squander binary format.
Matrix numpy2matrix(PyArrayObject *arr)
Call to create a PIC matrix representation of a numpy array.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_get_Gates(qgd_N_Qubit_Decomposition_Wrapper *self)
Method to get gates as a list of dictionaries (with parameters from optimized_parameters array) ...
PyObject_HEAD Gates_block * circuit
Pointer to the C++ class of the base Gate_block module.
void export_gate_list_to_binary(Matrix_real ¶meters, Gates_block *gates_block, const std::string &filename, int verbosity)
Use to export a quantum circuit into binary format.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_add_Adaptive_Layers(qgd_N_Qubit_Decomposition_Wrapper *self)
Wrapper method to add adaptive layers to the gate structure stored by the class.
double real
the real part of a complex number
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_export_Unitary(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Export unitary matrix to binary file.
Header file for a class implementing the adaptive gate decomposition algorithm of arXiv:2203...
dictionary iteration_loops
#define CIRQ_ADD_ROTATION_GATE(name, param)
#define decomposition_wrapper_type_template(decomp_class)
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_get_Second_Renyi_Entropy(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Get second Renyi entropy.
int get_qbit_num()
Call to get the number of qubits composing the unitary.
void extract_parameters_any(PyObject *parameters_arg, PyArrayObject **store_ref, Matrix_real ¶meters64, Matrix_real_float ¶meters32, bool &is_float32)
Extract real float32/float64 parameters without forced precision conversion.
gate_type
Type definition of operation types (also generalized for decomposition classes derived from the class...
Type definition for qgd_Circuit_Wrapper.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Optimizer(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args, PyObject *kwds)
Call to set the optimizer algorithm.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_get_Parameter_Num(qgd_N_Qubit_Decomposition_Wrapper *self)
Get the number of free parameters in the gate structure used for the decomposition.
static PyMethodDef qgd_N_Qubit_Decomposition_custom_methods[]
Method table for N_Qubit_Decomposition_custom.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Convergence_Threshold(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Wrapper method to set the threshold of convergence.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_get_Optimized_Parameters(qgd_N_Qubit_Decomposition_Wrapper *self)
Call to get the optimized parameters.
Header file for a class to determine the decomposition of an N-qubit unitary into a sequence of CNOT ...
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_import_Qiskit_Circuit(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Method to import Qiskit circuit.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Gate_Structure_From_Binary(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Wrapper function to set custom layers to the gate structure that are intended to be used in the decom...
Matrix extract_matrix(PyObject *Umtx_arg, PyArrayObject **store_ref)
Extract and validate Matrix from numpy array.
int set_identical_blocks(int n, int identical_blocks_in)
Set the number of identical successive blocks during the subdecomposition of the n-th qubit...
PyObject * matrix_to_numpy(Matrix &mtx)
Call to make a numpy array from an instance of matrix class.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_Optimization_Problem_Batch(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Call to evaluate the optimization problem for batched parameters.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_Upload_Umtx_to_DFE(qgd_N_Qubit_Decomposition_Wrapper *self)
Upload unitary matrix to DFE.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_get_Qbit_Num(qgd_N_Qubit_Decomposition_Wrapper *self)
Get the number of qubits.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Unitary(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Call to set unitary matrix.
Type definition of the unified N-Qubit Decomposition wrapper.
Matrix_float copy() const
Call to create a copy of the matrix.
static PyMethodDef qgd_N_Qubit_Decomposition_methods[]
Method table for base N_Qubit_Decomposition.
int get_control_qbit()
Call to get the index of the control qubit.
Class to store data of complex arrays and its properties.
A base class to determine the decomposition of an N-qubit unitary into a sequence of CNOT and U3 gate...
void extract_matrix_any(PyObject *matrix_arg, PyArrayObject **store_ref, Matrix &matrix64, Matrix_float &matrix32, bool &is_float32)
Extract complex64/complex128 numpy input without rejecting float32 callers.
double imag
the imaginary part of a complex number