Sequential Quantum Gate Decomposer  v1.9.3
Powerful decomposition of general unitarias into one- and two-qubit gates gates
qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper.cpp
Go to the documentation of this file.
1 /*
2 Created on Fri Jun 26 14:42:56 2020
3 Copyright 2020 Peter Rakyta, Ph.D.
4 
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8 
9  http://www.apache.org/licenses/LICENSE-2.0
10 
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see http://www.gnu.org/licenses/.
19 
20 @author: Peter Rakyta, Ph.D.
21 */
22 /*
23 \file qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper.cpp
24 \brief Python interface for the N_Qubit_Decomposition class
25 */
26 
27 #define PY_SSIZE_T_CLEAN
28 
29 
30 #include <Python.h>
31 #include <numpy/arrayobject.h>
32 #include "structmember.h"
33 #include <stdio.h>
35 #include "Gates_block.h"
36 
37 #include "numpy_interface.h"
38 
39 
40 
41 
45 typedef struct qgd_Circuit_Wrapper {
46  PyObject_HEAD
49 
50 
55  PyObject_HEAD
57  PyArrayObject *Umtx;
61 
63 
64 
76 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 ) {
77 
78  return new N_Qubit_Decomposition_Tabu_Search( Umtx, qbit_num, level_limit, topology_in, config, accelerator_num );
79 }
80 
81 
82 
83 
88 void
90 
91  if (instance != NULL ) {
92  delete instance;
93  }
94  return;
95 }
96 
97 
98 
99 
100 
101 
102 extern "C"
103 {
104 
105 
110 static void
112 {
113 
114  if ( self->decomp != NULL ) {
115  // deallocate the instance of class N_Qubit_Decomposition
117  self->decomp = NULL;
118  }
119 
120 
121  if ( self->Umtx != NULL ) {
122  // release the unitary to be decomposed
123  Py_DECREF(self->Umtx);
124  self->Umtx = NULL;
125  }
126 
127  Py_TYPE(self)->tp_free((PyObject *) self);
128 
129 }
130 
135 static PyObject *
137 {
139  self = (qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper *) type->tp_alloc(type, 0);
140  if (self != NULL) {
141 
142  self->decomp = NULL;
143  self->Umtx = NULL;
144 
145  }
146 
147  return (PyObject *) self;
148 }
149 
150 
157 static int
159 {
160  // The tuple of expected keywords
161  static char *kwlist[] = {(char*)"Umtx", (char*)"qbit_num", (char*)"method", (char*)"topology", (char*)"config", (char*)"accelerator_num", NULL};
162 
163  // initiate variables for input arguments
164  PyArrayObject *Umtx_arg = NULL;
165  PyObject *config_arg = NULL;
166  int qbit_num = -1;
167  int level_limit = 0;
168  PyObject *topology = NULL;
169  int accelerator_num = 0;
170 
171  // parsing input arguments
172  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OiiOOi", kwlist,
173  &Umtx_arg, &qbit_num, &level_limit, &topology, &config_arg, &accelerator_num))
174  return -1;
175 
176  // convert python object array to numpy C API array
177  if ( Umtx_arg == NULL ) return -1;
178  self->Umtx = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*) Umtx_arg, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
179 
180  // test C-style contiguous memory allocation of the array
181  if ( !PyArray_IS_C_CONTIGUOUS(self->Umtx) ) {
182  std::cout << "Umtx is not memory contiguous" << std::endl;
183  }
184 
185 
186  // create QGD version of the Umtx
187  Matrix Umtx_mtx = numpy2matrix(self->Umtx);
188 
189  // elaborate connectivity topology
190  bool is_None = topology == Py_None;
191  bool is_list = PyList_Check(topology);
192 
193  // Check whether input is a list
194  if (!is_list && !is_None) {
195  printf("Input topology must be a list!\n");
196  return -1;
197  }
198 
199  // create C++ variant of the list
200  std::vector<matrix_base<int>> topology_Cpp;
201 
202  if ( !is_None ) {
203 
204  // get the number of qbubits
205  Py_ssize_t element_num = PyList_GET_SIZE(topology);
206 
207  for ( Py_ssize_t idx=0; idx<element_num; idx++ ) {
208  PyObject *item = PyList_GetItem(topology, idx );
209 
210  // Check whether input is a list
211  if (!PyTuple_Check(item)) {
212  printf("Elements of topology must be a tuple!\n");
213  return -1;
214  }
215 
216  matrix_base<int> item_Cpp(1,2);
217  item_Cpp[0] = (int) PyLong_AsLong( PyTuple_GetItem(item, 0 ) );
218  item_Cpp[1] = (int) PyLong_AsLong( PyTuple_GetItem(item, 1 ) );
219 
220  topology_Cpp.push_back( item_Cpp );
221  }
222  }
223 
224 
225  // parse config and create C++ version of the hyperparameters
226 
227  bool is_dict = PyDict_Check( config_arg );
228  if (!is_dict) {
229  printf("Config object must be a python dictionary!\n");
230  return -1;
231  }
232 
233  // integer type config metadata utilized during the optimization
234  std::map<std::string, Config_Element> config;
235 
236 
237  // keys and values of the config dict
238  PyObject *key, *value;
239  Py_ssize_t pos = 0;
240 
241  while (PyDict_Next(config_arg, &pos, &key, &value)) {
242 
243  // determine the initial guess type
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);
247 
248  std::string key_Cpp( key_C );
249  Config_Element element;
250 
251  if ( PyLong_Check( value ) ) {
252  element.set_property( key_Cpp, PyLong_AsLongLong( value ) );
253  config[ key_Cpp ] = element;
254  }
255  else if ( PyFloat_Check( value ) ) {
256  element.set_property( key_Cpp, PyFloat_AsDouble( value ) );
257  config[ key_Cpp ] = element;
258  }
259  else {
260 
261  }
262 
263  }
264 
265 
266  // create an instance of the class N_Qubit_Decomposition
267  if (qbit_num > 0 ) {
268  try {
269  self->decomp = create_N_Qubit_Decomposition_Tabu_Search( Umtx_mtx, qbit_num, level_limit, topology_Cpp, config, accelerator_num);
270  }
271  catch (std::string err ) {
272  PyErr_SetString(PyExc_Exception, err.c_str());
273  return -1;
274  }
275  }
276  else {
277  std::cout << "The number of qubits should be given as a positive integer, " << qbit_num << " was given" << std::endl;
278  return -1;
279  }
280 
281 
282 
283  return 0;
284 }
285 
292 static PyObject *
294 {
295 
296  // The tuple of expected keywords
297  static char *kwlist[] = {NULL};
298 
299 
300  // parsing input arguments
301  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|", kwlist))
302  return Py_BuildValue("i", -1);
303 
304  // starting the decomposition
305  try {
306  self->decomp->start_decomposition();
307  }
308  catch (std::string err) {
309  PyErr_SetString(PyExc_Exception, err.c_str());
310  std::cout << err << std::endl;
311  return NULL;
312  }
313  catch(...) {
314  std::string err( "Invalid pointer to decomposition class");
315  PyErr_SetString(PyExc_Exception, err.c_str());
316  return NULL;
317  }
318 
319 
320 
321  return Py_BuildValue("i", 0);
322 }
323 
324 
325 
331 static PyObject *
333 
334  // get the number of gates
335  int ret = self->decomp->get_gate_num();
336 
337 
338  return Py_BuildValue("i", ret);
339 
340 }
341 
342 
343 
344 
345 
346 
351 static PyObject *
353 
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));
356 
357  return global_phase;
358 
359 }
360 
367 
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);
371 
372  return Py_BuildValue("i", 0);
373 
374 }
375 
381 
382  // get the number of gates
383  self->decomp->apply_global_phase_factor();
384 
385  return Py_BuildValue("i", 0);
386 
387 }
388 
389 
394 static PyObject *
396 
397 
398  PyObject* qgd_Circuit = PyImport_ImportModule("squander.gates.qgd_Circuit");
399 
400  if ( qgd_Circuit == NULL ) {
401  PyErr_SetString(PyExc_Exception, "Module import error: squander.gates.qgd_Circuit" );
402  return NULL;
403  }
404 
405  // retrieve the C++ variant of the flat circuit (flat circuit does not conatain any sub-circuits)
406  Gates_block* circuit = self->decomp->get_flat_circuit();
407 
408 
409 
410  // construct python interfarce for the circuit
411  PyObject* qgd_circuit_Dict = PyModule_GetDict( qgd_Circuit );
412 
413  // PyDict_GetItemString creates a borrowed reference to the item in the dict. Reference counting is not increased on this element, dont need to decrease the reference counting at the end
414  PyObject* py_circuit_class = PyDict_GetItemString( qgd_circuit_Dict, "qgd_Circuit");
415 
416  // create gate parameters
417  PyObject* qbit_num = Py_BuildValue("i", circuit->get_qbit_num() );
418  PyObject* circuit_input = Py_BuildValue("(O)", qbit_num);
419 
420  PyObject* py_circuit = PyObject_CallObject(py_circuit_class, circuit_input);
421  qgd_Circuit_Wrapper* py_circuit_C = reinterpret_cast<qgd_Circuit_Wrapper*>( py_circuit );
422 
423 
424  // replace the empty circuit with the extracted one
425 
426  delete( py_circuit_C->gate );
427  py_circuit_C->gate = circuit;
428 
429 
430  return py_circuit;
431 
432 }
433 
434 
439 static PyObject *
441 
442  self->decomp->list_gates( 0 );
443 
444  return Py_None;
445 }
446 
447 
448 
449 
454 static PyObject *
456 
457  int parameter_num = self->decomp->get_parameter_num();
458  Matrix_real parameters_mtx(1, parameter_num);
459  double* parameters = parameters_mtx.get_data();
460  self->decomp->get_optimized_parameters(parameters);
461 
462  // convert to numpy array
463  parameters_mtx.set_owner(false);
464  PyObject * parameter_arr = matrix_real_to_numpy( parameters_mtx );
465 
466  return parameter_arr;
467 
468 }
469 
470 
471 
472 
476 static PyObject *
478 
479  int parameter_num = self->decomp->get_parameter_num();
480 
481  return Py_BuildValue("i", parameter_num);
482 }
483 
487 static PyObject *
489 
490  int number_of_iters = self->decomp->get_num_iters();
491 
492  return Py_BuildValue("i", number_of_iters);
493 }
494 
495 
500 static PyObject *
502 
503  PyArrayObject* parameters_arr = NULL;
504 
505 
506  // parsing input arguments
507  if (!PyArg_ParseTuple(args, "|O", &parameters_arr ))
508  return Py_BuildValue("i", -1);
509 
510 
511  if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
512  Py_INCREF(parameters_arr);
513  }
514  else {
515  parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
516  }
517 
518 
519  Matrix_real parameters_mtx = numpy2matrix_real( parameters_arr );
520 
521  try {
522  self->decomp->set_optimized_parameters(parameters_mtx.get_data(), parameters_mtx.size());
523  }
524  catch (std::string err ) {
525  PyErr_SetString(PyExc_Exception, err.c_str());
526  return NULL;
527  }
528  catch(...) {
529  std::string err( "Invalid pointer to decomposition class");
530  PyErr_SetString(PyExc_Exception, err.c_str());
531  return NULL;
532  }
533 
534 
535 
536  Py_DECREF(parameters_arr);
537 
538  return Py_BuildValue("i", 0);
539 }
540 
541 
542 
543 
544 
549 static PyObject *
551 
552  // initiate variables for input arguments
553  PyObject* max_layer_num;
554 
555  // parsing input arguments
556  if (!PyArg_ParseTuple(args, "|O", &max_layer_num )) return Py_BuildValue("i", -1);
557 
558  // Check whether input is dictionary
559  if (!PyDict_Check(max_layer_num)) {
560  printf("Input must be dictionary!\n");
561  return Py_BuildValue("i", -1);
562  }
563 
564 
565  PyObject* key = NULL;
566  PyObject* value = NULL;
567  Py_ssize_t pos = 0;
568 
569 
570  while (PyDict_Next(max_layer_num, &pos, &key, &value)) {
571 
572  // convert value fron PyObject to int
573  assert(PyLong_Check(value) == 1);
574  int value_int = (int) PyLong_AsLong(value);
575 
576  // convert keylue fron PyObject to int
577  assert(PyLong_Check(key) == 1);
578  int key_int = (int) PyLong_AsLong(key);
579 
580  // set maximal layer nums on the C++ side
581  self->decomp->set_max_layer_num( key_int, value_int );
582 
583  }
584 
585  return Py_BuildValue("i", 0);
586 }
587 
588 
589 
590 
591 
592 
599 static PyObject *
601 
602  // initiate variables for input arguments
603  PyObject* iteration_loops;
604 
605  // parsing input arguments
606  if (!PyArg_ParseTuple(args, "|O", &iteration_loops )) return Py_BuildValue("i", -1);
607 
608  // Check whether input is dictionary
609  if (!PyDict_Check(iteration_loops)) {
610  printf("Input must be dictionary!\n");
611  return Py_BuildValue("i", -1);
612  }
613 
614 
615  PyObject* key = NULL;
616  PyObject* value = NULL;
617  Py_ssize_t pos = 0;
618 
619 
620  while (PyDict_Next(iteration_loops, &pos, &key, &value)) {
621 
622  // convert value fron PyObject to int
623  assert(PyLong_Check(value) == 1);
624  int value_int = (int) PyLong_AsLong(value);
625 
626  // convert keylue fron PyObject to int
627  assert(PyLong_Check(key) == 1);
628  int key_int = (int) PyLong_AsLong(key);
629 
630  // set maximal layer nums on the C++ side
631  self->decomp->set_iteration_loops( key_int, value_int );
632 
633  }
634 
635  return Py_BuildValue("i", 0);
636 }
637 
643 static PyObject *
645 
646  // initiate variables for input arguments
647  int max_iters_input;
648 
649  // parsing input arguments
650  if (!PyArg_ParseTuple(args, "|i", &max_iters_input )) return Py_BuildValue("i", -1);
651 
652 
653  //set the maximum number of iterations
654  self->decomp->set_max_inner_iterations(max_iters_input);
655 
656 
657  return Py_BuildValue("i", 0);
658 }
659 
666 static PyObject *
668 
669  // initiate variables for input arguments
670  int verbose;
671 
672  // parsing input arguments
673  if (!PyArg_ParseTuple(args, "|i", &verbose )) return Py_BuildValue("i", -1);
674 
675 
676  // set maximal layer nums on the C++ side
677  self->decomp->set_verbose( verbose );
678 
679 
680  return Py_BuildValue("i", 0);
681 }
682 
683 
690 static PyObject *
692 
693 
694  PyObject *debugfile = NULL;
695 
696  // parsing input arguments
697  if (!PyArg_ParseTuple(args, "|O", &debugfile )) return Py_BuildValue("s", -1);
698 
699  // determine the debugfile name type
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);
703 
704 
705  Py_XDECREF(debugfile_string);
706  Py_XDECREF(debugfile_string_unicode);
707 
708  // determine the length of the filename and initialize C++ variant of the string
709  Py_ssize_t string_length = PyBytes_Size(debugfile_string_unicode);
710  std::string debugfile_Cpp(debugfile_C, string_length);
711 
712  // set the name of the debugfile on the C++ side
713  self->decomp->set_debugfile( debugfile_Cpp );
714 
715 
716  return Py_BuildValue("s", NULL);
717 }
718 
719 
720 
727 static PyObject *
729 
730  // initiate variables for input arguments
731  double tolerance;
732 
733  // parsing input arguments
734  if (!PyArg_ParseTuple(args, "|d", &tolerance )) return Py_BuildValue("i", -1);
735 
736 
737  // set maximal layer nums on the C++ side
738  self->decomp->set_optimization_tolerance( tolerance );
739 
740 
741  return Py_BuildValue("i", 0);
742 }
743 
744 
745 
752 static PyObject *
754 
755  // initiate variables for input arguments
756  double threshold;
757 
758  // parsing input arguments
759  if (!PyArg_ParseTuple(args, "|d", &threshold )) return Py_BuildValue("i", -1);
760 
761 
762  // set maximal layer nums on the C++ side
763  self->decomp->set_convergence_threshold( threshold );
764 
765  return Py_BuildValue("i", 0);
766 }
767 
768 
775 static PyObject *
777 
778  // initiate variables for input arguments
779  double optimization_block;
780 
781  // parsing input arguments
782  if (!PyArg_ParseTuple(args, "|d", &optimization_block )) return Py_BuildValue("i", -1);
783 
784 
785  // set maximal layer nums on the C++ side
786  self->decomp->set_optimization_blocks( optimization_block );
787 
788 
789  return Py_BuildValue("i", 0);
790 }
791 
792 
793 
794 
795 
800 static PyObject *
802 
803 
804  std::string project_name = self->decomp->get_project_name();
805 
806  // convert to python string
807  PyObject* project_name_pyhton = PyUnicode_FromString(project_name.c_str());
808 
809  return project_name_pyhton;
810 }
811 
812 
813 
814 
819 static PyObject *
821  // initiate variables for input arguments
822  PyObject* project_name_new=NULL;
823 
824  // parsing input arguments
825  if (!PyArg_ParseTuple(args, "|O", &project_name_new)) return Py_BuildValue("i", -1);
826 
827 
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 );
832 
833  // convert to python string
834  self->decomp->set_project_name(project_name_new_str);
835 
836  return Py_BuildValue("i", 0);
837 }
838 
839 
844 static PyObject *
846 
847 
848  double decomposition_error = self->decomp->get_decomposition_error();
849 
850 
851  return Py_BuildValue("d", decomposition_error);
852 }
853 
858 static PyObject *
860  // initiate variables for input arguments
861  PyObject* filename=NULL;
862 
863  // parsing input arguments
864  if (!PyArg_ParseTuple(args, "|O", &filename)) return Py_BuildValue("i", -1);
865 
866 
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 );
871 
872  // convert to python string
873  self->decomp->export_unitary(filename_str);
874 
875  return Py_BuildValue("i", 0);
876 }
877 
882 static PyObject *
884 
885 
886  Matrix Unitary_mtx;
887 
888  try {
889  Unitary_mtx = self->decomp->get_Umtx().copy();
890  }
891  catch (std::string err ) {
892  PyErr_SetString(PyExc_Exception, err.c_str());
893  return NULL;
894  }
895  catch (...) {
896  std::string err( "Invalid pointer to decomposition class");
897  PyErr_SetString(PyExc_Exception, err.c_str());
898  return NULL;
899  }
900 
901 
902  // convert to numpy array
903  Unitary_mtx.set_owner(false);
904  PyObject *Unitary_py = matrix_to_numpy( Unitary_mtx );
905 
906  return Unitary_py;
907 }
908 
909 
914 static PyObject *
916 {
917 
918 
919  PyArrayObject* parameters_arg = NULL;
920 
921 
922  // parsing input arguments
923  if (!PyArg_ParseTuple(args, "|O", &parameters_arg )) {
924 
925  std::string err( "Unsuccessful argument parsing not ");
926  PyErr_SetString(PyExc_Exception, err.c_str());
927  return NULL;
928 
929  }
930 
931  // establish memory contiguous arrays for C calculations
932  if ( PyArray_IS_C_CONTIGUOUS(parameters_arg) && PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ){
933  Py_INCREF(parameters_arg);
934  }
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);
937  }
938  else {
939  std::string err( "Parameters should be should be real (given in float64 format)");
940  PyErr_SetString(PyExc_Exception, err.c_str());
941  return NULL;
942  }
943 
944 
945  Matrix_real parameters_mtx = numpy2matrix_real( parameters_arg );
946  double f0;
947 
948  try {
949  f0 = self->decomp->optimization_problem(parameters_mtx );
950  }
951  catch (std::string err ) {
952  PyErr_SetString(PyExc_Exception, err.c_str());
953  return NULL;
954  }
955  catch (...) {
956  std::string err( "Invalid pointer to decomposition class");
957  PyErr_SetString(PyExc_Exception, err.c_str());
958  return NULL;
959  }
960 
961  Py_DECREF(parameters_arg);
962 
963 
964  return Py_BuildValue("d", f0);
965 }
966 
967 
972 static PyObject *
974 {
975 
976 
977  PyArrayObject* parameters_arg = NULL;
978 
979 
980  // parsing input arguments
981  if (!PyArg_ParseTuple(args, "|O", &parameters_arg )) {
982 
983  std::string err( "Unsuccessful argument parsing not ");
984  PyErr_SetString(PyExc_Exception, err.c_str());
985  return NULL;
986 
987  }
988 
989  // establish memory contiguous arrays for C calculations
990  if ( PyArray_IS_C_CONTIGUOUS(parameters_arg) && PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ){
991  Py_INCREF(parameters_arg);
992  }
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);
995  }
996  else {
997  std::string err( "Parameters should be should be real (given in float64 format)");
998  PyErr_SetString(PyExc_Exception, err.c_str());
999  return NULL;
1000  }
1001 
1002 
1003  Matrix_real parameters_mtx = numpy2matrix_real( parameters_arg );
1004  Matrix_real grad_mtx(parameters_mtx.size(), 1);
1005 
1006  try {
1007  self->decomp->optimization_problem_grad(parameters_mtx, self->decomp, grad_mtx );
1008  }
1009  catch (std::string err ) {
1010  PyErr_SetString(PyExc_Exception, err.c_str());
1011  return NULL;
1012  }
1013  catch (...) {
1014  std::string err( "Invalid pointer to decomposition class");
1015  PyErr_SetString(PyExc_Exception, err.c_str());
1016  return NULL;
1017  }
1018 
1019  // convert to numpy array
1020  grad_mtx.set_owner(false);
1021  PyObject *grad_py = matrix_real_to_numpy( grad_mtx );
1022 
1023  Py_DECREF(parameters_arg);
1024 
1025 
1026  return grad_py;
1027 }
1028 
1033 static PyObject *
1035 {
1036 
1037 
1038  PyArrayObject* parameters_arg = NULL;
1039 
1040 
1041  // parsing input arguments
1042  if (!PyArg_ParseTuple(args, "|O", &parameters_arg )) {
1043 
1044  std::string err( "Unsuccessful argument parsing not ");
1045  PyErr_SetString(PyExc_Exception, err.c_str());
1046  return NULL;
1047 
1048  }
1049 
1050  // establish memory contiguous arrays for C calculations
1051  if ( PyArray_IS_C_CONTIGUOUS(parameters_arg) && PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ){
1052  Py_INCREF(parameters_arg);
1053  }
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);
1056  }
1057  else {
1058  std::string err( "Parameters should be should be real (given in float64 format)");
1059  PyErr_SetString(PyExc_Exception, err.c_str());
1060  return NULL;
1061  }
1062 
1063 
1064  Matrix_real parameters_mtx = numpy2matrix_real( parameters_arg );
1065  Matrix_real grad_mtx(parameters_mtx.size(), 1);
1066  double f0;
1067 
1068  try {
1069  self->decomp->optimization_problem_combined(parameters_mtx, &f0, grad_mtx );
1070  }
1071  catch (std::string err ) {
1072  PyErr_SetString(PyExc_Exception, err.c_str());
1073  return NULL;
1074  }
1075  catch (...) {
1076  std::string err( "Invalid pointer to decomposition class");
1077  PyErr_SetString(PyExc_Exception, err.c_str());
1078  return NULL;
1079  }
1080 
1081  // convert to numpy array
1082  grad_mtx.set_owner(false);
1083  PyObject *grad_py = matrix_real_to_numpy( grad_mtx );
1084 
1085  Py_DECREF(parameters_arg);
1086 
1087 
1088  PyObject* p = Py_BuildValue("(dO)", f0, grad_py);
1089  Py_DECREF(grad_py);
1090  return p;
1091 }
1092 
1097 static PyObject *
1099 {
1100 
1101 
1102  PyArrayObject* parameters_arg = NULL;
1103 
1104 
1105  // parsing input arguments
1106  if (!PyArg_ParseTuple(args, "|O", &parameters_arg )) {
1107 
1108  std::string err( "Unsuccessful argument parsing not ");
1109  PyErr_SetString(PyExc_Exception, err.c_str());
1110  return NULL;
1111 
1112  }
1113 
1114  // establish memory contiguous arrays for C calculations
1115  if ( PyArray_IS_C_CONTIGUOUS(parameters_arg) && PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ){
1116  Py_INCREF(parameters_arg);
1117  }
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);
1120  }
1121  else {
1122  std::string err( "Parameters should be should be real (given in float64 format)");
1123  PyErr_SetString(PyExc_Exception, err.c_str());
1124  return NULL;
1125  }
1126 
1127 
1128  Matrix_real parameters_mtx = numpy2matrix_real( parameters_arg );
1129  Matrix Umtx;
1130  std::vector<Matrix> Umtx_deriv;
1131 
1132  try {
1133  self->decomp->optimization_problem_combined_unitary(parameters_mtx, Umtx, Umtx_deriv );
1134  }
1135  catch (std::string err ) {
1136  PyErr_SetString(PyExc_Exception, err.c_str());
1137  return NULL;
1138  }
1139  catch (...) {
1140  std::string err( "Invalid pointer to decomposition class");
1141  PyErr_SetString(PyExc_Exception, err.c_str());
1142  return NULL;
1143  }
1144 
1145  // convert to numpy array
1146  Umtx.set_owner(false);
1147  PyObject *unitary_py = matrix_to_numpy( Umtx );
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);
1151  PyList_SetItem(graduni_py, i, matrix_to_numpy(Umtx_deriv[i]));
1152  }
1153 
1154  Py_DECREF(parameters_arg);
1155 
1156 
1157  PyObject* p = Py_BuildValue("(OO)", unitary_py, graduni_py);
1158  Py_DECREF(unitary_py); Py_DECREF(graduni_py);
1159  return p;
1160 }
1161 
1166 static PyObject *
1168 {
1169 
1170 
1171  PyArrayObject* parameters_arg = NULL;
1172 
1173 
1174  // parsing input arguments
1175  if (!PyArg_ParseTuple(args, "|O", &parameters_arg )) {
1176 
1177  std::string err( "Unsuccessful argument parsing not ");
1178  PyErr_SetString(PyExc_Exception, err.c_str());
1179  return NULL;
1180 
1181  }
1182 
1183  // establish memory contiguous arrays for C calculations
1184  if ( PyArray_IS_C_CONTIGUOUS(parameters_arg) && PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ){
1185  Py_INCREF(parameters_arg);
1186  }
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);
1189  }
1190  else {
1191  std::string err( "Parameters should be should be real (given in float64 format)");
1192  PyErr_SetString(PyExc_Exception, err.c_str());
1193  return NULL;
1194  }
1195 
1196 
1197  Matrix_real parameters_mtx = numpy2matrix_real( parameters_arg );
1198  Matrix_real result_mtx;
1199 
1200  try {
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++ ) {
1204  parameters_vec[row_idx] = Matrix_real( parameters_mtx.get_data() + row_idx*parameters_mtx.stride, 1, parameters_mtx.cols, parameters_mtx.stride );
1205  }
1206  result_mtx = self->decomp->optimization_problem_batched( parameters_vec );
1207  }
1208  catch (std::string err ) {
1209  PyErr_SetString(PyExc_Exception, err.c_str());
1210  return NULL;
1211  }
1212  catch (...) {
1213  std::string err( "Invalid pointer to decomposition class");
1214  PyErr_SetString(PyExc_Exception, err.c_str());
1215  return NULL;
1216  }
1217 
1218  // convert to numpy array
1219  result_mtx.set_owner(false);
1220  PyObject *result_py = matrix_real_to_numpy( result_mtx );
1221 
1222  Py_DECREF(parameters_arg);
1223 
1224  return result_py;
1225 
1226 }
1227 
1228 static PyObject *
1230 
1231  if ( self->Umtx != NULL ) {
1232  // release the unitary to be decomposed
1233  Py_DECREF(self->Umtx);
1234  self->Umtx = NULL;
1235  }
1236 
1237  PyArrayObject *Umtx_arg = NULL;
1238  //Parse arguments
1239  if (!PyArg_ParseTuple(args, "|O", &Umtx_arg )) return Py_BuildValue("i", -1);
1240 
1241  // convert python object array to numpy C API array
1242  if ( Umtx_arg == NULL ) {
1243  PyErr_SetString(PyExc_Exception, "Umtx argument in empty");
1244  return NULL;
1245  }
1246 
1247  self->Umtx = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)Umtx_arg, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
1248 
1249  // test C-style contiguous memory allocation of the array
1250  if ( !PyArray_IS_C_CONTIGUOUS(self->Umtx) ) {
1251  std::cout << "Umtx is not memory contiguous" << std::endl;
1252  }
1253 
1254 
1255  // create QGD version of the Umtx
1256  Matrix Umtx_mtx = numpy2matrix(self->Umtx);
1257  self->decomp->set_unitary(Umtx_mtx);
1258 
1259  return Py_BuildValue("i", 0);
1260 }
1261 
1266 static PyObject *
1268 
1269  // initiate variables for input arguments
1270  PyObject* qbit_list;
1271 
1272  // parsing input arguments
1273  if (!PyArg_ParseTuple(args, "|O", &qbit_list )) return Py_BuildValue("i", -1);
1274 
1275  bool is_tuple = PyTuple_Check(qbit_list);
1276  bool is_list = PyList_Check(qbit_list);
1277 
1278  // Check whether input is dictionary
1279  if (!is_list && !is_tuple) {
1280  printf("Input must be tuple or list!\n");
1281  return Py_BuildValue("i", -1);
1282  }
1283 
1284  // get the number of qbubits
1285  Py_ssize_t element_num;
1286 
1287  if (is_tuple) {
1288  element_num = PyTuple_GET_SIZE(qbit_list);
1289  }
1290  else {
1291  element_num = PyList_GET_SIZE(qbit_list);
1292  }
1293 
1294 
1295  // create C++ variant of the tuple/list
1296  std::vector<int> qbit_list_C( (int) element_num);
1297  for ( Py_ssize_t idx=0; idx<element_num; idx++ ) {
1298  if (is_tuple) {
1299  qbit_list_C[(int) idx] = (int) PyLong_AsLong( PyTuple_GetItem(qbit_list, idx ) );
1300  }
1301  else {
1302  qbit_list_C[(int) idx] = (int) PyLong_AsLong( PyList_GetItem(qbit_list, idx ) );
1303  }
1304 
1305  }
1306 
1307 
1308  // reorder the qubits in the decomposition class
1309  self->decomp->reorder_qubits( qbit_list_C );
1310 
1311 
1312 
1313 
1314  return Py_BuildValue("i", 0);
1315 }
1316 
1317 
1318 
1319 
1320 
1321 
1326 static PyObject *
1328 
1329  PyArrayObject* parameters_arr = NULL;
1330 
1331 
1332  // parsing input arguments
1333  if (!PyArg_ParseTuple(args, "|O", &parameters_arr ))
1334  return Py_BuildValue("i", -1);
1335 
1336 
1337  if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
1338  Py_INCREF(parameters_arr);
1339  }
1340  else {
1341  parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
1342  }
1343 
1344 
1345  // get the C++ wrapper around the data
1346  Matrix_real&& parameters_mtx = numpy2matrix_real( parameters_arr );
1347 
1348 
1349  Matrix unitary_mtx;
1350 
1351  unitary_mtx = self->decomp->get_matrix( parameters_mtx );
1352 
1353 
1354  // convert to numpy array
1355  unitary_mtx.set_owner(false);
1356  PyObject *unitary_py = matrix_to_numpy( unitary_mtx );
1357 
1358 
1359  Py_DECREF(parameters_arr);
1360 
1361  return unitary_py;
1362 }
1363 
1364 
1365 
1371 static PyObject *
1373 {
1374 
1375  // The tuple of expected keywords
1376  static char *kwlist[] = {(char*)"optimizer", NULL};
1377 
1378  PyObject* optimizer_arg = NULL;
1379 
1380 
1381  // parsing input arguments
1382  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &optimizer_arg)) {
1383 
1384  std::string err( "Unsuccessful argument parsing not ");
1385  PyErr_SetString(PyExc_Exception, err.c_str());
1386  return NULL;
1387 
1388  }
1389 
1390 
1391  if ( optimizer_arg == NULL ) {
1392  std::string err( "optimizer argument not set");
1393  PyErr_SetString(PyExc_Exception, err.c_str());
1394  return NULL;
1395  }
1396 
1397 
1398 
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);
1402 
1403  optimization_aglorithms qgd_optimizer;
1404  if ( strcmp("bfgs", optimizer_C) == 0 || strcmp("BFGS", optimizer_C) == 0) {
1405  qgd_optimizer = BFGS;
1406  }
1407  else if ( strcmp("adam", optimizer_C)==0 || strcmp("ADAM", optimizer_C)==0) {
1408  qgd_optimizer = ADAM;
1409  }
1410  else if ( strcmp("grad_descend", optimizer_C)==0 || strcmp("GRAD_DESCEND", optimizer_C)==0) {
1411  qgd_optimizer = GRAD_DESCEND;
1412  }
1413  else if ( strcmp("adam_batched", optimizer_C)==0 || strcmp("ADAM_BATCHED", optimizer_C)==0) {
1414  qgd_optimizer = ADAM_BATCHED;
1415  }
1416  else if ( strcmp("bfgs2", optimizer_C)==0 || strcmp("BFGS2", optimizer_C)==0) {
1417  qgd_optimizer = BFGS2;
1418  }
1419  else if ( strcmp("agents", optimizer_C)==0 || strcmp("AGENTS", optimizer_C)==0) {
1420  qgd_optimizer = AGENTS;
1421  }
1422  else if ( strcmp("cosine", optimizer_C)==0 || strcmp("COSINE", optimizer_C)==0) {
1423  qgd_optimizer = COSINE;
1424  }
1425  else if ( strcmp("grad_descend_phase_shift_rule", optimizer_C)==0 || strcmp("GRAD_DESCEND_PARAMETER_SHIFT_RULE", optimizer_C)==0) {
1426  qgd_optimizer = GRAD_DESCEND_PARAMETER_SHIFT_RULE;
1427  }
1428  else if ( strcmp("agents_combined", optimizer_C)==0 || strcmp("AGENTS_COMBINED", optimizer_C)==0) {
1429  qgd_optimizer = AGENTS_COMBINED;
1430  }
1431  else if ( strcmp("bayes_opt", optimizer_C)==0 || strcmp("BAYES_OPT", optimizer_C)==0) {
1432  qgd_optimizer = BAYES_OPT;
1433  }
1434  else {
1435  std::cout << "Wrong optimizer: " << optimizer_C << ". Using default: BFGS" << std::endl;
1436  qgd_optimizer = BFGS;
1437  }
1438 
1439 
1440  try {
1441  self->decomp->set_optimizer(qgd_optimizer);
1442  }
1443  catch (std::string err) {
1444  PyErr_SetString(PyExc_Exception, err.c_str());
1445  std::cout << err << std::endl;
1446  return NULL;
1447  }
1448  catch(...) {
1449  std::string err( "Invalid pointer to decomposition class");
1450  PyErr_SetString(PyExc_Exception, err.c_str());
1451  return NULL;
1452  }
1453 
1454 
1455  return Py_BuildValue("i", 0);
1456 
1457 }
1458 
1459 
1460 
1466 static PyObject *
1468 {
1469 
1470  // The tuple of expected keywords
1471  static char *kwlist[] = {(char*)"costfnc", NULL};
1472 
1473  int costfnc_arg = 0;
1474 
1475 
1476  // parsing input arguments
1477  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &costfnc_arg)) {
1478 
1479  std::string err( "Unsuccessful argument parsing");
1480  PyErr_SetString(PyExc_Exception, err.c_str());
1481  return NULL;
1482 
1483  }
1484 
1485  cost_function_type qgd_costfnc = (cost_function_type)costfnc_arg;
1486 
1487 
1488  try {
1489  self->decomp->set_cost_function_variant(qgd_costfnc);
1490  }
1491  catch (std::string err) {
1492  PyErr_SetString(PyExc_Exception, err.c_str());
1493  std::cout << err << std::endl;
1494  return NULL;
1495  }
1496  catch(...) {
1497  std::string err( "Invalid pointer to decomposition class");
1498  PyErr_SetString(PyExc_Exception, err.c_str());
1499  return NULL;
1500  }
1501 
1502 
1503  return Py_BuildValue("i", 0);
1504 
1505 }
1506 
1507 
1508 
1509 
1510 
1511 
1516 static PyObject *
1518 {
1519 
1520  // The tuple of expected keywords
1521  static char *kwlist[] = {(char*)"trace_offset", NULL};
1522 
1523  int trace_offset_arg = 0;
1524 
1525 
1526  // parsing input arguments
1527  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &trace_offset_arg)) {
1528 
1529  std::string err( "Unsuccessful argument parsing");
1530  PyErr_SetString(PyExc_Exception, err.c_str());
1531  return NULL;
1532 
1533  }
1534 
1535 
1536  try {
1537  self->decomp->set_trace_offset(trace_offset_arg);
1538  }
1539  catch (std::string err) {
1540  PyErr_SetString(PyExc_Exception, err.c_str());
1541  std::cout << err << std::endl;
1542  return NULL;
1543  }
1544  catch(...) {
1545  std::string err( "Invalid pointer to decomposition class");
1546  PyErr_SetString(PyExc_Exception, err.c_str());
1547  return NULL;
1548  }
1549 
1550 
1551  return Py_BuildValue("i", 0);
1552 
1553 }
1554 
1555 
1556 
1561 static PyObject *
1563 {
1564 
1565  int trace_offset = 0;
1566 
1567  try {
1568  trace_offset = self->decomp->get_trace_offset();
1569  }
1570  catch (std::string err) {
1571  PyErr_SetString(PyExc_Exception, err.c_str());
1572  std::cout << err << std::endl;
1573  return NULL;
1574  }
1575  catch(...) {
1576  std::string err( "Invalid pointer to decomposition class");
1577  PyErr_SetString(PyExc_Exception, err.c_str());
1578  return NULL;
1579  }
1580 
1581 
1582  return Py_BuildValue("i", trace_offset);
1583 
1584 }
1585 
1586 
1587 
1588 
1592 static PyObject *
1594 
1595 #ifdef __DFE__
1596 
1597  try {
1598  self->decomp->upload_Umtx_to_DFE();
1599  }
1600  catch (std::string err) {
1601  PyErr_SetString(PyExc_Exception, err.c_str());
1602  std::cout << err << std::endl;
1603  return NULL;
1604  }
1605  catch(...) {
1606  std::string err( "Invalid pointer to decomposition class");
1607  PyErr_SetString(PyExc_Exception, err.c_str());
1608  return NULL;
1609  }
1610 
1611 #endif
1612 
1613  return Py_BuildValue("i", 0);
1614 
1615 }
1616 
1617 
1618 
1619 
1620 
1621 
1625 static PyObject *
1627 {
1628 
1629 
1630  PyArrayObject * parameters_arr = NULL;
1631  PyArrayObject * input_state_arg = NULL;
1632  PyObject * qubit_list_arg = NULL;
1633 
1634 
1635  // parsing input arguments
1636  if (!PyArg_ParseTuple(args, "|OOO", &parameters_arr, &input_state_arg, &qubit_list_arg ))
1637  return Py_BuildValue("i", -1);
1638 
1639 
1640  if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
1641  Py_INCREF(parameters_arr);
1642  }
1643  else {
1644  parameters_arr = (PyArrayObject*)PyArray_FROM_OTF((PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
1645  }
1646 
1647  // get the C++ wrapper around the data
1648  Matrix_real&& parameters_mtx = numpy2matrix_real( parameters_arr );
1649 
1650 
1651  // convert python object array to numpy C API array
1652  if ( input_state_arg == NULL ) {
1653  PyErr_SetString(PyExc_Exception, "Input matrix was not given");
1654  return NULL;
1655  }
1656 
1657  PyArrayObject* input_state = (PyArrayObject*)PyArray_FROM_OTF((PyObject*)input_state_arg, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
1658 
1659  // test C-style contiguous memory allocation of the array
1660  if ( !PyArray_IS_C_CONTIGUOUS(input_state) ) {
1661  PyErr_SetString(PyExc_Exception, "input mtrix is not memory contiguous");
1662  return NULL;
1663  }
1664 
1665 
1666  // create QGD version of the input matrix
1667  Matrix input_state_mtx = numpy2matrix(input_state);
1668 
1669 
1670  // check input argument qbit_list
1671  if ( qubit_list_arg == NULL || (!PyList_Check( qubit_list_arg )) ) {
1672  PyErr_SetString(PyExc_Exception, "qubit_list should be a list");
1673  return NULL;
1674  }
1675 
1676  Py_ssize_t reduced_qbit_num = PyList_Size( qubit_list_arg );
1677 
1678  matrix_base<int> qbit_list_mtx( (int)reduced_qbit_num, 1);
1679  for ( int idx=0; idx<reduced_qbit_num; idx++ ) {
1680 
1681  PyObject* item = PyList_GET_ITEM( qubit_list_arg, idx );
1682  qbit_list_mtx[idx] = (int) PyLong_AsLong( item );
1683 
1684  }
1685 
1686 
1687  double entropy = -1;
1688 
1689 
1690  try {
1691  entropy = self->decomp->get_second_Renyi_entropy( parameters_mtx, input_state_mtx, qbit_list_mtx );
1692  }
1693  catch (std::string err) {
1694  PyErr_SetString(PyExc_Exception, err.c_str());
1695  std::cout << err << std::endl;
1696  return NULL;
1697  }
1698  catch(...) {
1699  std::string err( "Invalid pointer to decomposition class");
1700  PyErr_SetString(PyExc_Exception, err.c_str());
1701  return NULL;
1702  }
1703 
1704 
1705  Py_DECREF(parameters_arr);
1706  Py_DECREF(input_state);
1707 
1708 
1709 
1710  PyObject* p = Py_BuildValue("d", entropy);
1711 
1712  return p;
1713 }
1714 
1715 
1719 static PyObject *
1721 
1722  int qbit_num = 0;
1723 
1724  try {
1725  qbit_num = self->decomp->get_qbit_num();
1726  }
1727  catch (std::string err) {
1728  PyErr_SetString(PyExc_Exception, err.c_str());
1729  std::cout << err << std::endl;
1730  return NULL;
1731  }
1732  catch(...) {
1733  std::string err( "Invalid pointer to decomposition class");
1734  PyErr_SetString(PyExc_Exception, err.c_str());
1735  return NULL;
1736  }
1737 
1738 
1739  return Py_BuildValue("i", qbit_num );
1740 
1741 }
1742 
1743 
1744 
1749  {NULL} /* Sentinel */
1750 };
1751 
1756  {"Start_Decomposition", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Start_Decomposition, METH_VARARGS | METH_KEYWORDS,
1757  "Method to start the decomposition."
1758  },
1759  {"get_Gate_Num", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_gate_num, METH_NOARGS,
1760  "Method to get the number of decomposing gates."
1761  },
1762  {"get_Parameter_Num", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Parameter_Num, METH_NOARGS,
1763  "Call to get the number of free parameters in the gate structure used for the decomposition"
1764  },
1765  {"get_Optimized_Parameters", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Optimized_Parameters, METH_NOARGS,
1766  "Method to get the array of optimized parameters."
1767  },
1768  {"set_Optimized_Parameters", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Optimized_Parameters, METH_VARARGS,
1769  "Method to set the initial array of optimized parameters."
1770  },
1771  {"get_Circuit", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_circuit, METH_NOARGS,
1772  "Method to get the incorporated circuit."
1773  },
1774  {"List_Gates", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_List_Gates, METH_NOARGS,
1775  "Call to print the decomposing nitaries on standard output"
1776  },
1777  {"get_Num_of_Iters", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Num_of_Iters, METH_NOARGS,
1778  "Method to get the number of iterations."
1779  },
1780  {"set_Max_Layer_Num", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Max_Layer_Num, METH_VARARGS,
1781  "Call to set the maximal number of layers used in the subdecomposition of the qbit-th qubit."
1782  },
1783  {"set_Iteration_Loops", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Iteration_Loops, METH_VARARGS,
1784  "Call to set the number of iteration loops during the subdecomposition of the qbit-th qubit."
1785  },
1786  {"set_Verbose", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Verbose, METH_VARARGS,
1787  "Call to set the verbosity of the qgd_N_Qubit_Decomposition class."
1788  },
1789  {"set_Debugfile", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Debugfile, METH_VARARGS,
1790  "Set the debugfile name of the N_Qubit_Decomposition class."
1791  },
1792  {"Reorder_Qubits", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Reorder_Qubits, METH_VARARGS,
1793  "Wrapper method to reorder the qubits in the decomposition class."
1794  },
1795  {"set_Optimization_Tolerance", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Optimization_Tolerance, METH_VARARGS,
1796  "Wrapper method to set the optimization tolerance of the optimization process during the decomposition."
1797  },
1798  {"set_Convergence_Threshold", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Convergence_Threshold, METH_VARARGS,
1799  "Wrapper method to set the threshold of convergence in the optimization processes."
1800  },
1801  {"set_Optimization_Blocks", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Optimization_Blocks, METH_VARARGS,
1802  "Wrapper method to to set the number of gate blocks to be optimized in one shot."
1803  },
1804  {"set_Unitary", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Unitary, METH_VARARGS,
1805  "Call to set unitary matrix to a numpy matrix"
1806  },
1807  {"export_Unitary", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_export_Unitary, METH_VARARGS,
1808  "Call to export unitary matrix to a binary file"
1809  },
1810  {"get_Project_Name", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Project_Name, METH_NOARGS,
1811  "Call to get the name of SQUANDER project"
1812  },
1813  {"set_Project_Name", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Project_Name, METH_VARARGS,
1814  "Call to set the name of SQUANDER project"
1815  },
1816  {"get_Global_Phase", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Global_Phase, METH_NOARGS,
1817  "Call to get global phase"
1818  },
1819  {"set_Global_Phase", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Global_Phase, METH_VARARGS,
1820  "Call to set global phase"
1821  },
1822  {"apply_Global_Phase_Factor", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_apply_Global_Phase_Factor, METH_NOARGS,
1823  "Call to apply global phase on Unitary matrix"
1824  },
1825  {"get_Unitary", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Unitary, METH_NOARGS,
1826  "Call to get Unitary Matrix"
1827  },
1828  {"set_Optimizer", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Optimizer, METH_VARARGS | METH_KEYWORDS,
1829  "Wrapper method to to set the optimizer method for the gate synthesis."
1830  },
1831  {"set_Max_Iterations", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Max_Iterations, METH_VARARGS | METH_VARARGS,
1832  "Wrapper method to to set the maximum number of iterations for the gate synthesis."
1833  },
1834  {"get_Matrix", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Matrix, METH_VARARGS,
1835  "Method to retrieve the unitary of the circuit."
1836  },
1837  {"set_Cost_Function_Variant", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Cost_Function_Variant, METH_VARARGS | METH_KEYWORDS,
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."
1839  },
1840  {"Optimization_Problem", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Optimization_Problem, METH_VARARGS,
1841  "Wrapper function to evaluate the cost function."
1842  },
1843  {"Optimization_Problem_Combined_Unitary", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Optimization_Problem_Combined_Unitary, METH_VARARGS,
1844  "Wrapper function to evaluate the unitary function and the gradient components."
1845  },
1846  {"Optimization_Problem_Grad", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Optimization_Problem_Grad, METH_VARARGS,
1847  "Wrapper function to evaluate the gradient components."
1848  },
1849  {"Optimization_Problem_Combined", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Optimization_Problem_Combined, METH_VARARGS,
1850  "Wrapper function to evaluate the cost function and the gradient components."
1851  },
1852  {"Optimization_Problem_Batch", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Optimization_Problem_Batch, METH_VARARGS,
1853  "Wrapper function to evaluate the cost function of batch."
1854  },
1855  {"Upload_Umtx_to_DFE", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Upload_Umtx_to_DFE, METH_NOARGS,
1856  "Call to upload the unitary to the DFE. (Has no effect for non-DFE builds)"
1857  },
1858  {"get_Trace_Offset", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Trace_Offset, METH_NOARGS,
1859  "Call to get the trace offset used in the cost function. In this case Tr(A) = sum_(i-offset=j) A_{ij}"
1860  },
1861  {"set_Trace_Offset", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_set_Trace_Offset, METH_VARARGS | METH_KEYWORDS,
1862  "Call to set the trace offset used in the cost function. In this case Tr(A) = sum_(i-offset=j) A_{ij}"
1863  },
1864  {"get_Decomposition_Error", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Decomposition_Error, METH_NOARGS,
1865  "Call to get the error of the decomposition. (i.e. the final value of the cost function)"
1866  },
1867  {"get_Second_Renyi_Entropy", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Second_Renyi_Entropy, METH_VARARGS,
1868  "Wrapper function to evaluate the second Rényi entropy of a quantum circuit at a specific parameter set."
1869  },
1870  {"get_Qbit_Num", (PyCFunction) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_get_Qbit_Num, METH_NOARGS,
1871  "Call to get the number of qubits in the circuit"
1872  },
1873  {NULL} /* Sentinel */
1874 };
1875 
1880  PyVarObject_HEAD_INIT(NULL, 0)
1881  "qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper.qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper", /*tp_name*/
1882  sizeof(qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper), /*tp_basicsize*/
1883  0, /*tp_itemsize*/
1884  (destructor) qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_dealloc, /*tp_dealloc*/
1885  #if PY_VERSION_HEX < 0x030800b4
1886  0, /*tp_print*/
1887  #endif
1888  #if PY_VERSION_HEX >= 0x030800b4
1889  0, /*tp_vectorcall_offset*/
1890  #endif
1891  0, /*tp_getattr*/
1892  0, /*tp_setattr*/
1893  #if PY_MAJOR_VERSION < 3
1894  0, /*tp_compare*/
1895  #endif
1896  #if PY_MAJOR_VERSION >= 3
1897  0, /*tp_as_async*/
1898  #endif
1899  0, /*tp_repr*/
1900  0, /*tp_as_number*/
1901  0, /*tp_as_sequence*/
1902  0, /*tp_as_mapping*/
1903  0, /*tp_hash*/
1904  0, /*tp_call*/
1905  0, /*tp_str*/
1906  0, /*tp_getattro*/
1907  0, /*tp_setattro*/
1908  0, /*tp_as_buffer*/
1909  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
1910  "Object to represent a Circuit class of the QGD package.", /*tp_doc*/
1911  0, /*tp_traverse*/
1912  0, /*tp_clear*/
1913  0, /*tp_richcompare*/
1914  0, /*tp_weaklistoffset*/
1915  0, /*tp_iter*/
1916  0, /*tp_iternext*/
1919  0, /*tp_getset*/
1920  0, /*tp_base*/
1921  0, /*tp_dict*/
1922  0, /*tp_descr_get*/
1923  0, /*tp_descr_set*/
1924  0, /*tp_dictoffset*/
1926  0, /*tp_alloc*/
1928  0, /*tp_free*/
1929  0, /*tp_is_gc*/
1930  0, /*tp_bases*/
1931  0, /*tp_mro*/
1932  0, /*tp_cache*/
1933  0, /*tp_subclasses*/
1934  0, /*tp_weaklist*/
1935  0, /*tp_del*/
1936  0, /*tp_version_tag*/
1937  #if PY_VERSION_HEX >= 0x030400a1
1938  0, /*tp_finalize*/
1939  #endif
1940  #if PY_VERSION_HEX >= 0x030800b1
1941  0, /*tp_vectorcall*/
1942  #endif
1943  #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000
1944  0, /*tp_print*/
1945  #endif
1946 };
1947 
1952  PyModuleDef_HEAD_INIT,
1953  "qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper",
1954  "Python binding for QGD N_Qubit_Decomposition class",
1955  -1,
1956 };
1957 
1958 
1962 PyMODINIT_FUNC
1964 {
1965  // initialize Numpy API
1966  import_array();
1967 
1968  PyObject *m;
1969  if (PyType_Ready(&qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Type) < 0)
1970  return NULL;
1971 
1972  m = PyModule_Create(&qgd_N_Qubit_Decomposition_Tabu_Search_Wrapper_Module);
1973  if (m == NULL)
1974  return NULL;
1975 
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);
1979  Py_DECREF(m);
1980  return NULL;
1981  }
1982 
1983  return m;
1984 }
1985 
1986 
1987 } //extern C
1988 
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.
string project_name
Definition: test_Groq.py:98
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)
Definition: matrix_base.hpp:46
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.
Definition: matrix_base.hpp:42
int cols
The number of columns.
Definition: matrix_base.hpp:44
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.
Definition: example.py:53
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.
Definition: QGDTypes.h:38
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.
Definition: matrix.h:38
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.
Definition: Gates_block.h:41
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.
Definition: matrix.cpp:105
double real
the real part of a complex number
Definition: QGDTypes.h:40
int get_qbit_num()
Call to get the number of qubits composing the unitary.
Definition: Gate.cpp:504
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
Definition: example.py:97
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.
Definition: matrix_real.h:39
double imag
the imaginary part of a complex number
Definition: QGDTypes.h:42