27 #define PY_SSIZE_T_CLEAN 31 #include <numpy/arrayobject.h> 32 #include "structmember.h" 91 if (instance != NULL ) {
114 if ( self->decomp != NULL ) {
121 if ( self->Umtx != NULL ) {
123 Py_DECREF(self->Umtx);
127 Py_TYPE(
self)->tp_free((PyObject *)
self);
147 return (PyObject *)
self;
161 static char *kwlist[] = {(
char*)
"Umtx", (
char*)
"qbit_num", (
char*)
"method", (
char*)
"topology", (
char*)
"config", (
char*)
"accelerator_num", NULL};
164 PyArrayObject *Umtx_arg = NULL;
165 PyObject *config_arg = NULL;
169 int accelerator_num = 0;
172 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|OiiOOi", kwlist,
173 &Umtx_arg, &qbit_num, &level_limit, &topology, &config_arg, &accelerator_num))
177 if ( Umtx_arg == NULL )
return -1;
178 self->Umtx = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*) Umtx_arg, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
181 if ( !PyArray_IS_C_CONTIGUOUS(self->Umtx) ) {
182 std::cout <<
"Umtx is not memory contiguous" << std::endl;
190 bool is_None = topology == Py_None;
191 bool is_list = PyList_Check(topology);
194 if (!is_list && !is_None) {
195 printf(
"Input topology must be a list!\n");
200 std::vector<matrix_base<int>> topology_Cpp;
205 Py_ssize_t element_num = PyList_GET_SIZE(topology);
207 for ( Py_ssize_t idx=0; idx<element_num; idx++ ) {
208 PyObject *item = PyList_GetItem(topology, idx );
211 if (!PyTuple_Check(item)) {
212 printf(
"Elements of topology must be a tuple!\n");
217 item_Cpp[0] = (
int) PyLong_AsLong( PyTuple_GetItem(item, 0 ) );
218 item_Cpp[1] = (
int) PyLong_AsLong( PyTuple_GetItem(item, 1 ) );
220 topology_Cpp.push_back( item_Cpp );
227 bool is_dict = PyDict_Check( config_arg );
229 printf(
"Config object must be a python dictionary!\n");
234 std::map<std::string, Config_Element>
config;
238 PyObject *key, *value;
241 while (PyDict_Next(config_arg, &pos, &key, &value)) {
244 PyObject* key_string = PyObject_Str(key);
245 PyObject* key_string_unicode = PyUnicode_AsEncodedString(key_string,
"utf-8",
"~E~");
246 const char* key_C = PyBytes_AS_STRING(key_string_unicode);
248 std::string key_Cpp( key_C );
251 if ( PyLong_Check( value ) ) {
252 element.
set_property( key_Cpp, PyLong_AsLongLong( value ) );
253 config[ key_Cpp ] = element;
255 else if ( PyFloat_Check( value ) ) {
256 element.
set_property( key_Cpp, PyFloat_AsDouble( value ) );
257 config[ key_Cpp ] = element;
271 catch (std::string err ) {
272 PyErr_SetString(PyExc_Exception, err.c_str());
277 std::cout <<
"The number of qubits should be given as a positive integer, " << qbit_num <<
" was given" << std::endl;
297 static char *kwlist[] = {NULL};
301 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|", kwlist))
302 return Py_BuildValue(
"i", -1);
306 self->decomp->start_decomposition();
308 catch (std::string err) {
309 PyErr_SetString(PyExc_Exception, err.c_str());
310 std::cout << err << std::endl;
314 std::string err(
"Invalid pointer to decomposition class");
315 PyErr_SetString(PyExc_Exception, err.c_str());
321 return Py_BuildValue(
"i", 0);
335 int ret =
self->decomp->get_gate_num();
338 return Py_BuildValue(
"i", ret);
354 QGD_Complex16 global_phase_factor_C =
self->decomp->get_global_phase_factor();
355 PyObject* global_phase = PyFloat_FromDouble( std::atan2(global_phase_factor_C.
imag,global_phase_factor_C.
real));
368 double new_global_phase;
369 if (!PyArg_ParseTuple(args,
"|d", &new_global_phase ))
return Py_BuildValue(
"i", -1);
370 self->decomp->set_global_phase(new_global_phase);
372 return Py_BuildValue(
"i", 0);
383 self->decomp->apply_global_phase_factor();
385 return Py_BuildValue(
"i", 0);
398 PyObject* qgd_Circuit = PyImport_ImportModule(
"squander.gates.qgd_Circuit");
400 if ( qgd_Circuit == NULL ) {
401 PyErr_SetString(PyExc_Exception,
"Module import error: squander.gates.qgd_Circuit" );
411 PyObject* qgd_circuit_Dict = PyModule_GetDict( qgd_Circuit );
414 PyObject* py_circuit_class = PyDict_GetItemString( qgd_circuit_Dict,
"qgd_Circuit");
418 PyObject* circuit_input = Py_BuildValue(
"(O)", qbit_num);
420 PyObject* py_circuit = PyObject_CallObject(py_circuit_class, circuit_input);
426 delete( py_circuit_C->
gate );
442 self->decomp->list_gates( 0 );
460 self->decomp->get_optimized_parameters(parameters);
466 return parameter_arr;
481 return Py_BuildValue(
"i", parameter_num);
490 int number_of_iters =
self->decomp->get_num_iters();
492 return Py_BuildValue(
"i", number_of_iters);
503 PyArrayObject* parameters_arr = NULL;
507 if (!PyArg_ParseTuple(args,
"|O", ¶meters_arr ))
508 return Py_BuildValue(
"i", -1);
511 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
512 Py_INCREF(parameters_arr);
515 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
522 self->decomp->set_optimized_parameters(parameters_mtx.
get_data(), parameters_mtx.
size());
524 catch (std::string err ) {
525 PyErr_SetString(PyExc_Exception, err.c_str());
529 std::string err(
"Invalid pointer to decomposition class");
530 PyErr_SetString(PyExc_Exception, err.c_str());
536 Py_DECREF(parameters_arr);
538 return Py_BuildValue(
"i", 0);
553 PyObject* max_layer_num;
556 if (!PyArg_ParseTuple(args,
"|O", &max_layer_num ))
return Py_BuildValue(
"i", -1);
559 if (!PyDict_Check(max_layer_num)) {
560 printf(
"Input must be dictionary!\n");
561 return Py_BuildValue(
"i", -1);
565 PyObject* key = NULL;
566 PyObject* value = NULL;
570 while (PyDict_Next(max_layer_num, &pos, &key, &value)) {
573 assert(PyLong_Check(value) == 1);
574 int value_int = (
int) PyLong_AsLong(value);
577 assert(PyLong_Check(key) == 1);
578 int key_int = (
int) PyLong_AsLong(key);
581 self->decomp->set_max_layer_num( key_int, value_int );
585 return Py_BuildValue(
"i", 0);
603 PyObject* iteration_loops;
606 if (!PyArg_ParseTuple(args,
"|O", &iteration_loops ))
return Py_BuildValue(
"i", -1);
609 if (!PyDict_Check(iteration_loops)) {
610 printf(
"Input must be dictionary!\n");
611 return Py_BuildValue(
"i", -1);
615 PyObject* key = NULL;
616 PyObject* value = NULL;
620 while (PyDict_Next(iteration_loops, &pos, &key, &value)) {
623 assert(PyLong_Check(value) == 1);
624 int value_int = (
int) PyLong_AsLong(value);
627 assert(PyLong_Check(key) == 1);
628 int key_int = (
int) PyLong_AsLong(key);
631 self->decomp->set_iteration_loops( key_int, value_int );
635 return Py_BuildValue(
"i", 0);
650 if (!PyArg_ParseTuple(args,
"|i", &max_iters_input ))
return Py_BuildValue(
"i", -1);
654 self->decomp->set_max_inner_iterations(max_iters_input);
657 return Py_BuildValue(
"i", 0);
673 if (!PyArg_ParseTuple(args,
"|i", &verbose ))
return Py_BuildValue(
"i", -1);
677 self->decomp->set_verbose( verbose );
680 return Py_BuildValue(
"i", 0);
694 PyObject *debugfile = NULL;
697 if (!PyArg_ParseTuple(args,
"|O", &debugfile ))
return Py_BuildValue(
"s", -1);
700 PyObject* debugfile_string = PyObject_Str(debugfile);
701 PyObject* debugfile_string_unicode = PyUnicode_AsEncodedString(debugfile_string,
"utf-8",
"~E~");
702 const char* debugfile_C = PyBytes_AS_STRING(debugfile_string_unicode);
705 Py_XDECREF(debugfile_string);
706 Py_XDECREF(debugfile_string_unicode);
709 Py_ssize_t string_length = PyBytes_Size(debugfile_string_unicode);
710 std::string debugfile_Cpp(debugfile_C, string_length);
713 self->decomp->set_debugfile( debugfile_Cpp );
716 return Py_BuildValue(
"s", NULL);
734 if (!PyArg_ParseTuple(args,
"|d", &tolerance ))
return Py_BuildValue(
"i", -1);
738 self->decomp->set_optimization_tolerance( tolerance );
741 return Py_BuildValue(
"i", 0);
759 if (!PyArg_ParseTuple(args,
"|d", &threshold ))
return Py_BuildValue(
"i", -1);
763 self->decomp->set_convergence_threshold( threshold );
765 return Py_BuildValue(
"i", 0);
779 double optimization_block;
782 if (!PyArg_ParseTuple(args,
"|d", &optimization_block ))
return Py_BuildValue(
"i", -1);
786 self->decomp->set_optimization_blocks( optimization_block );
789 return Py_BuildValue(
"i", 0);
804 std::string
project_name =
self->decomp->get_project_name();
807 PyObject* project_name_pyhton = PyUnicode_FromString(project_name.c_str());
809 return project_name_pyhton;
822 PyObject* project_name_new=NULL;
825 if (!PyArg_ParseTuple(args,
"|O", &project_name_new))
return Py_BuildValue(
"i", -1);
828 PyObject* project_name_new_string = PyObject_Str(project_name_new);
829 PyObject* project_name_new_unicode = PyUnicode_AsEncodedString(project_name_new_string,
"utf-8",
"~E~");
830 const char* project_name_new_C = PyBytes_AS_STRING(project_name_new_unicode);
831 std::string project_name_new_str = ( project_name_new_C );
834 self->decomp->set_project_name(project_name_new_str);
836 return Py_BuildValue(
"i", 0);
851 return Py_BuildValue(
"d", decomposition_error);
864 if (!PyArg_ParseTuple(args,
"|O", &filename))
return Py_BuildValue(
"i", -1);
867 PyObject* filename_string = PyObject_Str(filename);
868 PyObject* filename_unicode = PyUnicode_AsEncodedString(filename_string,
"utf-8",
"~E~");
869 const char* filename_C = PyBytes_AS_STRING(filename_unicode);
870 std::string filename_str = ( filename_C );
873 self->decomp->export_unitary(filename_str);
875 return Py_BuildValue(
"i", 0);
889 Unitary_mtx =
self->decomp->get_Umtx().
copy();
891 catch (std::string err ) {
892 PyErr_SetString(PyExc_Exception, err.c_str());
896 std::string err(
"Invalid pointer to decomposition class");
897 PyErr_SetString(PyExc_Exception, err.c_str());
919 PyArrayObject* parameters_arg = NULL;
923 if (!PyArg_ParseTuple(args,
"|O", ¶meters_arg )) {
925 std::string err(
"Unsuccessful argument parsing not ");
926 PyErr_SetString(PyExc_Exception, err.c_str());
932 if ( PyArray_IS_C_CONTIGUOUS(parameters_arg) && PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ){
933 Py_INCREF(parameters_arg);
935 else if (PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ) {
936 parameters_arg = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arg, NPY_FLOAT64, NPY_ARRAY_IN_ARRAY);
939 std::string err(
"Parameters should be should be real (given in float64 format)");
940 PyErr_SetString(PyExc_Exception, err.c_str());
949 f0 =
self->decomp->optimization_problem(parameters_mtx );
951 catch (std::string err ) {
952 PyErr_SetString(PyExc_Exception, err.c_str());
956 std::string err(
"Invalid pointer to decomposition class");
957 PyErr_SetString(PyExc_Exception, err.c_str());
961 Py_DECREF(parameters_arg);
964 return Py_BuildValue(
"d", f0);
977 PyArrayObject* parameters_arg = NULL;
981 if (!PyArg_ParseTuple(args,
"|O", ¶meters_arg )) {
983 std::string err(
"Unsuccessful argument parsing not ");
984 PyErr_SetString(PyExc_Exception, err.c_str());
990 if ( PyArray_IS_C_CONTIGUOUS(parameters_arg) && PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ){
991 Py_INCREF(parameters_arg);
993 else if (PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ) {
994 parameters_arg = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arg, NPY_FLOAT64, NPY_ARRAY_IN_ARRAY);
997 std::string err(
"Parameters should be should be real (given in float64 format)");
998 PyErr_SetString(PyExc_Exception, err.c_str());
1007 self->decomp->optimization_problem_grad(parameters_mtx, self->decomp, grad_mtx );
1009 catch (std::string err ) {
1010 PyErr_SetString(PyExc_Exception, err.c_str());
1014 std::string err(
"Invalid pointer to decomposition class");
1015 PyErr_SetString(PyExc_Exception, err.c_str());
1020 grad_mtx.set_owner(
false);
1023 Py_DECREF(parameters_arg);
1038 PyArrayObject* parameters_arg = NULL;
1042 if (!PyArg_ParseTuple(args,
"|O", ¶meters_arg )) {
1044 std::string err(
"Unsuccessful argument parsing not ");
1045 PyErr_SetString(PyExc_Exception, err.c_str());
1051 if ( PyArray_IS_C_CONTIGUOUS(parameters_arg) && PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ){
1052 Py_INCREF(parameters_arg);
1054 else if (PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ) {
1055 parameters_arg = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arg, NPY_FLOAT64, NPY_ARRAY_IN_ARRAY);
1058 std::string err(
"Parameters should be should be real (given in float64 format)");
1059 PyErr_SetString(PyExc_Exception, err.c_str());
1069 self->decomp->optimization_problem_combined(parameters_mtx, &f0, grad_mtx );
1071 catch (std::string err ) {
1072 PyErr_SetString(PyExc_Exception, err.c_str());
1076 std::string err(
"Invalid pointer to decomposition class");
1077 PyErr_SetString(PyExc_Exception, err.c_str());
1082 grad_mtx.set_owner(
false);
1085 Py_DECREF(parameters_arg);
1088 PyObject* p = Py_BuildValue(
"(dO)", f0, grad_py);
1102 PyArrayObject* parameters_arg = NULL;
1106 if (!PyArg_ParseTuple(args,
"|O", ¶meters_arg )) {
1108 std::string err(
"Unsuccessful argument parsing not ");
1109 PyErr_SetString(PyExc_Exception, err.c_str());
1115 if ( PyArray_IS_C_CONTIGUOUS(parameters_arg) && PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ){
1116 Py_INCREF(parameters_arg);
1118 else if (PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ) {
1119 parameters_arg = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arg, NPY_FLOAT64, NPY_ARRAY_IN_ARRAY);
1122 std::string err(
"Parameters should be should be real (given in float64 format)");
1123 PyErr_SetString(PyExc_Exception, err.c_str());
1130 std::vector<Matrix> Umtx_deriv;
1133 self->decomp->optimization_problem_combined_unitary(parameters_mtx, Umtx, Umtx_deriv );
1135 catch (std::string err ) {
1136 PyErr_SetString(PyExc_Exception, err.c_str());
1140 std::string err(
"Invalid pointer to decomposition class");
1141 PyErr_SetString(PyExc_Exception, err.c_str());
1148 PyObject* graduni_py = PyList_New(Umtx_deriv.size());
1149 for (
size_t i = 0; i < Umtx_deriv.size(); i++) {
1150 Umtx_deriv[i].set_owner(
false);
1154 Py_DECREF(parameters_arg);
1157 PyObject* p = Py_BuildValue(
"(OO)", unitary_py, graduni_py);
1158 Py_DECREF(unitary_py); Py_DECREF(graduni_py);
1171 PyArrayObject* parameters_arg = NULL;
1175 if (!PyArg_ParseTuple(args,
"|O", ¶meters_arg )) {
1177 std::string err(
"Unsuccessful argument parsing not ");
1178 PyErr_SetString(PyExc_Exception, err.c_str());
1184 if ( PyArray_IS_C_CONTIGUOUS(parameters_arg) && PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ){
1185 Py_INCREF(parameters_arg);
1187 else if (PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ) {
1188 parameters_arg = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arg, NPY_FLOAT64, NPY_ARRAY_IN_ARRAY);
1191 std::string err(
"Parameters should be should be real (given in float64 format)");
1192 PyErr_SetString(PyExc_Exception, err.c_str());
1201 std::vector<Matrix_real> parameters_vec;
1202 parameters_vec.resize(parameters_mtx.
rows);
1203 for(
int row_idx=0; row_idx<parameters_mtx.
rows; row_idx++ ) {
1206 result_mtx =
self->decomp->optimization_problem_batched( parameters_vec );
1208 catch (std::string err ) {
1209 PyErr_SetString(PyExc_Exception, err.c_str());
1213 std::string err(
"Invalid pointer to decomposition class");
1214 PyErr_SetString(PyExc_Exception, err.c_str());
1222 Py_DECREF(parameters_arg);
1231 if ( self->Umtx != NULL ) {
1233 Py_DECREF(self->Umtx);
1237 PyArrayObject *Umtx_arg = NULL;
1239 if (!PyArg_ParseTuple(args,
"|O", &Umtx_arg ))
return Py_BuildValue(
"i", -1);
1242 if ( Umtx_arg == NULL ) {
1243 PyErr_SetString(PyExc_Exception,
"Umtx argument in empty");
1247 self->Umtx = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)Umtx_arg, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
1250 if ( !PyArray_IS_C_CONTIGUOUS(self->Umtx) ) {
1251 std::cout <<
"Umtx is not memory contiguous" << std::endl;
1257 self->decomp->set_unitary(Umtx_mtx);
1259 return Py_BuildValue(
"i", 0);
1270 PyObject* qbit_list;
1273 if (!PyArg_ParseTuple(args,
"|O", &qbit_list ))
return Py_BuildValue(
"i", -1);
1275 bool is_tuple = PyTuple_Check(qbit_list);
1276 bool is_list = PyList_Check(qbit_list);
1279 if (!is_list && !is_tuple) {
1280 printf(
"Input must be tuple or list!\n");
1281 return Py_BuildValue(
"i", -1);
1285 Py_ssize_t element_num;
1288 element_num = PyTuple_GET_SIZE(qbit_list);
1291 element_num = PyList_GET_SIZE(qbit_list);
1296 std::vector<int> qbit_list_C( (
int) element_num);
1297 for ( Py_ssize_t idx=0; idx<element_num; idx++ ) {
1299 qbit_list_C[(
int) idx] = (
int) PyLong_AsLong( PyTuple_GetItem(qbit_list, idx ) );
1302 qbit_list_C[(
int) idx] = (
int) PyLong_AsLong( PyList_GetItem(qbit_list, idx ) );
1309 self->decomp->reorder_qubits( qbit_list_C );
1314 return Py_BuildValue(
"i", 0);
1329 PyArrayObject* parameters_arr = NULL;
1333 if (!PyArg_ParseTuple(args,
"|O", ¶meters_arr ))
1334 return Py_BuildValue(
"i", -1);
1337 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
1338 Py_INCREF(parameters_arr);
1341 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
1351 unitary_mtx =
self->decomp->get_matrix( parameters_mtx );
1359 Py_DECREF(parameters_arr);
1376 static char *kwlist[] = {(
char*)
"optimizer", NULL};
1378 PyObject* optimizer_arg = NULL;
1382 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|O", kwlist, &optimizer_arg)) {
1384 std::string err(
"Unsuccessful argument parsing not ");
1385 PyErr_SetString(PyExc_Exception, err.c_str());
1391 if ( optimizer_arg == NULL ) {
1392 std::string err(
"optimizer argument not set");
1393 PyErr_SetString(PyExc_Exception, err.c_str());
1399 PyObject* optimizer_string = PyObject_Str(optimizer_arg);
1400 PyObject* optimizer_string_unicode = PyUnicode_AsEncodedString(optimizer_string,
"utf-8",
"~E~");
1401 const char* optimizer_C = PyBytes_AS_STRING(optimizer_string_unicode);
1404 if ( strcmp(
"bfgs", optimizer_C) == 0 || strcmp(
"BFGS", optimizer_C) == 0) {
1405 qgd_optimizer =
BFGS;
1407 else if ( strcmp(
"adam", optimizer_C)==0 || strcmp(
"ADAM", optimizer_C)==0) {
1408 qgd_optimizer =
ADAM;
1410 else if ( strcmp(
"grad_descend", optimizer_C)==0 || strcmp(
"GRAD_DESCEND", optimizer_C)==0) {
1413 else if ( strcmp(
"adam_batched", optimizer_C)==0 || strcmp(
"ADAM_BATCHED", optimizer_C)==0) {
1416 else if ( strcmp(
"bfgs2", optimizer_C)==0 || strcmp(
"BFGS2", optimizer_C)==0) {
1417 qgd_optimizer =
BFGS2;
1419 else if ( strcmp(
"agents", optimizer_C)==0 || strcmp(
"AGENTS", optimizer_C)==0) {
1422 else if ( strcmp(
"cosine", optimizer_C)==0 || strcmp(
"COSINE", optimizer_C)==0) {
1425 else if ( strcmp(
"grad_descend_phase_shift_rule", optimizer_C)==0 || strcmp(
"GRAD_DESCEND_PARAMETER_SHIFT_RULE", optimizer_C)==0) {
1428 else if ( strcmp(
"agents_combined", optimizer_C)==0 || strcmp(
"AGENTS_COMBINED", optimizer_C)==0) {
1431 else if ( strcmp(
"bayes_opt", optimizer_C)==0 || strcmp(
"BAYES_OPT", optimizer_C)==0) {
1435 std::cout <<
"Wrong optimizer: " << optimizer_C <<
". Using default: BFGS" << std::endl;
1436 qgd_optimizer =
BFGS;
1441 self->decomp->set_optimizer(qgd_optimizer);
1443 catch (std::string err) {
1444 PyErr_SetString(PyExc_Exception, err.c_str());
1445 std::cout << err << std::endl;
1449 std::string err(
"Invalid pointer to decomposition class");
1450 PyErr_SetString(PyExc_Exception, err.c_str());
1455 return Py_BuildValue(
"i", 0);
1471 static char *kwlist[] = {(
char*)
"costfnc", NULL};
1473 int costfnc_arg = 0;
1477 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|i", kwlist, &costfnc_arg)) {
1479 std::string err(
"Unsuccessful argument parsing");
1480 PyErr_SetString(PyExc_Exception, err.c_str());
1489 self->decomp->set_cost_function_variant(qgd_costfnc);
1491 catch (std::string err) {
1492 PyErr_SetString(PyExc_Exception, err.c_str());
1493 std::cout << err << std::endl;
1497 std::string err(
"Invalid pointer to decomposition class");
1498 PyErr_SetString(PyExc_Exception, err.c_str());
1503 return Py_BuildValue(
"i", 0);
1521 static char *kwlist[] = {(
char*)
"trace_offset", NULL};
1523 int trace_offset_arg = 0;
1527 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|i", kwlist, &trace_offset_arg)) {
1529 std::string err(
"Unsuccessful argument parsing");
1530 PyErr_SetString(PyExc_Exception, err.c_str());
1537 self->decomp->set_trace_offset(trace_offset_arg);
1539 catch (std::string err) {
1540 PyErr_SetString(PyExc_Exception, err.c_str());
1541 std::cout << err << std::endl;
1545 std::string err(
"Invalid pointer to decomposition class");
1546 PyErr_SetString(PyExc_Exception, err.c_str());
1551 return Py_BuildValue(
"i", 0);
1565 int trace_offset = 0;
1568 trace_offset =
self->decomp->get_trace_offset();
1570 catch (std::string err) {
1571 PyErr_SetString(PyExc_Exception, err.c_str());
1572 std::cout << err << std::endl;
1576 std::string err(
"Invalid pointer to decomposition class");
1577 PyErr_SetString(PyExc_Exception, err.c_str());
1582 return Py_BuildValue(
"i", trace_offset);
1598 self->decomp->upload_Umtx_to_DFE();
1600 catch (std::string err) {
1601 PyErr_SetString(PyExc_Exception, err.c_str());
1602 std::cout << err << std::endl;
1606 std::string err(
"Invalid pointer to decomposition class");
1607 PyErr_SetString(PyExc_Exception, err.c_str());
1613 return Py_BuildValue(
"i", 0);
1630 PyArrayObject * parameters_arr = NULL;
1631 PyArrayObject * input_state_arg = NULL;
1632 PyObject * qubit_list_arg = NULL;
1636 if (!PyArg_ParseTuple(args,
"|OOO", ¶meters_arr, &input_state_arg, &qubit_list_arg ))
1637 return Py_BuildValue(
"i", -1);
1640 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
1641 Py_INCREF(parameters_arr);
1644 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF((PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
1652 if ( input_state_arg == NULL ) {
1653 PyErr_SetString(PyExc_Exception,
"Input matrix was not given");
1657 PyArrayObject* input_state = (PyArrayObject*)PyArray_FROM_OTF((PyObject*)input_state_arg, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
1660 if ( !PyArray_IS_C_CONTIGUOUS(input_state) ) {
1661 PyErr_SetString(PyExc_Exception,
"input mtrix is not memory contiguous");
1671 if ( qubit_list_arg == NULL || (!PyList_Check( qubit_list_arg )) ) {
1672 PyErr_SetString(PyExc_Exception,
"qubit_list should be a list");
1676 Py_ssize_t reduced_qbit_num = PyList_Size( qubit_list_arg );
1679 for (
int idx=0; idx<reduced_qbit_num; idx++ ) {
1681 PyObject* item = PyList_GET_ITEM( qubit_list_arg, idx );
1682 qbit_list_mtx[idx] = (
int) PyLong_AsLong( item );
1691 entropy =
self->decomp->get_second_Renyi_entropy( parameters_mtx, input_state_mtx, qbit_list_mtx );
1693 catch (std::string err) {
1694 PyErr_SetString(PyExc_Exception, err.c_str());
1695 std::cout << err << std::endl;
1699 std::string err(
"Invalid pointer to decomposition class");
1700 PyErr_SetString(PyExc_Exception, err.c_str());
1705 Py_DECREF(parameters_arr);
1706 Py_DECREF(input_state);
1710 PyObject* p = Py_BuildValue(
"d", entropy);
1725 qbit_num =
self->decomp->get_qbit_num();
1727 catch (std::string err) {
1728 PyErr_SetString(PyExc_Exception, err.c_str());
1729 std::cout << err << std::endl;
1733 std::string err(
"Invalid pointer to decomposition class");
1734 PyErr_SetString(PyExc_Exception, err.c_str());
1739 return Py_BuildValue(
"i", qbit_num );
1757 "Method to start the decomposition." 1760 "Method to get the number of decomposing gates." 1763 "Call to get the number of free parameters in the gate structure used for the decomposition" 1766 "Method to get the array of optimized parameters." 1769 "Method to set the initial array of optimized parameters." 1772 "Method to get the incorporated circuit." 1775 "Call to print the decomposing nitaries on standard output" 1778 "Method to get the number of iterations." 1781 "Call to set the maximal number of layers used in the subdecomposition of the qbit-th qubit." 1784 "Call to set the number of iteration loops during the subdecomposition of the qbit-th qubit." 1787 "Call to set the verbosity of the qgd_N_Qubit_Decomposition class." 1790 "Set the debugfile name of the N_Qubit_Decomposition class." 1793 "Wrapper method to reorder the qubits in the decomposition class." 1796 "Wrapper method to set the optimization tolerance of the optimization process during the decomposition." 1799 "Wrapper method to set the threshold of convergence in the optimization processes." 1802 "Wrapper method to to set the number of gate blocks to be optimized in one shot." 1805 "Call to set unitary matrix to a numpy matrix" 1808 "Call to export unitary matrix to a binary file" 1811 "Call to get the name of SQUANDER project" 1814 "Call to set the name of SQUANDER project" 1817 "Call to get global phase" 1820 "Call to set global phase" 1823 "Call to apply global phase on Unitary matrix" 1826 "Call to get Unitary Matrix" 1829 "Wrapper method to to set the optimizer method for the gate synthesis." 1832 "Wrapper method to to set the maximum number of iterations for the gate synthesis." 1835 "Method to retrieve the unitary of the circuit." 1838 "Wrapper method to to set the variant of the cost function. Input argument 0 stands for FROBENIUS_NORM, 1 for FROBENIUS_NORM_CORRECTION1, 2 for FROBENIUS_NORM_CORRECTION2, 3 for HILBERT_SCHMIDT_TEST, 4 for HILBERT_SCHMIDT_TEST_CORRECTION1, 5 for HILBERT_SCHMIDT_TEST_CORRECTION2." 1841 "Wrapper function to evaluate the cost function." 1844 "Wrapper function to evaluate the unitary function and the gradient components." 1847 "Wrapper function to evaluate the gradient components." 1850 "Wrapper function to evaluate the cost function and the gradient components." 1853 "Wrapper function to evaluate the cost function of batch." 1856 "Call to upload the unitary to the DFE. (Has no effect for non-DFE builds)" 1859 "Call to get the trace offset used in the cost function. In this case Tr(A) = sum_(i-offset=j) A_{ij}" 1862 "Call to set the trace offset used in the cost function. In this case Tr(A) = sum_(i-offset=j) A_{ij}" 1865 "Call to get the error of the decomposition. (i.e. the final value of the cost function)" 1868 "Wrapper function to evaluate the second Rényi entropy of a quantum circuit at a specific parameter set." 1871 "Call to get the number of qubits in the circuit" 1880 PyVarObject_HEAD_INIT(NULL, 0)
1881 "qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper.qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper",
1885 #if PY_VERSION_HEX < 0x030800b4 1888 #if PY_VERSION_HEX >= 0x030800b4 1893 #if PY_MAJOR_VERSION < 3 1896 #if PY_MAJOR_VERSION >= 3 1909 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1910 "Object to represent a Circuit class of the QGD package.",
1937 #
if PY_VERSION_HEX >= 0x030400a1
1940 #
if PY_VERSION_HEX >= 0x030800b1
1943 #
if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000
1952 PyModuleDef_HEAD_INIT,
1953 "qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper",
1954 "Python binding for QGD N_Qubit_Decomposition class",
1969 if (PyType_Ready(&qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Type) < 0)
1972 m = PyModule_Create(&qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Module);
1976 Py_INCREF(&qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Type);
1977 if (PyModule_AddObject(m,
"qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper", (PyObject *) &qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Type) < 0) {
1978 Py_DECREF(&qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Type);
Gates_block * get_flat_circuit()
Method to generate a flat circuit.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Unitary(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self)
get Unitary
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Matrix(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args)
Retrieve the unified unitary operation of the circuit.
N_Qubit_Decomposition_Tabu_Search * create_N_Qubit_Decomposition_Tabu_Search(Matrix &Umtx, int qbit_num, int level_limit, std::vector< matrix_base< int >> topology_in, std::map< std::string, Config_Element > &config, int accelerator_num)
Constructor of the class.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Optimizer(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args, PyObject *kwds)
Wrapper function to set custom gate structure for the decomposition.
parameter_num
[set adaptive gate structure]
static void qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_dealloc(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self)
Method called when a python instance of the class qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper is de...
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Cost_Function_Variant(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args, PyObject *kwds)
Wrapper function to set a variant for the cost function.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Project_Name(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self)
get project name
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Max_Layer_Num(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args)
Set the maximal number of layers used in the subdecomposition of the qbit-th qubit.
static int qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_init(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args, PyObject *kwds)
Method called when a python instance of the class qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper is in...
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Second_Renyi_Entropy(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args)
Wrapper function to evaluate the second Rényi entropy of a quantum circuit at a specific parameter s...
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_real numpy2matrix_real(PyArrayObject *arr)
Call to create a PIC matrix_real representation of a numpy array.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Optimization_Problem_Batch(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args)
Wrapper function to evaluate the cost function an dthe gradient components.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Debugfile(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args)
Set the debugfile name of the N_Qubit_Decomposition class.
static PyModuleDef qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Module
Structure containing metadata about the module.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Optimization_Problem_Combined(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args)
Wrapper function to evaluate the cost function an dthe gradient components.
Header file for a class responsible for grouping gates into subcircuits. (Subcircuits can be nested) ...
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_Tabu_Search_Wrapper_Reorder_Qubits(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args)
Wrapper method to reorder the qubits in the decomposition class.
static PyMethodDef qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_methods[]
Structure containing metadata about the methods of class qgd_N_Qubit_Decomposition_Tabu_Search_Wrappe...
A class describing a universal configuration element.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Unitary(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args)
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.
N_Qubit_Decomposition_Tabu_Search * decomp
An object to decompose the unitary.
optimization_aglorithms
implemented optimization strategies
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_gate_num(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self)
Wrapper function to get the number of decomposing gates.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Qbit_Num(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self)
Call to retrieve the number of qubits in the circuit.
Type definition of the qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper Python class of the qgd_N_Qubit_...
int rows
The number of rows.
int cols
The number of columns.
PyObject_HEAD Gates_block * gate
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Start_Decomposition(qgd_N_Qubit_Decomposition_Tabu_Search_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_Tabu_Search_Wrapper_set_Max_Iterations(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args)
Set the number of maximum iterations.
Umtx
The unitary to be decomposed.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Project_Name(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args)
set project 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...
Structure type representing complex numbers in the SQUANDER package.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Optimization_Blocks(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args)
Wrapper method to to set the number of gate blocks to be optimized in one shot.
static PyMemberDef qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_members[]
Structure containing metadata about the members of class qgd_N_Qubit_Decomposition_Tabu_Search_Wrappe...
dictionary config
gate systhesis #####################################
Class to store data of complex arrays and its properties.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_List_Gates(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self)
Lists the gates decomposing the initial unitary.
int size() const
Call to get the number of the allocated elements.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Global_Phase(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self)
returns the angle of the global phase (the radius us always sqrt(2))
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Optimization_Problem_Grad(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args)
Wrapper function to evaluate the cost function an dthe gradient components.
void release_N_Qubit_Decomposition_Tabu_Search(N_Qubit_Decomposition_Tabu_Search *instance)
Call to deallocate an instance of N_Qubit_Decomposition_Tabu_Search class.
cost_function_type
Type definition of the fifferent types of the cost function.
A class responsible for grouping two-qubit (CNOT,CZ,CH) and one-qubit gates into layers.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Iteration_Loops(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args)
Set the number of iteration loops during the subdecomposition of the qbit-th qubit.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Optimization_Problem_Combined_Unitary(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args)
Wrapper function to evaluate the unitary function and the unitary derivates.
Header file for a class implementing the adaptive gate decomposition algorithm of arXiv:2203...
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Optimization_Problem(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args)
Wrapper function to evaluate the cost function.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Optimization_Tolerance(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args)
Wrapper method to set the optimization tolerance of the optimization process during the decomposition...
void set_property(std::string name_, double val_)
Call to set a double value.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Trace_Offset(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self)
Wrapper function to get the trace offset used in the cost function.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_circuit(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self)
Wrapper function to retrieve the circuit (Squander format) incorporated in the instance.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Optimized_Parameters(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self)
Extract the optimized parameters.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Method called when a python instance of the class qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper is al...
static PyTypeObject qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Type
A structure describing the type of the class qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Verbose(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args)
Set the verbosity of the N_Qubit_Decomposition class.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_export_Unitary(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args)
export unitary to binary file
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_apply_Global_Phase_Factor(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self)
applies the global phase to the Unitary matrix
Matrix numpy2matrix(PyArrayObject *arr)
Call to create a PIC matrix representation of a numpy array.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Parameter_Num(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self)
Get the number of free parameters in the gate structure used for the decomposition.
PyMODINIT_FUNC PyInit_qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper(void)
Method called when the Python module is initialized.
PyObject_HEAD Gates_block * circuit
Pointer to the C++ class of the base Gate_block module.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Upload_Umtx_to_DFE(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self)
Call to upload the unitary to the DFE.
Matrix copy()
Call to create a copy of the matrix.
double real
the real part of a complex number
int get_qbit_num()
Call to get the number of qubits composing the unitary.
Type definition of the qgd_Circuit_Wrapper Python class of the qgd_Circuit_Wrapper module...
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Global_Phase(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args)
sets the global phase to the new angle given
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Decomposition_Error(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self)
Cll to get the error of the decomposition (i.e.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Optimized_Parameters(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args)
Extract the optimized parameters.
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Convergence_Threshold(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args)
Wrapper method to set the threshold of convergence in the optimization processes. ...
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Trace_Offset(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self, PyObject *args, PyObject *kwds)
Wrapper function to set the trace offset used in the cost function.
PyObject * matrix_to_numpy(Matrix &mtx)
Call to make a numpy array from an instance of matrix class.
tuple decomposition_error
PyObject_HEAD PyArrayObject * Umtx
pointer to the unitary to be decomposed to keep it alive
static PyObject * qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Num_of_Iters(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *self)
Get the number of free parameters in the gate structure used for the decomposition.
Class to store data of complex arrays and its properties.
double imag
the imaginary part of a complex number