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;
905 if (!PyArg_ParseTuple(args,
"|O", &gate_structure_py)) {
910 if (PyDict_Check(gate_structure_py)) {
911 PyObject *
key = NULL, *value = NULL;
915 while (PyDict_Next(gate_structure_py, &pos, &key, &value)) {
917 if (!PyLong_Check(key)) {
918 PyErr_SetString(PyExc_TypeError,
"Dictionary keys must be integers");
921 int key_int = (
int)PyLong_AsLong(key);
924 gate_structure.insert(std::pair<int, Gates_block*>(key_int, qgd_op_block->
gate));
929 if (base_decomp != NULL) {
933 }
catch (std::string err) {
934 PyErr_SetString(PyExc_Exception, err.c_str());
936 }
catch (std::exception& e) {
937 PyErr_SetString(PyExc_Exception, e.what());
940 std::string err(
"Invalid pointer to decomposition class");
941 PyErr_SetString(PyExc_Exception, err.c_str());
945 PyErr_SetString(PyExc_AttributeError,
"Dictionary-based set_Gate_Structure is only available for N_Qubit_Decomposition");
951 self->decomp->set_custom_gate_structure(qgd_op_block->
gate);
953 }
catch (std::string err) {
954 PyErr_SetString(PyExc_Exception, err.c_str());
956 }
catch (std::exception& e) {
957 PyErr_SetString(PyExc_Exception, e.what());
960 std::string err(
"Invalid pointer to decomposition class");
961 PyErr_SetString(PyExc_Exception, err.c_str());
985 PyObject* parameters_obj = NULL;
986 PyArrayObject* parameters_arr = NULL;
988 if (!PyArg_ParseTuple(args,
"|O", ¶meters_obj )) {
994 bool parameters_is_float32 =
false;
996 extract_parameters_any(parameters_obj, ¶meters_arr, parameters_mtx, parameters_mtx_float, parameters_is_float32);
997 if (parameters_is_float32) {
1000 self->decomp->set_optimized_parameters(parameters_mtx.
get_data(), parameters_mtx.
size());
1002 catch (std::string err ) {
1003 PyErr_SetString(PyExc_Exception, err.c_str());
1007 std::string err(
"Invalid pointer to decomposition class");
1008 PyErr_SetString(PyExc_Exception, err.c_str());
1011 Py_DECREF(parameters_arr);
1023 int number_of_iters =
self->decomp->get_num_iters();
1039 if (!PyArg_ParseTuple(args,
"|O", &filename)) {
1042 PyObject* filename_string = PyObject_Str(filename);
1043 PyObject* filename_unicode = PyUnicode_AsEncodedString(filename_string,
"utf-8",
"~E~");
1044 const char* filename_C = PyBytes_AS_STRING(filename_unicode);
1045 std::string filename_str(filename_C);
1047 self->decomp->export_unitary(filename_str);
1060 std::string
project_name =
self->decomp->get_project_name();
1061 return PyUnicode_FromString(project_name.c_str());
1062 }
catch (std::exception& e) {
1063 PyErr_SetString(PyExc_Exception, e.what());
1078 PyObject* project_name_new = NULL;
1080 if (!PyArg_ParseTuple(args,
"|O", &project_name_new)) {
1083 PyObject* project_name_new_string = PyObject_Str(project_name_new);
1084 PyObject* project_name_new_unicode = PyUnicode_AsEncodedString(project_name_new_string,
"utf-8",
"~E~");
1085 const char* project_name_new_C = PyBytes_AS_STRING(project_name_new_unicode);
1086 std::string project_name_new_str(project_name_new_C);
1088 self->decomp->set_project_name(project_name_new_str);
1100 QGD_Complex16 global_phase_factor_C =
self->decomp->get_global_phase_factor();
1101 PyObject* global_phase = PyFloat_FromDouble(std::atan2(global_phase_factor_C.
imag, global_phase_factor_C.
real));
1102 return global_phase;
1115 if (!PyArg_ParseTuple(args,
"d", &phase_angle)) {
1119 self->decomp->set_global_phase(phase_angle);
1121 }
catch (std::exception& e) {
1122 PyErr_SetString(PyExc_Exception, e.what());
1136 self->decomp->apply_global_phase_factor();
1138 }
catch (std::exception& e) {
1139 PyErr_SetString(PyExc_Exception, e.what());
1152 if (self->decomp->get_use_float()) {
1155 Unitary_mtx =
self->decomp->get_Umtx_float().
copy();
1157 catch (std::string err) {
1158 PyErr_SetString(PyExc_Exception, err.c_str());
1162 std::string err(
"Invalid pointer to decomposition class");
1163 PyErr_SetString(PyExc_Exception, err.c_str());
1172 Unitary_mtx =
self->decomp->get_Umtx().
copy();
1174 catch (std::string err) {
1175 PyErr_SetString(PyExc_Exception, err.c_str());
1179 std::string err(
"Invalid pointer to decomposition class");
1180 PyErr_SetString(PyExc_Exception, err.c_str());
1200 static char *kwlist[] = {(
char*)
"optimizer", NULL};
1202 PyObject* optimizer_arg = NULL;
1205 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|O", kwlist, &optimizer_arg)) {
1206 std::string err(
"Unsuccessful argument parsing");
1207 PyErr_SetString(PyExc_Exception, err.c_str());
1211 if (optimizer_arg == NULL) {
1212 std::string err(
"optimizer argument not set");
1213 PyErr_SetString(PyExc_Exception, err.c_str());
1217 PyObject* optimizer_string = PyObject_Str(optimizer_arg);
1218 PyObject* optimizer_string_unicode = PyUnicode_AsEncodedString(optimizer_string,
"utf-8",
"~E~");
1219 const char* optimizer_C = PyBytes_AS_STRING(optimizer_string_unicode);
1222 if (strcmp(
"bfgs", optimizer_C) == 0 || strcmp(
"BFGS", optimizer_C) == 0) {
1223 qgd_optimizer =
BFGS;
1225 else if (strcmp(
"adam", optimizer_C) == 0 || strcmp(
"ADAM", optimizer_C) == 0) {
1226 qgd_optimizer =
ADAM;
1228 else if (strcmp(
"grad_descend", optimizer_C) == 0 || strcmp(
"GRAD_DESCEND", optimizer_C) == 0) {
1231 else if (strcmp(
"adam_batched", optimizer_C) == 0 || strcmp(
"ADAM_BATCHED", optimizer_C) == 0) {
1234 else if (strcmp(
"bfgs2", optimizer_C) == 0 || strcmp(
"BFGS2", optimizer_C) == 0) {
1235 qgd_optimizer =
BFGS2;
1237 else if (strcmp(
"agents", optimizer_C) == 0 || strcmp(
"AGENTS", optimizer_C) == 0) {
1240 else if (strcmp(
"cosine", optimizer_C) == 0 || strcmp(
"COSINE", optimizer_C) == 0) {
1243 else if (strcmp(
"grad_descend_phase_shift_rule", optimizer_C) == 0 || strcmp(
"GRAD_DESCEND_PARAMETER_SHIFT_RULE", optimizer_C) == 0) {
1246 else if (strcmp(
"agents_combined", optimizer_C) == 0 || strcmp(
"AGENTS_COMBINED", optimizer_C) == 0) {
1249 else if (strcmp(
"bayes_opt", optimizer_C) == 0 || strcmp(
"BAYES_OPT", optimizer_C) == 0) {
1253 std::cout <<
"Wrong optimizer: " << optimizer_C <<
". Using default: BFGS" << std::endl;
1254 qgd_optimizer =
BFGS;
1258 self->decomp->set_optimizer(qgd_optimizer);
1260 catch (std::string err) {
1261 PyErr_SetString(PyExc_Exception, err.c_str());
1262 std::cout << err << std::endl;
1266 std::string err(
"Invalid pointer to decomposition class");
1267 PyErr_SetString(PyExc_Exception, err.c_str());
1283 if (!PyArg_ParseTuple(args,
"i", &max_iterations)) {
1287 self->decomp->set_max_inner_iterations(max_iterations);
1289 }
catch (std::exception& e) {
1290 PyErr_SetString(PyExc_Exception, e.what());
1305 PyObject* parameters_obj = NULL;
1306 PyArrayObject* parameters_arr = NULL;
1309 if (!PyArg_ParseTuple(args,
"|O", ¶meters_obj))
1314 bool parameters_is_float32 =
false;
1316 extract_parameters_any(parameters_obj, ¶meters_arr, parameters_mtx, parameters_mtx_float, parameters_is_float32);
1318 catch (std::exception& e) {
1319 PyErr_SetString(PyExc_Exception, e.what());
1323 PyObject *unitary_py = NULL;
1324 if (parameters_is_float32 || self->decomp->get_use_float()) {
1325 if (!parameters_is_float32) {
1327 for (
int row=0; row<parameters_mtx.
rows; row++) {
1328 for (
int col=0; col<parameters_mtx.
cols; col++) {
1329 int idx = row*parameters_mtx.
stride + col;
1330 parameters_mtx_float[idx] =
static_cast<float>(parameters_mtx[idx]);
1334 Matrix_float unitary_mtx =
self->decomp->get_matrix(parameters_mtx_float);
1339 Matrix unitary_mtx =
self->decomp->get_matrix(parameters_mtx);
1344 Py_DECREF(parameters_arr);
1360 static char *kwlist[] = {(
char*)
"costfnc", NULL};
1362 int costfnc_arg = 0;
1365 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|i", kwlist, &costfnc_arg)) {
1366 std::string err(
"Unsuccessful argument parsing");
1367 PyErr_SetString(PyExc_Exception, err.c_str());
1374 self->decomp->set_cost_function_variant(qgd_costfnc);
1376 catch (std::string err) {
1377 PyErr_SetString(PyExc_Exception, err.c_str());
1378 std::cout << err << std::endl;
1382 std::string err(
"Invalid pointer to decomposition class");
1383 PyErr_SetString(PyExc_Exception, err.c_str());
1398 PyObject* parameters_obj = NULL;
1399 PyArrayObject* parameters_arg = NULL;
1402 if (!PyArg_ParseTuple(args,
"|O", ¶meters_obj)) {
1403 std::string err(
"Unsuccessful argument parsing not ");
1404 PyErr_SetString(PyExc_Exception, err.c_str());
1410 bool parameters_is_float32 =
false;
1414 extract_parameters_any(parameters_obj, ¶meters_arg, parameters_mtx, parameters_mtx_float, parameters_is_float32);
1415 if (parameters_is_float32) {
1418 f0 =
self->decomp->optimization_problem(parameters_mtx);
1420 catch (std::exception& e) {
1421 PyErr_SetString(PyExc_Exception, e.what());
1424 catch (std::string err) {
1425 PyErr_SetString(PyExc_Exception, err.c_str());
1429 std::string err(
"Invalid pointer to decomposition class");
1430 PyErr_SetString(PyExc_Exception, err.c_str());
1434 Py_DECREF(parameters_arg);
1448 PyObject* parameters_obj = NULL;
1449 PyArrayObject* parameters_arg = NULL;
1452 if (!PyArg_ParseTuple(args,
"|O", ¶meters_obj)) {
1453 std::string err(
"Unsuccessful argument parsing not ");
1454 PyErr_SetString(PyExc_Exception, err.c_str());
1460 bool parameters_is_float32 =
false;
1462 std::vector<Matrix> Umtx_deriv;
1465 extract_parameters_any(parameters_obj, ¶meters_arg, parameters_mtx, parameters_mtx_float, parameters_is_float32);
1466 if (parameters_is_float32) {
1469 self->decomp->optimization_problem_combined_unitary(parameters_mtx, Umtx, Umtx_deriv);
1471 catch (std::exception& e) {
1472 PyErr_SetString(PyExc_Exception, e.what());
1475 catch (std::string err) {
1476 PyErr_SetString(PyExc_Exception, err.c_str());
1480 std::string err(
"Invalid pointer to decomposition class");
1481 PyErr_SetString(PyExc_Exception, err.c_str());
1488 PyObject* graduni_py = PyList_New(Umtx_deriv.size());
1489 for (
size_t i = 0; i < Umtx_deriv.size(); i++) {
1490 Umtx_deriv[i].set_owner(
false);
1494 Py_DECREF(parameters_arg);
1496 PyObject* p =
Py_BuildValue(
"(OO)", unitary_py, graduni_py);
1497 Py_DECREF(unitary_py);
1498 Py_DECREF(graduni_py);
1511 PyObject* parameters_obj = NULL;
1512 PyArrayObject* parameters_arg = NULL;
1515 if (!PyArg_ParseTuple(args,
"|O", ¶meters_obj)) {
1516 std::string err(
"Unsuccessful argument parsing not ");
1517 PyErr_SetString(PyExc_Exception, err.c_str());
1523 bool parameters_is_float32 =
false;
1527 extract_parameters_any(parameters_obj, ¶meters_arg, parameters_mtx, parameters_mtx_float, parameters_is_float32);
1528 if (parameters_is_float32) {
1532 self->decomp->optimization_problem_grad(parameters_mtx, self->decomp, grad_mtx);
1534 catch (std::exception& e) {
1535 PyErr_SetString(PyExc_Exception, e.what());
1538 catch (std::string err) {
1539 PyErr_SetString(PyExc_Exception, err.c_str());
1543 std::string err(
"Invalid pointer to decomposition class");
1544 PyErr_SetString(PyExc_Exception, err.c_str());
1549 PyObject *grad_py = NULL;
1550 if (parameters_is_float32 || self->decomp->get_use_float()) {
1552 for (
int row=0; row<grad_mtx.rows; row++) {
1553 for (
int col=0; col<grad_mtx.cols; col++) {
1554 int idx = row*grad_mtx.stride + col;
1555 grad_float[idx] =
static_cast<float>(grad_mtx[idx]);
1562 grad_mtx.set_owner(
false);
1566 Py_DECREF(parameters_arg);
1580 PyObject* parameters_obj = NULL;
1581 PyArrayObject* parameters_arg = NULL;
1584 if (!PyArg_ParseTuple(args,
"|O", ¶meters_obj)) {
1585 std::string err(
"Unsuccessful argument parsing not ");
1586 PyErr_SetString(PyExc_Exception, err.c_str());
1592 bool parameters_is_float32 =
false;
1597 extract_parameters_any(parameters_obj, ¶meters_arg, parameters_mtx, parameters_mtx_float, parameters_is_float32);
1598 if (parameters_is_float32) {
1602 self->decomp->optimization_problem_combined(parameters_mtx, &f0, grad_mtx);
1604 catch (std::exception& e) {
1605 PyErr_SetString(PyExc_Exception, e.what());
1608 catch (std::string err) {
1609 PyErr_SetString(PyExc_Exception, err.c_str());
1613 std::string err(
"Invalid pointer to decomposition class");
1614 PyErr_SetString(PyExc_Exception, err.c_str());
1619 PyObject *grad_py = NULL;
1620 if (parameters_is_float32 || self->decomp->get_use_float()) {
1622 for (
int row=0; row<grad_mtx.rows; row++) {
1623 for (
int col=0; col<grad_mtx.cols; col++) {
1624 int idx = row*grad_mtx.stride + col;
1625 grad_float[idx] =
static_cast<float>(grad_mtx[idx]);
1632 grad_mtx.set_owner(
false);
1636 Py_DECREF(parameters_arg);
1652 PyObject* parameters_obj = NULL;
1653 PyArrayObject* parameters_arg = NULL;
1656 if (!PyArg_ParseTuple(args,
"|O", ¶meters_obj)) {
1657 std::string err(
"Unsuccessful argument parsing not ");
1658 PyErr_SetString(PyExc_Exception, err.c_str());
1664 bool parameters_is_float32 =
false;
1668 extract_parameters_any(parameters_obj, ¶meters_arg, parameters_mtx, parameters_mtx_float, parameters_is_float32);
1669 if (parameters_is_float32) {
1672 std::vector<Matrix_real> parameters_vec;
1673 parameters_vec.resize(parameters_mtx.
rows);
1674 for (
int row_idx = 0; row_idx < parameters_mtx.
rows; row_idx++) {
1677 result_mtx =
self->decomp->optimization_problem_batched(parameters_vec);
1679 catch (std::exception& e) {
1680 PyErr_SetString(PyExc_Exception, e.what());
1683 catch (std::string err) {
1684 PyErr_SetString(PyExc_Exception, err.c_str());
1688 std::string err(
"Invalid pointer to decomposition class");
1689 PyErr_SetString(PyExc_Exception, err.c_str());
1694 PyObject *result_py = NULL;
1695 if (parameters_is_float32 || self->decomp->get_use_float()) {
1697 for (
int row=0; row<result_mtx.
rows; row++) {
1698 for (
int col=0; col<result_mtx.
cols; col++) {
1699 int idx = row*result_mtx.
stride + col;
1700 result_float[idx] =
static_cast<float>(result_mtx[idx]);
1711 Py_DECREF(parameters_arg);
1726 self->decomp->upload_Umtx_to_DFE();
1728 }
catch (std::string err) {
1729 PyErr_SetString(PyExc_Exception, err.c_str());
1731 }
catch (std::exception& e) {
1732 PyErr_SetString(PyExc_Exception, e.what());
1735 std::string err(
"Invalid pointer to decomposition class");
1736 PyErr_SetString(PyExc_Exception, err.c_str());
1740 PyErr_SetString(PyExc_NotImplementedError,
"upload_Umtx_to_DFE is only available when compiled with DFE support");
1754 int trace_offset =
self->decomp->get_trace_offset();
1756 }
catch (std::string err) {
1757 PyErr_SetString(PyExc_Exception, err.c_str());
1759 }
catch (std::exception& e) {
1760 PyErr_SetString(PyExc_Exception, e.what());
1763 std::string err(
"Invalid pointer to decomposition class");
1764 PyErr_SetString(PyExc_Exception, err.c_str());
1778 static char *kwlist[] = {(
char*)
"trace_offset", NULL};
1780 int trace_offset = 0;
1781 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|i", kwlist, &trace_offset)) {
1782 std::string err(
"Invalid arguments: expected (trace_offset: int)");
1783 PyErr_SetString(PyExc_Exception, err.c_str());
1788 self->decomp->set_trace_offset(trace_offset);
1790 }
catch (std::string err) {
1791 PyErr_SetString(PyExc_Exception, err.c_str());
1793 }
catch (std::exception& e) {
1794 PyErr_SetString(PyExc_Exception, e.what());
1797 std::string err(
"Invalid pointer to decomposition class");
1798 PyErr_SetString(PyExc_Exception, err.c_str());
1812 double error =
self->decomp->get_decomposition_error();
1814 }
catch (std::string err) {
1815 PyErr_SetString(PyExc_Exception, err.c_str());
1817 }
catch (std::exception& e) {
1818 PyErr_SetString(PyExc_Exception, e.what());
1821 std::string err(
"Invalid pointer to decomposition class");
1822 PyErr_SetString(PyExc_Exception, err.c_str());
1836 PyObject *parameters_obj = NULL, *input_state_obj = NULL;
1837 PyArrayObject *parameters_arr = NULL, *input_state_arg = NULL;
1838 PyObject *qubit_list_arg = NULL;
1841 if (!PyArg_ParseTuple(args,
"|OOO", ¶meters_obj, &input_state_obj, &qubit_list_arg)) {
1847 bool parameters_is_float32 =
false;
1849 extract_parameters_any(parameters_obj, ¶meters_arr, parameters_mtx, parameters_mtx_float, parameters_is_float32);
1850 if (parameters_is_float32) {
1854 catch (std::exception& e) {
1855 PyErr_SetString(PyExc_Exception, e.what());
1860 if (input_state_obj == NULL) {
1861 PyErr_SetString(PyExc_Exception,
"Input matrix was not given");
1867 bool input_state_is_float32 =
false;
1869 extract_matrix_any(input_state_obj, &input_state_arg, input_state_mtx, input_state_mtx_float, input_state_is_float32);
1870 if (input_state_is_float32) {
1871 input_state_mtx = input_state_mtx_float.
to_float64();
1874 catch (std::exception& e) {
1875 PyErr_SetString(PyExc_Exception, e.what());
1880 if (!PyArray_IS_C_CONTIGUOUS(input_state_arg)) {
1881 PyErr_SetString(PyExc_Exception,
"Input matrix is not memory contiguous");
1886 if (qubit_list_arg == NULL || !PyList_Check(qubit_list_arg)) {
1887 PyErr_SetString(PyExc_Exception,
"qubit_list should be a list");
1891 Py_ssize_t reduced_qbit_num = PyList_Size(qubit_list_arg);
1894 for (
int idx = 0; idx < reduced_qbit_num; idx++) {
1895 PyObject* item = PyList_GET_ITEM(qubit_list_arg, idx);
1896 qbit_list_mtx[idx] = (
int)PyLong_AsLong(item);
1902 entropy =
self->decomp->get_second_Renyi_entropy(parameters_mtx, input_state_mtx, qbit_list_mtx);
1903 }
catch (std::string err) {
1904 PyErr_SetString(PyExc_Exception, err.c_str());
1906 }
catch (std::exception& e) {
1907 PyErr_SetString(PyExc_Exception, e.what());
1910 std::string err(
"Invalid pointer to decomposition class");
1911 PyErr_SetString(PyExc_Exception, err.c_str());
1916 Py_DECREF(parameters_arr);
1917 Py_DECREF(input_state_arg);
1932 int qbit_num =
self->decomp->get_qbit_num();
1934 }
catch (std::string err) {
1935 PyErr_SetString(PyExc_Exception, err.c_str());
1937 }
catch (std::exception& e) {
1938 PyErr_SetString(PyExc_Exception, e.what());
1941 std::string err(
"Invalid pointer to decomposition class");
1942 PyErr_SetString(PyExc_Exception, err.c_str());
1956 PyObject* identical_blocks_dict;
1957 if (!PyArg_ParseTuple(args,
"O", &identical_blocks_dict)) {
1960 if (!PyDict_Check(identical_blocks_dict)) {
1961 PyErr_SetString(PyExc_TypeError,
"Expected dictionary argument");
1966 if (base_decomp == NULL) {
1967 PyErr_SetString(PyExc_AttributeError,
"set_identical_blocks is only available for N_Qubit_Decomposition");
1970 std::map<int, int> identical_blocks_map;
1971 PyObject *
key, *value;
1973 while (PyDict_Next(identical_blocks_dict, &pos, &key, &value)) {
1974 if (!PyLong_Check(key) || !PyLong_Check(value)) {
1975 PyErr_SetString(PyExc_TypeError,
"Dictionary keys and values must be integers");
1978 int qubit_idx = PyLong_AsLong(key);
1979 int blocks = PyLong_AsLong(value);
1980 identical_blocks_map[qubit_idx] = blocks;
1984 }
catch (std::exception& e) {
1985 PyErr_SetString(PyExc_Exception, e.what());
1999 if (adaptive_decomp == NULL) {
2000 PyErr_SetString(PyExc_AttributeError,
"get_initial_circuit is only available for N_Qubit_Decomposition_adaptive");
2005 }
catch (std::exception& e) {
2006 PyErr_SetString(PyExc_Exception, e.what());
2020 if (adaptive_decomp == NULL) {
2021 PyErr_SetString(PyExc_AttributeError,
"compress_circuit is only available for N_Qubit_Decomposition_adaptive");
2026 }
catch (std::exception& e) {
2027 PyErr_SetString(PyExc_Exception, e.what());
2041 if (adaptive_decomp == NULL) {
2042 PyErr_SetString(PyExc_AttributeError,
"finalize_circuit is only available for N_Qubit_Decomposition_adaptive");
2047 }
catch (std::exception& e) {
2048 PyErr_SetString(PyExc_Exception, e.what());
2061 PyObject* filename_py=NULL;
2063 if (!PyArg_ParseTuple(args,
"|O", &filename_py )) {
2067 PyObject* filename_string = PyObject_Str(filename_py);
2068 PyObject* filename_string_unicode = PyUnicode_AsEncodedString(filename_string,
"utf-8",
"~E~");
2069 const char* filename_C = PyBytes_AS_STRING(filename_string_unicode);
2070 std::string filename_str( filename_C );
2073 if (adaptive_decomp == NULL) {
2074 std::string err(
"set_Gate_Structure_From_Binary is only available for adaptive decomposition");
2075 PyErr_SetString(PyExc_Exception, err.c_str());
2080 catch (std::string err ) {
2081 PyErr_SetString(PyExc_Exception, err.c_str());
2085 std::string err(
"Invalid pointer to decomposition class");
2086 PyErr_SetString(PyExc_Exception, err.c_str());
2101 PyObject* filename_py = NULL;
2103 if (!PyArg_ParseTuple(args,
"|O", &filename_py)) {
2107 PyObject* filename_string = PyObject_Str(filename_py);
2108 PyObject* filename_string_unicode = PyUnicode_AsEncodedString(filename_string,
"utf-8",
"~E~");
2109 const char* filename_C = PyBytes_AS_STRING(filename_string_unicode);
2110 std::string filename_str(filename_C);
2113 if (adaptive_decomp == NULL) {
2114 PyErr_SetString(PyExc_AttributeError,
"add_Gate_Structure_From_Binary is only available for N_Qubit_Decomposition_adaptive");
2119 catch (std::string err) {
2120 PyErr_SetString(PyExc_Exception, err.c_str());
2124 std::string err(
"Invalid pointer to decomposition class");
2125 PyErr_SetString(PyExc_Exception, err.c_str());
2139 PyObject* filename_py = NULL;
2141 if (!PyArg_ParseTuple(args,
"|O", &filename_py)) {
2145 PyObject* filename_string = PyObject_Str(filename_py);
2146 PyObject* filename_string_unicode = PyUnicode_AsEncodedString(filename_string,
"utf-8",
"~E~");
2147 const char* filename_C = PyBytes_AS_STRING(filename_string_unicode);
2148 std::string filename_str(filename_C);
2151 if (adaptive_decomp == NULL) {
2152 PyErr_SetString(PyExc_AttributeError,
"set_Unitary_From_Binary is only available for N_Qubit_Decomposition_adaptive");
2157 catch (std::string err) {
2158 PyErr_SetString(PyExc_Exception, err.c_str());
2162 std::string err(
"Invalid pointer to decomposition class");
2163 PyErr_SetString(PyExc_Exception, err.c_str());
2177 if (adaptive_decomp == NULL) {
2178 PyErr_SetString(PyExc_AttributeError,
"add_Adaptive_Layers is only available for N_Qubit_Decomposition_adaptive");
2193 if (adaptive_decomp == NULL) {
2194 PyErr_SetString(PyExc_AttributeError,
"add_Layer_To_Imported_Gate_Structure is only available for N_Qubit_Decomposition_adaptive");
2210 if (adaptive_decomp == NULL) {
2211 PyErr_SetString(PyExc_AttributeError,
"apply_Imported_Gate_Structure is only available for N_Qubit_Decomposition_adaptive");
2216 catch (std::string err) {
2217 PyErr_SetString(PyExc_Exception, err.c_str());
2221 std::string err(
"Invalid pointer to decomposition class");
2222 PyErr_SetString(PyExc_Exception, err.c_str());
2239 if ( self->Umtx != NULL ) {
2241 Py_DECREF(self->Umtx);
2245 PyObject *Umtx_obj = NULL;
2247 if (!PyArg_ParseTuple(args,
"|O", &Umtx_obj )) {
2252 if ( Umtx_obj == NULL ) {
2253 PyErr_SetString(PyExc_Exception,
"Umtx argument in empty");
2259 bool Umtx_is_float32 =
false;
2261 extract_matrix_any(Umtx_obj, &self->Umtx, Umtx_mtx, Umtx_mtx_float, Umtx_is_float32);
2263 catch (std::exception& e) {
2264 PyErr_SetString(PyExc_Exception, e.what());
2270 if (Umtx_is_float32) {
2271 p->set_unitary(Umtx_mtx_float);
2274 p->set_unitary(Umtx_mtx);
2279 if (Umtx_is_float32) {
2280 p->set_unitary(Umtx_mtx_float);
2283 p->set_unitary(Umtx_mtx);
2288 if (Umtx_is_float32) {
2289 p->set_unitary(Umtx_mtx_float);
2292 p->set_unitary(Umtx_mtx);
2297 PyErr_SetString(PyExc_TypeError,
"set_unitary not available for this decomposition type");
2311 std::vector<Gate*>&& gates =
self->decomp->get_gates();
2312 Matrix_real&& params =
self->decomp->get_optimized_parameters();
2314 PyObject* gates_list = PyList_New(0);
2315 if (!gates_list)
return NULL;
2317 for (
size_t idx = 0; idx < gates.size(); idx++) {
2319 if (!gate)
continue;
2321 PyObject* gate_dict = PyDict_New();
2323 Py_DECREF(gates_list);
2328 const char* type_str =
nullptr;
2367 default: type_str =
"UNKNOWN";
break;
2369 PyDict_SetItemString(gate_dict,
"type", PyUnicode_FromString(type_str));
2371 PyDict_SetItemString(gate_dict,
"target_qbit", PyLong_FromLong(gate->
get_target_qbit()));
2374 if (control_qbit >= 0) {
2375 PyDict_SetItemString(gate_dict,
"control_qbit", PyLong_FromLong(control_qbit));
2381 if (pnum > 0 && pstart >= 0 && (pstart + pnum) <= (
int)params.
size()) {
2383 PyDict_SetItemString(gate_dict,
"Theta", PyFloat_FromDouble(params[pstart]));
2384 PyDict_SetItemString(gate_dict,
"Phi", PyFloat_FromDouble(params[pstart + 1]));
2385 PyDict_SetItemString(gate_dict,
"Lambda", PyFloat_FromDouble(params[pstart + 2]));
2387 PyDict_SetItemString(gate_dict,
"Theta", PyFloat_FromDouble(params[pstart]));
2389 PyDict_SetItemString(gate_dict,
"Phi", PyFloat_FromDouble(params[pstart]));
2393 PyList_Append(gates_list, gate_dict);
2394 Py_DECREF(gate_dict);
2407 PyObject* qiskit_io_module = PyImport_ImportModule(
"squander.IO_interfaces.Qiskit_IO");
2408 if (!qiskit_io_module) {
2409 PyErr_SetString(PyExc_ImportError,
"Failed to import squander.IO_interfaces.Qiskit_IO");
2414 PyObject* get_qiskit_func = PyObject_GetAttrString(qiskit_io_module,
"get_Qiskit_Circuit");
2415 Py_DECREF(qiskit_io_module);
2416 if (!get_qiskit_func) {
2417 PyErr_SetString(PyExc_AttributeError,
"get_Qiskit_Circuit not found in Qiskit_IO");
2424 Py_DECREF(get_qiskit_func);
2429 Py_DECREF(get_qiskit_func);
2435 PyObject*
args = PyTuple_Pack(2, circuit, parameters);
2436 PyObject*
result = PyObject_CallObject(get_qiskit_func, args);
2439 Py_DECREF(parameters);
2441 Py_DECREF(get_qiskit_func);
2451 #define CIRQ_ADD_SINGLE_QUBIT_GATE(name) do { \ 2452 PyObject* gate_func = PyObject_GetAttrString(cirq_module, #name); \ 2453 PyObject* gate_args = PyTuple_Pack(1, target_qubit); \ 2454 PyObject* cirq_gate = PyObject_CallObject(gate_func, gate_args); \ 2455 Py_DECREF(gate_args); Py_DECREF(gate_func); \ 2457 PyObject* append_args = PyTuple_Pack(1, cirq_gate); \ 2458 PyObject_CallObject(append_func, append_args); \ 2459 Py_DECREF(append_args); Py_DECREF(cirq_gate); \ 2464 #define CIRQ_ADD_TWO_QUBIT_GATE(name) do { \ 2465 PyObject* control_qbit_obj = PyDict_GetItemString(gate, "control_qbit"); \ 2466 if (!control_qbit_obj) continue; \ 2467 long control_idx = qbit_num - 1 - PyLong_AsLong(control_qbit_obj); \ 2468 PyObject* control_qubit = PyList_GetItem(qubits, control_idx); \ 2469 PyObject* gate_func = PyObject_GetAttrString(cirq_module, #name); \ 2470 PyObject* gate_args = PyTuple_Pack(2, control_qubit, target_qubit); \ 2471 PyObject* cirq_gate = PyObject_CallObject(gate_func, gate_args); \ 2472 Py_DECREF(gate_args); Py_DECREF(gate_func); \ 2474 PyObject* append_args = PyTuple_Pack(1, cirq_gate); \ 2475 PyObject_CallObject(append_func, append_args); \ 2476 Py_DECREF(append_args); Py_DECREF(cirq_gate); \ 2480 #define CIRQ_ADD_ROTATION_GATE(name, param) do { \ 2481 PyObject* param_obj = PyDict_GetItemString(gate, param); \ 2482 if (!param_obj) continue; \ 2483 PyObject* gate_func = PyObject_GetAttrString(cirq_module, #name); \ 2484 PyObject* gate_args = PyTuple_Pack(1, param_obj); \ 2485 PyObject* cirq_gate = PyObject_CallObject(gate_func, gate_args); \ 2486 Py_DECREF(gate_args); Py_DECREF(gate_func); \ 2488 PyObject* on_method = PyObject_GetAttrString(cirq_gate, "on"); \ 2489 PyObject* on_args = PyTuple_Pack(1, target_qubit); \ 2490 PyObject* gate_op = PyObject_CallObject(on_method, on_args); \ 2491 Py_DECREF(on_args); Py_DECREF(on_method); Py_DECREF(cirq_gate); \ 2493 PyObject* append_args = PyTuple_Pack(1, gate_op); \ 2494 PyObject_CallObject(append_func, append_args); \ 2495 Py_DECREF(append_args); Py_DECREF(gate_op); \ 2503 PyObject* cirq_module = PyImport_ImportModule(
"cirq");
2505 PyErr_SetString(PyExc_ImportError,
"Failed to import cirq. Please install cirq package.");
2509 PyObject* cirq_circuit_class = PyObject_GetAttrString(cirq_module,
"Circuit");
2510 if (!cirq_circuit_class) {
2511 Py_DECREF(cirq_module);
2515 PyObject* cirq_circuit_obj = PyObject_CallObject(cirq_circuit_class, NULL);
2516 Py_DECREF(cirq_circuit_class);
2517 if (!cirq_circuit_obj) {
2518 Py_DECREF(cirq_module);
2523 PyObject* cirq_line_qubit_class = PyObject_GetAttrString(cirq_module,
"LineQubit");
2524 if (!cirq_line_qubit_class) {
2525 Py_DECREF(cirq_circuit_obj);
2526 Py_DECREF(cirq_module);
2529 PyObject* range_func = PyObject_GetAttrString(cirq_line_qubit_class,
"range");
2530 Py_DECREF(cirq_line_qubit_class);
2532 Py_DECREF(cirq_circuit_obj);
2533 Py_DECREF(cirq_module);
2537 int qbit_num =
self->decomp->get_qbit_num();
2538 PyObject* range_args = PyTuple_Pack(1, PyLong_FromLong(qbit_num));
2539 PyObject*
qubits = PyObject_CallObject(range_func, range_args);
2540 Py_DECREF(range_args); Py_DECREF(range_func);
2542 Py_DECREF(cirq_circuit_obj);
2543 Py_DECREF(cirq_module);
2550 Py_DECREF(cirq_circuit_obj);
2551 Py_DECREF(cirq_module);
2555 PyObject* append_func = PyObject_GetAttrString(cirq_circuit_obj,
"append");
2557 Py_DECREF(gates_list); Py_DECREF(qubits); Py_DECREF(cirq_circuit_obj); Py_DECREF(cirq_module);
2561 PyObject* cirq_google_module = PyObject_GetAttrString(cirq_module,
"google");
2564 Py_ssize_t num_gates = PyList_Size(gates_list);
2565 for (Py_ssize_t idx = num_gates - 1; idx >= 0; idx--) {
2566 PyObject*
gate = PyList_GetItem(gates_list, idx);
2567 if (!gate)
continue;
2569 PyObject*
gate_type = PyDict_GetItemString(gate,
"type");
2570 if (!gate_type)
continue;
2571 const char* gate_type_str = PyUnicode_AsUTF8(gate_type);
2572 if (!gate_type_str)
continue;
2574 PyObject* target_qbit_obj = PyDict_GetItemString(gate,
"target_qbit");
2575 if (!target_qbit_obj)
continue;
2577 long target_idx = qbit_num - 1 - PyLong_AsLong(target_qbit_obj);
2578 PyObject* target_qubit = PyList_GetItem(qubits, target_idx);
2579 if (!target_qubit)
continue;
2584 else if (strcmp(gate_type_str,
"SYC") == 0 && cirq_google_module) {
2585 PyObject* control_qbit_obj = PyDict_GetItemString(gate,
"control_qbit");
2586 if (control_qbit_obj) {
2587 long control_idx = qbit_num - 1 - PyLong_AsLong(control_qbit_obj);
2588 PyObject* control_qubit = PyList_GetItem(qubits, control_idx);
2590 PyObject* syc_func = PyObject_GetAttrString(cirq_google_module,
"SYC");
2591 PyObject* syc_args = PyTuple_Pack(2, control_qubit, target_qubit);
2592 PyObject* cirq_gate = PyObject_CallObject(syc_func, syc_args);
2593 Py_DECREF(syc_args);
2594 Py_DECREF(syc_func);
2596 PyObject* append_args = PyTuple_Pack(1, cirq_gate);
2597 PyObject_CallObject(append_func, append_args);
2598 Py_DECREF(append_args);
2599 Py_DECREF(cirq_gate);
2603 else if (strcmp(gate_type_str,
"CRY") == 0) {
2604 printf(
"CRY gate needs to be implemented\n");
2606 else if (strcmp(gate_type_str,
"U3") == 0) {
2607 printf(
"Unsupported gate in the Cirq export: U3 gate\n");
2608 Py_XDECREF(cirq_google_module);
2609 Py_DECREF(append_func);
2610 Py_DECREF(gates_list);
2612 Py_DECREF(cirq_circuit_obj);
2613 Py_DECREF(cirq_module);
2625 Py_XDECREF(cirq_google_module);
2626 Py_DECREF(append_func);
2627 Py_DECREF(gates_list);
2629 Py_DECREF(cirq_module);
2631 return cirq_circuit_obj;
2634 #undef CIRQ_ADD_SINGLE_QUBIT_GATE 2635 #undef CIRQ_ADD_TWO_QUBIT_GATE 2636 #undef CIRQ_ADD_ROTATION_GATE 2647 PyObject* qiskit_io_module = PyImport_ImportModule(
"squander.IO_interfaces.Qiskit_IO");
2648 if (!qiskit_io_module) {
2649 PyErr_SetString(PyExc_ImportError,
"Failed to import squander.IO_interfaces.Qiskit_IO");
2653 PyObject* convert_func = PyObject_GetAttrString(qiskit_io_module,
"convert_Qiskit_to_Squander");
2654 Py_DECREF(qiskit_io_module);
2655 if (!convert_func) {
2656 PyErr_SetString(PyExc_AttributeError,
"convert_Qiskit_to_Squander not found in Qiskit_IO");
2660 PyObject* convert_args = PyTuple_Pack(1, qc_in);
2661 PyObject* convert_result = PyObject_CallObject(convert_func, convert_args);
2662 Py_DECREF(convert_args);
2663 Py_DECREF(convert_func);
2664 if (!convert_result || !PyTuple_Check(convert_result) || PyTuple_Size(convert_result) != 2) {
2665 Py_XDECREF(convert_result);
2666 PyErr_SetString(PyExc_ValueError,
"convert_Qiskit_to_Squander should return (circuit, parameters)");
2673 PyObject* set_gate_args = PyTuple_Pack(1, circuit_squander);
2675 Py_DECREF(set_gate_args);
2676 if (!set_gate_result) {
2677 Py_DECREF(convert_result);
2680 Py_DECREF(set_gate_result);
2683 PyObject* set_params_args = PyTuple_Pack(1,
parameters);
2685 Py_DECREF(set_params_args);
2686 Py_DECREF(convert_result);
2687 if (!set_params_result) {
2690 Py_DECREF(set_params_result);
2704 PyObject* qiskit_module = PyImport_ImportModule(
"qiskit");
2705 if (!qiskit_module) {
2706 PyErr_SetString(PyExc_ImportError,
"Failed to import qiskit");
2710 PyObject* transpile_func = PyObject_GetAttrString(qiskit_module,
"transpile");
2711 Py_DECREF(qiskit_module);
2712 if (!transpile_func) {
2713 PyErr_SetString(PyExc_AttributeError,
"transpile not found in qiskit");
2718 PyObject* basis_gates = PyList_New(2);
2719 PyList_SetItem(basis_gates, 0, PyUnicode_FromString(
"cz"));
2720 PyList_SetItem(basis_gates, 1, PyUnicode_FromString(
"u3"));
2722 PyObject* kwargs = PyDict_New();
2723 PyDict_SetItemString(kwargs,
"optimization_level", PyLong_FromLong(0));
2724 PyDict_SetItemString(kwargs,
"basis_gates", basis_gates);
2725 PyDict_SetItemString(kwargs,
"layout_method", PyUnicode_FromString(
"sabre"));
2727 PyObject* transpile_args = PyTuple_Pack(1, qc_in);
2728 PyObject*
qc = PyObject_Call(transpile_func, transpile_args, kwargs);
2730 Py_DECREF(transpile_args);
2732 Py_DECREF(basis_gates);
2733 Py_DECREF(transpile_func);
2739 PyObject* count_ops_func = PyObject_GetAttrString(qc,
"count_ops");
2740 if (count_ops_func) {
2741 PyObject* count_ops_result = PyObject_CallObject(count_ops_func, NULL);
2742 Py_DECREF(count_ops_func);
2743 if (count_ops_result) {
2744 printf(
"Gate counts in the imported Qiskit transpiled quantum circuit: ");
2745 PyObject_Print(count_ops_result, stdout, 0);
2747 Py_DECREF(count_ops_result);
2752 PyObject* qc_data_attr = PyObject_GetAttrString(qc,
"data");
2753 PyObject* qc_qubits_attr = PyObject_GetAttrString(qc,
"qubits");
2754 PyObject* qc_num_qubits_attr = PyObject_GetAttrString(qc,
"num_qubits");
2755 if (!qc_data_attr || !qc_qubits_attr || !qc_num_qubits_attr) {
2756 Py_XDECREF(qc_data_attr);
2757 Py_XDECREF(qc_qubits_attr);
2758 Py_XDECREF(qc_num_qubits_attr);
2763 int register_size = PyLong_AsLong(qc_num_qubits_attr);
2764 Py_DECREF(qc_num_qubits_attr);
2767 PyObject* circuit_wrapper_module = PyImport_ImportModule(
"squander.gates.qgd_Circuit_Wrapper");
2768 if (!circuit_wrapper_module) {
2769 Py_DECREF(qc_data_attr);
2770 Py_DECREF(qc_qubits_attr);
2775 PyObject* circuit_wrapper_class = PyObject_GetAttrString(circuit_wrapper_module,
"qgd_Circuit_Wrapper");
2776 Py_DECREF(circuit_wrapper_module);
2777 if (!circuit_wrapper_class) {
2778 Py_DECREF(qc_data_attr);
2779 Py_DECREF(qc_qubits_attr);
2785 PyObject* circuit_ret_args = PyTuple_Pack(1, PyLong_FromLong(register_size));
2786 PyObject* Circuit_ret_result = PyObject_CallObject(circuit_wrapper_class, circuit_ret_args);
2787 Py_DECREF(circuit_ret_args);
2788 Py_DECREF(circuit_wrapper_class);
2789 if (!Circuit_ret_result) {
2790 Py_DECREF(qc_data_attr);
2791 Py_DECREF(qc_qubits_attr);
2797 PyObject* single_qubit_gates = PyDict_New();
2798 for (
int idx = 0; idx < register_size; idx++) {
2799 PyObject*
key = PyLong_FromLong(idx);
2800 PyObject* value = PyList_New(0);
2801 PyDict_SetItem(single_qubit_gates, key, value);
2806 PyObject* optimized_parameters = PyList_New(0);
2809 Py_ssize_t qc_data_attr_size = PyList_Size(qc_data_attr);
2810 for (Py_ssize_t i = 0; i < qc_data_attr_size; i++) {
2811 PyObject*
gate = PyList_GetItem(qc_data_attr, i);
2812 PyObject* gate_operation = PyObject_GetAttrString(gate,
"operation");
2813 PyObject* gate_qubits = PyObject_GetAttrString(gate,
"qubits");
2814 if (!gate_operation || !gate_qubits) {
2815 Py_XDECREF(gate_operation);
2816 Py_XDECREF(gate_qubits);
2820 PyObject* gate_operation_name_attr = PyObject_GetAttrString(gate_operation,
"name");
2821 const char* name = PyUnicode_AsUTF8(gate_operation_name_attr);
2823 if (strcmp(name,
"u3") == 0) {
2825 PyObject* index_func = PyObject_GetAttrString(qc_qubits_attr,
"index");
2827 PyObject* index_args = PyTuple_Pack(1, PyList_GetItem(gate_qubits, 0));
2828 PyObject* index_result = PyObject_CallObject(index_func, index_args);
2829 Py_DECREF(index_func);
2830 Py_DECREF(index_args);
2832 long qubit = PyLong_AsLong(index_result);
2833 Py_DECREF(index_result);
2836 PyObject* gate_info_dict = PyDict_New();
2837 PyObject* gate_operation_params_attr = PyObject_GetAttrString(gate_operation,
"params");
2838 PyDict_SetItemString(gate_info_dict,
"params", gate_operation_params_attr);
2839 PyDict_SetItemString(gate_info_dict,
"type", PyUnicode_FromString(
"u3"));
2840 Py_DECREF(gate_operation_params_attr);
2842 PyObject*
qubit_list = PyDict_GetItem(single_qubit_gates, PyLong_FromLong(qubit));
2843 PyList_Append(qubit_list, gate_info_dict);
2844 Py_DECREF(gate_info_dict);
2845 }
else if (strcmp(name,
"cz") == 0) {
2847 PyObject* index_func = PyObject_GetAttrString(qc_qubits_attr,
"index");
2849 PyObject* index_args0 = PyTuple_Pack(1, PyList_GetItem(gate_qubits, 0));
2850 PyObject* index_args0_result = PyObject_CallObject(index_func, index_args0);
2851 Py_DECREF(index_args0);
2853 PyObject* index_args1 = PyTuple_Pack(1, PyList_GetItem(gate_qubits, 1));
2854 PyObject* index_args1_result = PyObject_CallObject(index_func, index_args1);
2855 Py_DECREF(index_args1);
2856 Py_DECREF(index_func);
2858 long qubit0 = PyLong_AsLong(index_args0_result);
2859 long qubit1 = PyLong_AsLong(index_args1_result);
2860 Py_DECREF(index_args0_result);
2861 Py_DECREF(index_args1_result);
2864 PyObject* layer_args = PyTuple_Pack(1, PyLong_FromLong(register_size));
2865 PyObject* circuit_wrapper_module2 = PyImport_ImportModule(
"squander.gates.qgd_Circuit_Wrapper");
2866 PyObject* circuit_wrapper_class2 = PyObject_GetAttrString(circuit_wrapper_module2,
"qgd_Circuit_Wrapper");
2867 Py_DECREF(circuit_wrapper_module2);
2869 PyObject*
Layer = PyObject_CallObject(circuit_wrapper_class2, layer_args);
2870 Py_DECREF(layer_args);
2871 Py_DECREF(circuit_wrapper_class2);
2874 PyObject* qubit0_list = PyDict_GetItem(single_qubit_gates, PyLong_FromLong(qubit0));
2875 if (qubit0_list && PyList_Size(qubit0_list) > 0) {
2876 PyObject* gate0 = PyList_GetItem(qubit0_list, 0);
2877 PyList_SetSlice(qubit0_list, 0, 1, NULL);
2879 PyObject* add_u3_func = PyObject_GetAttrString(Layer,
"add_U3");
2880 PyObject* add_u3_args =
Py_BuildValue(
"(iOOO)", qubit0, Py_True, Py_True, Py_True);
2881 PyObject_CallObject(add_u3_func, add_u3_args);
2882 Py_DECREF(add_u3_func);
2883 Py_DECREF(add_u3_args);
2886 PyObject* params = PyDict_GetItemString(gate0,
"params");
2887 PyObject* reversed_params = PyList_New(0);
2888 for (Py_ssize_t j = PyList_Size(params) - 1; j >= 0; j--) {
2889 PyList_Append(reversed_params, PyList_GetItem(params, j));
2891 for (Py_ssize_t j = 0; j < PyList_Size(reversed_params); j++) {
2892 PyList_Append(optimized_parameters, PyList_GetItem(reversed_params, j));
2894 Py_DECREF(reversed_params);
2897 Py_ssize_t last_idx = PyList_Size(optimized_parameters) - 1;
2898 PyObject* last_param = PyList_GetItem(optimized_parameters, last_idx);
2899 double val = PyFloat_AsDouble(last_param) / 2.0;
2900 PyList_SetItem(optimized_parameters, last_idx, PyFloat_FromDouble(val));
2904 PyObject* qubit1_list = PyDict_GetItem(single_qubit_gates, PyLong_FromLong(qubit1));
2905 if (qubit1_list && PyList_Size(qubit1_list) > 0) {
2906 PyObject* gate1 = PyList_GetItem(qubit1_list, 0);
2907 PyList_SetSlice(qubit1_list, 0, 1, NULL);
2909 PyObject* add_u3_func = PyObject_GetAttrString(Layer,
"add_U3");
2910 PyObject* u3_args =
Py_BuildValue(
"(iOOO)", qubit1, Py_True, Py_True, Py_True);
2911 PyObject_CallObject(add_u3_func, u3_args);
2912 Py_DECREF(add_u3_func);
2915 PyObject* params = PyDict_GetItemString(gate1,
"params");
2916 PyObject* reversed_params = PyList_New(0);
2917 for (Py_ssize_t j = PyList_Size(params) - 1; j >= 0; j--) {
2918 PyList_Append(reversed_params, PyList_GetItem(params, j));
2920 for (Py_ssize_t j = 0; j < PyList_Size(reversed_params); j++) {
2921 PyList_Append(optimized_parameters, PyList_GetItem(reversed_params, j));
2923 Py_DECREF(reversed_params);
2925 Py_ssize_t last_idx = PyList_Size(optimized_parameters) - 1;
2926 PyObject* last_param = PyList_GetItem(optimized_parameters, last_idx);
2927 double val = PyFloat_AsDouble(last_param) / 2.0;
2928 PyList_SetItem(optimized_parameters, last_idx, PyFloat_FromDouble(val));
2932 PyObject* qubit0_obj = PyLong_FromLong(qubit0);
2933 PyObject* qubit1_obj = PyLong_FromLong(qubit1);
2935 PyObject* add_rx_func = PyObject_GetAttrString(Layer,
"add_RX");
2936 PyObject* add_rx_arg = PyTuple_Pack(1, qubit0_obj);
2937 PyObject_CallObject(add_rx_func, add_rx_arg);
2938 Py_DECREF(add_rx_func);
2939 Py_DECREF(add_rx_arg);
2941 PyObject* add_adaptive_func = PyObject_GetAttrString(Layer,
"add_adaptive");
2942 PyObject* add_adaptive_args = PyTuple_Pack(2, qubit0_obj, qubit1_obj);
2943 PyObject_CallObject(add_adaptive_func, add_adaptive_args);
2944 Py_DECREF(add_adaptive_func);
2945 Py_DECREF(add_adaptive_args);
2947 PyObject* add_rz_func = PyObject_GetAttrString(Layer,
"add_RZ");
2948 PyObject* add_rz_arg = PyTuple_Pack(1, qubit1_obj);
2949 PyObject_CallObject(add_rz_func, add_rz_arg);
2950 Py_DECREF(add_rz_func);
2951 Py_DECREF(add_rz_arg);
2953 PyObject* add_rx_func_2 = PyObject_GetAttrString(Layer,
"add_RX");
2954 PyObject* add_rx_arg_2 = PyTuple_Pack(1, qubit0_obj);
2955 PyObject_CallObject(add_rx_func_2, add_rx_arg_2);
2956 Py_DECREF(add_rx_func_2);
2957 Py_DECREF(add_rx_arg_2);
2959 Py_DECREF(qubit0_obj);
2960 Py_DECREF(qubit1_obj);
2963 PyList_Append(optimized_parameters, PyFloat_FromDouble(
M_PI / 4.0));
2964 PyList_Append(optimized_parameters, PyFloat_FromDouble(
M_PI / 2.0));
2965 PyList_Append(optimized_parameters, PyFloat_FromDouble(-
M_PI / 2.0));
2966 PyList_Append(optimized_parameters, PyFloat_FromDouble(-
M_PI / 4.0));
2969 PyObject* add_circuit_func = PyObject_GetAttrString(Circuit_ret_result,
"add_Circuit");
2970 PyObject* add_circuit_args = PyTuple_Pack(1, Layer);
2971 PyObject_CallObject(add_circuit_func, add_circuit_args);
2972 Py_DECREF(add_circuit_func);
2973 Py_DECREF(add_circuit_args);
2976 Py_DECREF(gate_operation_name_attr);
2977 Py_DECREF(gate_operation);
2978 Py_DECREF(gate_qubits);
2982 PyObject* circuit_module = PyImport_ImportModule(
"squander.gates.qgd_Circuit");
2983 PyObject* circuit_class = PyObject_GetAttrString(circuit_module,
"qgd_Circuit");
2984 Py_DECREF(circuit_module);
2986 PyObject* final_layer_args = PyTuple_Pack(1, PyLong_FromLong(register_size));
2987 PyObject* final_layer_result = PyObject_CallObject(circuit_class, final_layer_args);
2988 Py_DECREF(circuit_class);
2989 Py_DECREF(final_layer_args);
2991 for (
int qubit = 0; qubit < register_size; qubit++) {
2992 PyObject* gates_list = PyDict_GetItem(single_qubit_gates, PyLong_FromLong(qubit));
2993 Py_ssize_t gates_list_size = PyList_Size(gates_list);
2995 for (Py_ssize_t j = 0; j < gates_list_size; j++) {
2996 PyObject* gate_obj = PyList_GetItem(gates_list, j);
2997 PyObject* gate_obj_type = PyDict_GetItemString(gate_obj,
"type");
2998 const char* gate_obj_type_str = PyUnicode_AsUTF8(gate_obj_type);
3000 if (strcmp(gate_obj_type_str,
"u3") == 0) {
3001 PyObject* add_u3_func = PyObject_GetAttrString(final_layer_result,
"add_U3");
3002 PyObject* add_u3_args =
Py_BuildValue(
"(iOOO)", qubit, Py_True, Py_True, Py_True);
3003 PyObject_CallObject(add_u3_func, add_u3_args);
3004 Py_DECREF(add_u3_func);
3005 Py_DECREF(add_u3_args);
3007 PyObject* gate_obj_params = PyDict_GetItemString(gate_obj,
"params");
3008 PyObject* reversed_params = PyList_New(0);
3009 for (Py_ssize_t
k = PyList_Size(gate_obj_params) - 1;
k >= 0;
k--) {
3010 PyList_Append(reversed_params, PyList_GetItem(gate_obj_params,
k));
3014 for (Py_ssize_t
k = 0;
k < PyList_Size(reversed_params);
k++) {
3015 PyObject* param = PyList_GetItem(reversed_params,
k);
3016 PyObject* param_float = PyFloat_FromDouble(PyFloat_AsDouble(param));
3017 PyList_Append(optimized_parameters, param_float);
3018 Py_DECREF(param_float);
3020 Py_DECREF(reversed_params);
3023 Py_ssize_t optimized_parameters_last_idx = PyList_Size(optimized_parameters) - 1;
3024 PyObject* optimized_parameters_last_param = PyList_GetItem(optimized_parameters, optimized_parameters_last_idx);
3025 double val = PyFloat_AsDouble(optimized_parameters_last_param) / 2.0;
3026 PyList_SetItem(optimized_parameters, optimized_parameters_last_idx, PyFloat_FromDouble(val));
3031 PyObject* add_final_circuit_func = PyObject_GetAttrString(Circuit_ret_result,
"add_Circuit");
3032 PyObject* add_final_circuit_args = PyTuple_Pack(1, final_layer_result);
3033 PyObject_CallObject(add_final_circuit_func, add_final_circuit_args);
3034 Py_DECREF(add_final_circuit_func);
3035 Py_DECREF(add_final_circuit_args);
3036 Py_DECREF(final_layer_result);
3039 PyObject* numpy_module = PyImport_ImportModule(
"numpy");
3040 PyObject* numpy_asarray_func = PyObject_GetAttrString(numpy_module,
"asarray");
3041 PyObject* numpy_flip_func = PyObject_GetAttrString(numpy_module,
"flip");
3042 Py_DECREF(numpy_module);
3044 PyObject* dtype_dict = PyDict_New();
3045 PyDict_SetItemString(dtype_dict,
"dtype", (PyObject*)&PyFloat_Type);
3046 PyObject* numpy_asarray_args = PyTuple_Pack(1, optimized_parameters);
3047 PyObject* numpy_asarray_result = PyObject_Call(numpy_asarray_func, numpy_asarray_args, dtype_dict);
3048 Py_DECREF(numpy_asarray_func);
3049 Py_DECREF(numpy_asarray_args);
3050 Py_DECREF(dtype_dict);
3052 PyObject* numpt_flip_args = PyTuple_Pack(2, numpy_asarray_result, PyLong_FromLong(0));
3053 PyObject* numpt_flip_result = PyObject_CallObject(numpy_flip_func, numpt_flip_args);
3054 Py_DECREF(numpy_flip_func);
3055 Py_DECREF(numpt_flip_args);
3056 Py_DECREF(numpy_asarray_result);
3059 PyObject* set_gate_structure_args = PyTuple_Pack(1, Circuit_ret_result);
3061 Py_DECREF(set_gate_structure_args);
3062 Py_DECREF(Circuit_ret_result);
3063 if (!set_gate_structure_result) {
3064 Py_DECREF(numpt_flip_result);
3065 Py_DECREF(optimized_parameters);
3066 Py_DECREF(single_qubit_gates);
3067 Py_DECREF(qc_data_attr);
3068 Py_DECREF(qc_qubits_attr);
3072 Py_DECREF(set_gate_structure_result);
3074 PyObject* set_optimized_params_args = PyTuple_Pack(1, numpt_flip_result);
3076 Py_DECREF(set_optimized_params_args);
3077 Py_DECREF(numpt_flip_result);
3078 Py_DECREF(optimized_parameters);
3079 Py_DECREF(single_qubit_gates);
3080 Py_DECREF(qc_data_attr);
3081 Py_DECREF(qc_qubits_attr);
3083 if (!set_optimized_params_result) {
3086 Py_DECREF(set_optimized_params_result);
3099 PyObject* qc_in = NULL;
3100 if (!PyArg_ParseTuple(args,
"O", &qc_in)) {
3124 #define DECOMPOSITION_WRAPPER_BASE_METHODS \ 3125 {"Start_Decomposition", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_Start_Decomposition, METH_VARARGS | METH_KEYWORDS, \ 3126 "Method to start the decomposition"}, \ 3127 {"get_Gate_Num", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Gate_Num, METH_NOARGS, \ 3128 "Method to get the number of decomposing gates"}, \ 3129 {"get_Optimized_Parameters", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Optimized_Parameters, METH_NOARGS, \ 3130 "Method to get the array of optimized parameters"}, \ 3131 {"get_Circuit", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Circuit, METH_NOARGS, \ 3132 "Method to get the incorporated circuit"}, \ 3133 {"List_Gates", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_List_Gates, METH_NOARGS, \ 3134 "Call to print the decomposing unitaries on standard output"}, \ 3135 {"set_Max_Layer_Num", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Max_Layer_Num, METH_VARARGS, \ 3136 "Set the maximal number of layers used in the subdecomposition"}, \ 3137 {"set_Iteration_Loops", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Iteration_Loops, METH_VARARGS, \ 3138 "Set the number of iteration loops during the subdecomposition"}, \ 3139 {"set_Verbose", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Verbose, METH_VARARGS, \ 3140 "Set the verbosity of the decomposition class"}, \ 3141 {"set_Debugfile", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Debugfile, METH_VARARGS, \ 3142 "Set the debugfile name of the decomposition class"}, \ 3143 {"Reorder_Qubits", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_Reorder_Qubits, METH_VARARGS, \ 3144 "Method to reorder the qubits in the decomposition class"}, \ 3145 {"set_Optimization_Tolerance", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Optimization_Tolerance, METH_VARARGS, \ 3146 "Wrapper method to set the optimization tolerance"}, \ 3147 {"set_Convergence_Threshold", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Convergence_Threshold, METH_VARARGS, \ 3148 "Wrapper method to set the threshold of convergence"}, \ 3149 {"set_Optimization_Blocks", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Optimization_Blocks, METH_VARARGS, \ 3150 "Wrapper method to set the number of gate blocks to be optimized"}, \ 3151 {"get_Parameter_Num", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Parameter_Num, METH_NOARGS, \ 3152 "Get the number of free parameters"}, \ 3153 {"set_Optimized_Parameters", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Optimized_Parameters, METH_VARARGS, \ 3154 "Set the optimized parameters"}, \ 3155 {"get_Num_of_Iters", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Num_of_Iters, METH_NOARGS, \ 3156 "Get the number of iterations"}, \ 3157 {"export_Unitary", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_export_Unitary, METH_VARARGS, \ 3158 "Export unitary matrix"}, \ 3159 {"get_Project_Name", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Project_Name, METH_NOARGS, \ 3160 "Get the name of SQUANDER project"}, \ 3161 {"set_Project_Name", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Project_Name, METH_VARARGS, \ 3162 "Set the name of SQUANDER project"}, \ 3163 {"get_Global_Phase", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Global_Phase, METH_NOARGS, \ 3164 "Call to get global phase"}, \ 3165 {"set_Global_Phase", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Global_Phase, METH_VARARGS, \ 3166 "Set global phase"}, \ 3167 {"apply_Global_Phase_Factor", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_apply_Global_Phase_Factor, METH_NOARGS, \ 3168 "Apply global phase factor"}, \ 3169 {"get_Unitary", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Unitary, METH_NOARGS, \ 3170 "Get Unitary Matrix"}, \ 3171 {"set_Optimizer", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Optimizer, METH_VARARGS | METH_KEYWORDS, \ 3172 "Set the optimizer method"}, \ 3173 {"set_Max_Iterations", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Max_Iterations, METH_VARARGS | METH_KEYWORDS, \ 3174 "Set the number of maximum iterations"}, \ 3175 {"get_Matrix", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Matrix, METH_VARARGS | METH_KEYWORDS, \ 3176 "Method to retrieve the unitary of the circuit"}, \ 3177 {"set_Cost_Function_Variant", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Cost_Function_Variant, METH_VARARGS | METH_KEYWORDS, \ 3178 "Set the cost function variant"}, \ 3179 {"Optimization_Problem", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_Optimization_Problem, METH_VARARGS, \ 3180 "Optimization problem method"}, \ 3181 {"Optimization_Problem_Combined_Unitary", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_Optimization_Problem_Combined_Unitary, METH_VARARGS, \ 3182 "Optimization problem combined unitary method"}, \ 3183 {"Optimization_Problem_Grad", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_Optimization_Problem_Grad, METH_VARARGS, \ 3184 "Optimization problem gradient method"}, \ 3185 {"Optimization_Problem_Combined", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_Optimization_Problem_Combined, METH_VARARGS, \ 3186 "Optimization problem combined method"}, \ 3187 {"Optimization_Problem_Batch", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_Optimization_Problem_Batch, METH_VARARGS, \ 3188 "Optimization problem batch method"}, \ 3189 {"Upload_Umtx_to_DFE", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_Upload_Umtx_to_DFE, METH_NOARGS, \ 3190 "Upload unitary matrix to DFE"}, \ 3191 {"get_Trace_Offset", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Trace_Offset, METH_NOARGS, \ 3192 "Get trace offset"}, \ 3193 {"set_Trace_Offset", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Trace_Offset, METH_VARARGS | METH_KEYWORDS, \ 3194 "Set trace offset"}, \ 3195 {"get_Decomposition_Error", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Decomposition_Error, METH_NOARGS, \ 3196 "Get decomposition error"}, \ 3197 {"get_Second_Renyi_Entropy", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Second_Renyi_Entropy, METH_VARARGS, \ 3198 "Get second Renyi entropy"}, \ 3199 {"get_Qbit_Num", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Qbit_Num, METH_NOARGS, \ 3200 "Get the number of qubits"}, \ 3201 {"set_Gate_Structure", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_set_Gate_Structure, METH_VARARGS, \ 3202 "Set custom gate structure for decomposition"}, \ 3203 {"add_Finalyzing_Layer_To_Gate_Structure", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_add_Finalyzing_Layer_To_Gate_Structure, METH_NOARGS, \ 3204 "Add finalizing layer to gate structure"}, \ 3205 {"get_Gates", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Gates, METH_NOARGS, \ 3206 "Get gates as a list of dictionaries"}, \ 3207 {"get_Qiskit_Circuit", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Qiskit_Circuit, METH_NOARGS, \ 3208 "Export decomposition to Qiskit QuantumCircuit format"}, \ 3209 {"get_Cirq_Circuit", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_get_Cirq_Circuit, METH_NOARGS, \ 3210 "Export decomposition to Cirq Circuit format"}, \ 3211 {"import_Qiskit_Circuit", (PyCFunction) qgd_N_Qubit_Decomposition_Wrapper_import_Qiskit_Circuit, METH_VARARGS, \ 3212 "Import Qiskit QuantumCircuit"}, \ 3221 "Set the number of identical successive blocks during subdecomposition"},
3231 "Method to get initial circuit in decomposition"},
3233 "Method to compress gate structure"},
3235 "Method to finalize the decomposition"},
3237 "Set gate structure from binary"},
3239 "Add gate structure from binary"},
3241 "Set unitary from binary"},
3243 "Call to add adaptive layers to the gate structure"},
3245 "Add layer to imported gate structure"},
3247 "Apply imported gate structure"},
3249 "Call to set unitary matrix"},
3267 "Call to set unitary matrix"},
3277 "Call to set unitary matrix"},
3281 #define decomposition_wrapper_type_template(decomp_class) \ 3282 static PyTypeObject qgd_##decomp_class##_Wrapper_Type = { \ 3283 PyVarObject_HEAD_INIT(NULL, 0) \ 3284 "qgd_N_Qubit_Decomposition_Wrapper." #decomp_class, \ 3285 sizeof(qgd_N_Qubit_Decomposition_Wrapper), \ 3287 (destructor) qgd_N_Qubit_Decomposition_Wrapper_dealloc, \ 3302 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, \ 3303 #decomp_class " decomposition wrapper", \ 3310 qgd_##decomp_class##_methods, \ 3318 (initproc) qgd_##decomp_class##_Wrapper_init, \ 3320 (newfunc) qgd_N_Qubit_Decomposition_Wrapper_new, \ 3345 static PyModuleDef qgd_N_Qubit_Decompositions_Wrapper_Module = {
3346 PyModuleDef_HEAD_INIT,
3347 "qgd_N_Qubit_Decompositions_Wrapper",
3348 "Python binding for N-Qubit Decompositions wrapper module",
3357 #define Py_INCREF_template(decomp_name) \ 3358 Py_INCREF(&qgd_##decomp_name##_Wrapper_Type); \ 3359 if (PyModule_AddObject(m, "qgd_" #decomp_name, (PyObject *) &qgd_##decomp_name##_Wrapper_Type) < 0) { \ 3360 Py_DECREF(&qgd_##decomp_name##_Wrapper_Type); \ 3376 if (PyType_Ready(&qgd_N_Qubit_Decomposition_Wrapper_Type) < 0 ||
3377 PyType_Ready(&qgd_N_Qubit_Decomposition_adaptive_Wrapper_Type) < 0 ||
3378 PyType_Ready(&qgd_N_Qubit_Decomposition_custom_Wrapper_Type) < 0 ||
3379 PyType_Ready(&qgd_N_Qubit_Decomposition_Tree_Search_Wrapper_Type) < 0 ||
3380 PyType_Ready(&qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Type) < 0) {
3384 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.
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.
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.
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.
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