Sequential Quantum Gate Decomposer  v1.9.6
Powerful decomposition of general unitarias into one- and two-qubit gates gates
qgd_GQML_Base_Wrapper.cpp
Go to the documentation of this file.
1 /*
2 Created on Fri Jun 26 14:13:26 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 @author: Peter Rakyta, Ph.D.
18 */
23 #define PY_SSIZE_T_CLEAN
24 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
25 
26 #include <Python.h>
27 #include <numpy/arrayobject.h>
28 #include "structmember.h"
29 #include <stdio.h>
31 
32 #include "numpy_interface.h"
33 
34 
35 
36 
37 
41 typedef struct qgd_Circuit_Wrapper {
42  PyObject_HEAD
45 
46 
51  PyObject_HEAD
53  PyObject *x_vectors;
54  PyObject *P_star;
57 
59 
60 
61 
76 create_qgd_Generative_Quantum_Machine_Learning_Base( std::vector<int> x_vectors, std::vector<std::vector<int>> x_bitstrings, Matrix_real P_star, Matrix_real sigma, int qbit_num, bool use_lookup_table, std::vector<std::vector<int>> cliques, bool use_exact, std::map<std::string, Config_Element>& config) {
77 
78  return new Generative_Quantum_Machine_Learning_Base( x_vectors, x_bitstrings, P_star, sigma, qbit_num, use_lookup_table, cliques, use_exact, config);
79 }
80 
81 
86 void
88 
89  if (instance != NULL ) {
90  delete instance;
91  }
92  return;
93 }
94 
95 
96 
97 extern "C"
98 {
99 
100 
105 static void
107 {
108 
109  if ( self->gqml != NULL ) {
110  // deallocate the instance of class Generative_Quantum_Machine_Learning_Base
112  self->gqml = NULL;
113  }
114 
115  if ( self->x_vectors != NULL ) {
116  // release the unitary to be decomposed
117  Py_DECREF(self->x_vectors);
118  self->x_vectors = NULL;
119  }
120 
121  if ( self->P_star != NULL ) {
122  // release the unitary to be decomposed
123  Py_DECREF(self->P_star);
124  self->P_star = NULL;
125  }
126 
127  Py_TYPE(self)->tp_free((PyObject *) self);
128 
129 }
130 
135 static PyObject *
137 {
139  self = (qgd_Generative_Quantum_Machine_Learning_Base_Wrapper *) type->tp_alloc(type, 0);
140  if (self != NULL) {}
141 
142  self->gqml = NULL;
143  self->x_vectors = NULL;
144  self->P_star = NULL;
145 
146  return (PyObject *) self;
147 }
148 
149 
156 static int
158 {
159  // The tuple of expected keywords
160  static char *kwlist[] = {(char*)"x_bitstring_data", (char*)"p_star_data", (char*) "sigma", (char*)"qbit_num", (char*)"use_lookup_table", (char*)"cliques", (char*)"use_exact", (char*)"config", NULL};
161 
162  // initiate variables for input arguments
163  PyArrayObject *x_bitstring_data_arg = NULL;
164  PyArrayObject *p_star_data_arg = NULL;
165  PyObject *cliques_data_arg = NULL;
166  PyArrayObject *sigma_data_arg;
167  int qbit_num = -1;
168  int use_lookup_table;
169  PyObject *config_arg = NULL;
170  int use_exact;
171 
172  // parsing input arguments
173  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOipOpO", kwlist,
174  &x_bitstring_data_arg, &p_star_data_arg, &sigma_data_arg, &qbit_num, &use_lookup_table, &cliques_data_arg, &use_exact,&config_arg))
175  return -1;
176 
177 
178  int shape = Power_of_2(qbit_num);
179  // convert python object array to numpy C API array
180  if ( x_bitstring_data_arg == NULL ) return -1;
181 
182  if ( !PyArray_ISINTEGER(x_bitstring_data_arg) && PyArray_TYPE(x_bitstring_data_arg) != NPY_BOOL) {
183  PyErr_SetString(PyExc_TypeError, "x_bitstring_data should be int type or bool!" );
184  return -1;
185  }
186 
187  x_bitstring_data_arg = (PyArrayObject*)PyArray_FROM_OF( (PyObject*)x_bitstring_data_arg, NPY_ARRAY_IN_ARRAY);
188  int* x_bitsring_data = (int*)PyArray_DATA(x_bitstring_data_arg);
189  npy_intp* x_bistring_shape = PyArray_DIMS(x_bitstring_data_arg);
190 
191  if (x_bistring_shape[1] != qbit_num) {
192  std::cout<< shape << " " << x_bistring_shape[1] << std::endl;
193  PyErr_SetString(PyExc_ValueError, "Each vector in x_bitsring_data should be qbit_num length!");
194  return -1;
195  }
196 
197  if ( p_star_data_arg == NULL ) return -1;
198 
199  p_star_data_arg = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)p_star_data_arg, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
200  double* p_star_data = (double*)PyArray_DATA(p_star_data_arg);
201  int p_star_ndim = PyArray_NDIM(p_star_data_arg);
202  int p_star_shape = static_cast<int>(PyArray_DIMS(p_star_data_arg)[0]);
203 
204  if ( p_star_ndim != 1 ) {
205  PyErr_SetString(PyExc_ValueError, "p_star_data should be 1D array!");
206  return -1;
207  }
208 
209  std::vector<int> x_bitstrings_continous(x_bitsring_data, x_bitsring_data+(x_bistring_shape[0]*x_bistring_shape[1]));
210  std::vector<std::vector<int>> x_bitstrings(x_bistring_shape[0], std::vector<int>(x_bistring_shape[1]));
211 
212  // Calculate which data corresponds with which element of the state vector
213  std::vector<int> x_indices(x_bistring_shape[0], 0);
214  for (int idx_data=0; idx_data < x_bistring_shape[0]; idx_data++) {
215  for (int idx=0; idx < x_bistring_shape[1]; idx++) {
216  x_bitstrings[idx_data][idx] = x_bitstrings_continous[idx_data*x_bistring_shape[1]+idx];
217  if (x_bitstrings_continous[idx_data*x_bistring_shape[1]+idx] == 1) {
218  x_indices[idx_data] += Power_of_2(qbit_num-idx-1);
219  }
220  }
221  }
222 
223  Matrix_real p_stars = Matrix_real(p_star_data, p_star_shape, 1);
224 
225  if ( sigma_data_arg == NULL ) return -1;
226  if (!PyList_Check(sigma_data_arg)) {
227  PyErr_SetString(PyExc_TypeError, "sigma expected to be a list");
228  return -1;
229  }
230 
231  sigma_data_arg = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)sigma_data_arg, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
232  double* sigma_data = (double*)PyArray_DATA(sigma_data_arg);
233  int sigma_ndim = PyArray_NDIM(sigma_data_arg);
234  int sigma_shape = static_cast<int>(PyArray_DIMS(sigma_data_arg)[0]);
235 
236  if ( sigma_ndim != 1 || sigma_shape != 3 ) {
237  PyErr_SetString(PyExc_TypeError, "sigma expected to be a 1 by 3 list");
238  return -1;
239  }
240 
241  Matrix_real sigma(sigma_data, sigma_shape, 1);
242 
243  if ( cliques_data_arg == NULL ) return -1;
244  if (!PyList_Check(cliques_data_arg)) {
245  PyErr_SetString(PyExc_TypeError, "cliques expected to be a list of lists");
246  return -1;
247  }
248 
249  Py_ssize_t nrows = PyList_Size(cliques_data_arg);
250  std::vector<std::vector<int>> cliques;
251 
252  for (Py_ssize_t i = 0; i < nrows; i++) {
253  PyObject *row = PyList_GetItem(cliques_data_arg, i); // borrowed ref
254  std::vector<int> clique;
255 
256  if (!PyList_Check(row)) {
257  PyErr_SetString(PyExc_TypeError, "cliques Expected a list of lists");
258  return -1;
259  }
260 
261  Py_ssize_t ncols = PyList_Size(row);
262 
263  for (Py_ssize_t j = 0; j < ncols; j++) {
264  PyObject *item = PyList_GetItem(row, j); // borrowed ref
265 
266  if (!PyFloat_Check(item) && !PyLong_Check(item)) {
267  PyErr_SetString(PyExc_TypeError, "List elements must be numbers");
268  return -1;
269  }
270 
271  clique.push_back(static_cast<int>(PyFloat_AsDouble(item)));
272  }
273  cliques.push_back(clique);
274  }
275 
276  // integer type config metadata utilized during the optimization
277  std::map<std::string, Config_Element> config;
278 
279 
280  // keys and values of the config dict
281  PyObject *key, *value;
282  Py_ssize_t pos = 0;
283 
284  while (PyDict_Next(config_arg, &pos, &key, &value)) {
285 
286  // determine the initial guess type
287  PyObject* key_string = PyObject_Str(key);
288  PyObject* key_string_unicode = PyUnicode_AsEncodedString(key_string, "utf-8", "~E~");
289  const char* key_C = PyBytes_AS_STRING(key_string_unicode);
290 
291  std::string key_Cpp( key_C );
292  Config_Element element;
293 
294  if (PyBool_Check(value)) {
295  element.set_property(key_Cpp, value == Py_True);
296  config[key_Cpp] = element;
297  }
298  else if ( PyLong_Check( value ) ) {
299  element.set_property( key_Cpp, PyLong_AsLongLong( value ) );
300  config[ key_Cpp ] = element;
301  }
302  else if ( PyFloat_Check( value ) ) {
303  element.set_property( key_Cpp, PyFloat_AsDouble( value ) );
304  config[ key_Cpp ] = element;
305  }
306  else {
307 
308  }
309 
310  }
311 
312  // create an instance of the class Generative_Quantum_Machine_Learning_Base
313  if (qbit_num > 0 ) {
314  self->gqml = create_qgd_Generative_Quantum_Machine_Learning_Base(x_indices, x_bitstrings, p_stars, sigma, qbit_num, use_lookup_table, cliques, use_exact, config);
315  }
316  else {
317  std::cout << "The number of qubits should be given as a positive integer, " << qbit_num << " was given" << std::endl;
318  return -1;
319  }
320 
321 
322  std::cout << "reading args done" << std::endl;
323  return 0;
324 }
325 
326 
327 
332 static PyObject *
334 
335  int parameter_num = self->gqml->get_parameter_num();
336 
337  Matrix_real parameters_mtx(1, parameter_num);
338  double* parameters = parameters_mtx.get_data();
339  self->gqml->get_optimized_parameters(parameters);
340 
341 
342  // convert to numpy array
343  parameters_mtx.set_owner(false);
344  PyObject * parameter_arr = matrix_real_to_numpy( parameters_mtx );
345 
346  return parameter_arr;
347 }
348 
349 
350 static PyObject *
352 {
353 
354  // starting the decomposition
355  try {
356  self->gqml->start_optimization();
357  }
358  catch (std::string err) {
359  PyErr_SetString(PyExc_Exception, err.c_str());
360  std::cout << err << std::endl;
361  return NULL;
362  }
363  catch(...) {
364  std::string err( "Invalid pointer to decomposition class");
365  PyErr_SetString(PyExc_Exception, err.c_str());
366  return NULL;
367  }
368 
369 
370 
371  return Py_BuildValue("i", 0);
372 
373 }
374 
375 
379 static PyObject *
381 
382  int qbit_num = 0;
383 
384  try {
385  qbit_num = self->gqml->get_qbit_num();
386  }
387  catch (std::string err) {
388  PyErr_SetString(PyExc_Exception, err.c_str());
389  std::cout << err << std::endl;
390  return NULL;
391  }
392  catch(...) {
393  std::string err( "Invalid pointer to decomposition class");
394  PyErr_SetString(PyExc_Exception, err.c_str());
395  return NULL;
396  }
397 
398 
399  return Py_BuildValue("i", qbit_num );
400 
401 }
402 
403 
404 
408 static PyObject *
410 
411  PyArrayObject * parameters_arr = NULL;
412 
413 
414  // parsing input arguments
415  if (!PyArg_ParseTuple(args, "|O", &parameters_arr ))
416  return Py_BuildValue("i", -1);
417 
418 
419  if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
420  Py_INCREF(parameters_arr);
421  }
422  else {
423  parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
424  }
425 
426 
427  Matrix_real parameters_mtx = numpy2matrix_real( parameters_arr );
428 
429 
430 
431  try {
432  self->gqml->set_optimized_parameters(parameters_mtx.get_data(), parameters_mtx.size());
433  }
434  catch (std::string err ) {
435  PyErr_SetString(PyExc_Exception, err.c_str());
436  return NULL;
437  }
438  catch(...) {
439  std::string err( "Invalid pointer to decomposition class");
440  PyErr_SetString(PyExc_Exception, err.c_str());
441  return NULL;
442  }
443 
444  Py_DECREF(parameters_arr);
445 
446  return Py_BuildValue("i", 0);
447 }
448 
449 
450 
454 static PyObject *
456 
457  PyArrayObject * initial_state_arg = NULL;
458 
459  // parsing input arguments
460  if (!PyArg_ParseTuple(args, "|O", &initial_state_arg )) {
461  PyErr_SetString(PyExc_Exception, "error occured during input parsing");
462  return NULL;
463  }
464 
465  if ( PyArray_IS_C_CONTIGUOUS(initial_state_arg) ) {
466  Py_INCREF(initial_state_arg);
467  }
468  else {
469  initial_state_arg = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)initial_state_arg, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
470  }
471 
472 
473  Matrix initial_state_mtx = numpy2matrix( initial_state_arg );
474 
475 
476 
477  try {
478  self->gqml->set_initial_state( initial_state_mtx );
479  }
480  catch (std::string err ) {
481  PyErr_SetString(PyExc_Exception, err.c_str());
482  return NULL;
483  }
484  catch(...) {
485  std::string err( "Invalid pointer to decomposition class");
486  PyErr_SetString(PyExc_Exception, err.c_str());
487  return NULL;
488  }
489 
490 
491 
492 
493  Py_DECREF(initial_state_arg);
494 
495  return Py_BuildValue("i", 0);
496 }
497 
498 
502 static PyObject *
504 
505 
506 
507  // initiate variables for input arguments
508  PyObject* filename_py=NULL;
509 
510  // parsing input arguments
511  if (!PyArg_ParseTuple(args, "|O", &filename_py )) return Py_BuildValue("i", -1);
512 
513  // determine the optimizaton method
514  PyObject* filename_string = PyObject_Str(filename_py);
515  PyObject* filename_string_unicode = PyUnicode_AsEncodedString(filename_string, "utf-8", "~E~");
516  const char* filename_C = PyBytes_AS_STRING(filename_string_unicode);
517  std::string filename_str( filename_C );
518 
519 
520  try {
521  self->gqml->set_gate_structure( filename_str );
522  }
523  catch (std::string err ) {
524  PyErr_SetString(PyExc_Exception, err.c_str());
525  return NULL;
526  }
527  catch(...) {
528  std::string err( "Invalid pointer to decomposition class");
529  PyErr_SetString(PyExc_Exception, err.c_str());
530  return NULL;
531  }
532 
533 
534 
535  return Py_BuildValue("i", 0);
536 
537 }
538 
539 static PyObject *
541 
542  // initiate variables for input arguments
543  double tolerance;
544 
545  // parsing input arguments
546  if (!PyArg_ParseTuple(args, "|d", &tolerance )) return Py_BuildValue("i", -1);
547 
548 
549  // set maximal layer nums on the C++ side
550  self->gqml->set_optimization_tolerance( tolerance );
551 
552 
553  return Py_BuildValue("i", 0);
554 }
555 
556 
557 
558 static PyObject *
560 
561  PyArrayObject * parameters_arr = NULL;
562  PyArrayObject * unitary_arg = NULL;
563 
564 
565  // parsing input arguments
566  if (!PyArg_ParseTuple(args, "|OO", &parameters_arr, &unitary_arg ))
567  return Py_BuildValue("i", -1);
568 
569 
570  if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
571  Py_INCREF(parameters_arr);
572  }
573  else {
574  parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
575  }
576 
577  // get the C++ wrapper around the data
578  Matrix_real&& parameters_mtx = numpy2matrix_real( parameters_arr );
579 
580 
581  // convert python object array to numpy C API array
582  if ( unitary_arg == NULL ) {
583  PyErr_SetString(PyExc_Exception, "Input matrix was not given");
584  return NULL;
585  }
586 
587  PyArrayObject* unitary = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)unitary_arg, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
588 
589  // test C-style contiguous memory allocation of the array
590  if ( !PyArray_IS_C_CONTIGUOUS(unitary) ) {
591  PyErr_SetString(PyExc_Exception, "input mtrix is not memory contiguous");
592  return NULL;
593  }
594 
595 
596  // create QGD version of the input matrix
597  Matrix unitary_mtx = numpy2matrix(unitary);
598 
599 
600  self->gqml->apply_to( parameters_mtx, unitary_mtx );
601 
602  if (unitary_mtx.data != PyArray_DATA(unitary)) {
603  memcpy(PyArray_DATA(unitary), unitary_mtx.data, unitary_mtx.size() * sizeof(QGD_Complex16));
604  }
605 
606  Py_DECREF(parameters_arr);
607  Py_DECREF(unitary);
608 
609  return Py_BuildValue("i", 0);
610 }
611 
612 
613 
614 static PyObject *
616 {
617 
618  // The tuple of expected keywords
619  static char *kwlist[] = {(char*)"optimizer", NULL};
620 
621  PyObject* optimizer_arg = NULL;
622 
623 
624  // parsing input arguments
625  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &optimizer_arg)) {
626 
627  std::string err( "Unsuccessful argument parsing not ");
628  PyErr_SetString(PyExc_Exception, err.c_str());
629  return NULL;
630 
631  }
632 
633  if ( optimizer_arg == NULL ) {
634  std::string err( "optimizer argument not set");
635  PyErr_SetString(PyExc_Exception, err.c_str());
636  return NULL;
637  }
638 
639 
640  PyObject* optimizer_string = PyObject_Str(optimizer_arg);
641  PyObject* optimizer_string_unicode = PyUnicode_AsEncodedString(optimizer_string, "utf-8", "~E~");
642  const char* optimizer_C = PyBytes_AS_STRING(optimizer_string_unicode);
643 
644  optimization_aglorithms qgd_optimizer;
645  if ( strcmp("agents", optimizer_C) == 0 || strcmp("AGENTS", optimizer_C) == 0) {
646  qgd_optimizer = AGENTS;
647  }
648  else if ( strcmp("agents_combined", optimizer_C)==0 || strcmp("AGENTS_COMBINED", optimizer_C)==0) {
649  qgd_optimizer = AGENTS_COMBINED;
650  }
651  else if ( strcmp("cosined", optimizer_C)==0 || strcmp("COSINE", optimizer_C)==0) {
652  qgd_optimizer = COSINE;
653  }
654  else if ( strcmp("grad_descend_phase_shift_rule", optimizer_C)==0 || strcmp("GRAD_DESCEND_PARAMETER_SHIFT_RULE", optimizer_C)==0) {
655  qgd_optimizer = GRAD_DESCEND_PARAMETER_SHIFT_RULE;
656  }
657  else if ( strcmp("bfgs", optimizer_C)==0 || strcmp("BFGS", optimizer_C)==0) {
658  qgd_optimizer = BFGS;
659  }
660  else if ( strcmp("adam", optimizer_C)==0 || strcmp("ADAM", optimizer_C)==0) {
661  qgd_optimizer = ADAM;
662  }
663  else if ( strcmp("grad_descend", optimizer_C)==0 || strcmp("GRAD_DESCEND", optimizer_C)==0) {
664  qgd_optimizer = GRAD_DESCEND;
665  }
666  else if ( strcmp("bayes_opt", optimizer_C)==0 || strcmp("BAYES_OPT", optimizer_C)==0) {
667  qgd_optimizer = BAYES_OPT;
668  }
669  else if ( strcmp("bayes_agents", optimizer_C)==0 || strcmp("BAYES_AGENTS", optimizer_C)==0) {
670  qgd_optimizer = BAYES_AGENTS;
671  }
672  else {
673  std::cout << "Wrong optimizer. Using default: AGENTS" << std::endl;
674  qgd_optimizer = AGENTS;
675  }
676 
677 
678  try {
679  self->gqml->set_optimizer(qgd_optimizer);
680  }
681  catch (std::string err) {
682  PyErr_SetString(PyExc_Exception, err.c_str());
683  std::cout << err << std::endl;
684  return NULL;
685  }
686  catch(...) {
687  std::string err( "Invalid pointer to decomposition class");
688  PyErr_SetString(PyExc_Exception, err.c_str());
689  return NULL;
690  }
691 
692 
693  return Py_BuildValue("i", 0);
694 
695 }
696 
697 static PyObject *
699 {
700 
701  // The tuple of expected keywords
702  static char *kwlist[] = {(char*)"optimizer", NULL};
703 
704  PyObject* ansatz_arg = NULL;
705 
706 
707  // parsing input arguments
708  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &ansatz_arg)) {
709 
710  std::string err( "Unsuccessful argument parsing not ");
711  PyErr_SetString(PyExc_Exception, err.c_str());
712  return NULL;
713 
714  }
715 
716 
717  if ( ansatz_arg == NULL ) {
718  std::string err( "optimizer argument not set");
719  PyErr_SetString(PyExc_Exception, err.c_str());
720  return NULL;
721  }
722 
723 
724 
725  PyObject* ansatz_string = PyObject_Str(ansatz_arg);
726  PyObject* ansatz_string_unicode = PyUnicode_AsEncodedString(ansatz_string, "utf-8", "~E~");
727  const char* ansatz_C = PyBytes_AS_STRING(ansatz_string_unicode);
728 
729 
730  ansatz_type qgd_ansatz;
731 
732  if ( strcmp("hea", ansatz_C) == 0 || strcmp("HEA", ansatz_C) == 0) {
733  qgd_ansatz = HEA;
734  }
735  else if ( strcmp("hea_zyz", ansatz_C) == 0 || strcmp("HEA_ZYZ", ansatz_C) == 0) {
736  qgd_ansatz = HEA_ZYZ;
737  }
738  else if ( strcmp("qcmrf", ansatz_C) == 0 || strcmp("QCMRF", ansatz_C) == 0) {
739  qgd_ansatz = QCMRF;
740  }
741  else {
742  std::cout << "Wrong ansatz. Using default: HEA" << std::endl;
743  qgd_ansatz = HEA;
744  }
745 
746 
747  try {
748  self->gqml->set_ansatz(qgd_ansatz);
749  }
750  catch (std::string err) {
751  PyErr_SetString(PyExc_Exception, err.c_str());
752  std::cout << err << std::endl;
753  return NULL;
754  }
755  catch(...) {
756  std::string err( "Invalid pointer to decomposition class");
757  PyErr_SetString(PyExc_Exception, err.c_str());
758  return NULL;
759  }
760 
761 
762  return Py_BuildValue("i", 0);
763 
764 }
765 
766 
770 static PyObject *
772 {
773 
774 
775  PyArrayObject * parameters_arr = NULL;
776  PyArrayObject * input_state_arg = NULL;
777  PyObject * qubit_list_arg = NULL;
778 
779 
780  // parsing input arguments
781  if (!PyArg_ParseTuple(args, "|OOO", &parameters_arr, &input_state_arg, &qubit_list_arg ))
782  return Py_BuildValue("i", -1);
783 
784 
785  if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
786  Py_INCREF(parameters_arr);
787  }
788  else {
789  parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
790  }
791 
792  // get the C++ wrapper around the data
793  Matrix_real&& parameters_mtx = numpy2matrix_real( parameters_arr );
794 
795  // convert python object array to numpy C API array
796  if ( input_state_arg == NULL ) {
797  PyErr_SetString(PyExc_Exception, "Input matrix was not given");
798  return NULL;
799  }
800 
801  PyArrayObject* input_state = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)input_state_arg, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
802 
803  // test C-style contiguous memory allocation of the array
804  if ( !PyArray_IS_C_CONTIGUOUS(input_state) ) {
805  PyErr_SetString(PyExc_Exception, "input mtrix is not memory contiguous");
806  return NULL;
807  }
808 
809 
810  // create QGD version of the input matrix
811  Matrix input_state_mtx = numpy2matrix(input_state);
812 
813 
814  // check input argument qbit_list
815  if ( qubit_list_arg == NULL || (!PyList_Check( qubit_list_arg )) ) {
816  PyErr_SetString(PyExc_Exception, "qubit_list should be a list");
817  return NULL;
818  }
819 
820  Py_ssize_t reduced_qbit_num = PyList_Size( qubit_list_arg );
821 
822  matrix_base<int> qbit_list_mtx( (int)reduced_qbit_num, 1);
823  for ( int idx=0; idx<reduced_qbit_num; idx++ ) {
824 
825  PyObject* item = PyList_GET_ITEM( qubit_list_arg, idx );
826  qbit_list_mtx[idx] = (int) PyLong_AsLong( item );
827 
828  }
829 
830 
831  double entropy = -1;
832 
833 
834  try {
835  entropy = self->gqml->get_second_Renyi_entropy( parameters_mtx, input_state_mtx, qbit_list_mtx );
836  }
837  catch (std::string err) {
838  PyErr_SetString(PyExc_Exception, err.c_str());
839  std::cout << err << std::endl;
840  return NULL;
841  }
842  catch(...) {
843  std::string err( "Invalid pointer to decomposition class");
844  PyErr_SetString(PyExc_Exception, err.c_str());
845  return NULL;
846  }
847 
848 
849  Py_DECREF(parameters_arr);
850  Py_DECREF(input_state);
851 
852 
853 
854  PyObject* p = Py_BuildValue("d", entropy);
855 
856  return p;
857 }
858 
859 
860 static PyObject *
862 
863  // initiate variables for input arguments
864  int layers;
865  int inner_blocks;
866 
867  // parsing input arguments
868  if (!PyArg_ParseTuple(args, "|ii", &layers, &inner_blocks )) return Py_BuildValue("i", -1);
869 
870 
871  try {
872  self->gqml->generate_circuit( layers, inner_blocks );
873  }
874  catch (std::string err) {
875  PyErr_SetString(PyExc_Exception, err.c_str());
876  std::cout << err << std::endl;
877  return NULL;
878  }
879  catch(...) {
880  std::string err( "Invalid pointer to decomposition class");
881  PyErr_SetString(PyExc_Exception, err.c_str());
882  return NULL;
883  }
884 
885  return Py_BuildValue("i", 0);
886 
887 
888 }
889 
890 static PyObject *
892 {
893 
894 
895  PyArrayObject* parameters_arg = NULL;
896 
897 
898  // parsing input arguments
899  if (!PyArg_ParseTuple(args, "|O", &parameters_arg )) {
900 
901  std::string err( "Unsuccessful argument parsing not ");
902  PyErr_SetString(PyExc_Exception, err.c_str());
903  return NULL;
904 
905  }
906 
907  // establish memory contiguous arrays for C calculations
908  if ( PyArray_IS_C_CONTIGUOUS(parameters_arg) && PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ){
909  Py_INCREF(parameters_arg);
910  }
911  else if (PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ) {
912  parameters_arg = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arg, NPY_FLOAT64, NPY_ARRAY_IN_ARRAY);
913  }
914  else {
915  std::string err( "Parameters should be should be real (given in float64 format)");
916  PyErr_SetString(PyExc_Exception, err.c_str());
917  return NULL;
918  }
919 
920 
921  Matrix_real parameters_mtx = numpy2matrix_real( parameters_arg );
922  double f0;
923 
924  try {
925  f0 = self->gqml->optimization_problem(parameters_mtx );
926  }
927  catch (std::string err ) {
928  PyErr_SetString(PyExc_Exception, err.c_str());
929  return NULL;
930  }
931  catch (...) {
932  std::string err( "Invalid pointer to decomposition class");
933  PyErr_SetString(PyExc_Exception, err.c_str());
934  return NULL;
935  }
936 
937  Py_DECREF(parameters_arg);
938 
939 
940  return Py_BuildValue("d", f0);
941 }
942 
943 
947 static PyObject *
949 
950  int parameter_num = self->gqml->get_parameter_num();
951 
952  return Py_BuildValue("i", parameter_num);
953 }
954 
955 
956 
957 
958 
963 static PyObject *
965 
966 
967  PyObject* qgd_Circuit = PyImport_ImportModule("squander.gates.qgd_Circuit");
968 
969  if ( qgd_Circuit == NULL ) {
970  PyErr_SetString(PyExc_Exception, "Module import error: squander.gates.qgd_Circuit" );
971  return NULL;
972  }
973 
974  // retrieve the C++ variant of the flat circuit (flat circuit does not conatain any sub-circuits)
975  Gates_block* circuit = self->gqml->get_flat_circuit();
976 
977 
978 
979  // construct python interfarce for the circuit
980  PyObject* qgd_circuit_Dict = PyModule_GetDict( qgd_Circuit );
981 
982  // 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
983  PyObject* py_circuit_class = PyDict_GetItemString( qgd_circuit_Dict, "qgd_Circuit");
984 
985  // create gate parameters
986  PyObject* qbit_num = Py_BuildValue("i", circuit->get_qbit_num() );
987  PyObject* circuit_input = Py_BuildValue("(O)", qbit_num);
988 
989  PyObject* py_circuit = PyObject_CallObject(py_circuit_class, circuit_input);
990  qgd_Circuit_Wrapper* py_circuit_C = reinterpret_cast<qgd_Circuit_Wrapper*>( py_circuit );
991 
992 
993  // replace the empty circuit with the extracted one
994 
995  delete( py_circuit_C->gate );
996  py_circuit_C->gate = circuit;
997 
998 
999  return py_circuit;
1000 
1001 }
1002 
1003 
1004 
1005 
1009 static PyObject *
1011  // initiate variables for input arguments
1012  PyObject* project_name_new=NULL;
1013 
1014  // parsing input arguments
1015  if (!PyArg_ParseTuple(args, "|O", &project_name_new)) return Py_BuildValue("i", -1);
1016 
1017 
1018  PyObject* project_name_new_string = PyObject_Str(project_name_new);
1019  PyObject* project_name_new_unicode = PyUnicode_AsEncodedString(project_name_new_string, "utf-8", "~E~");
1020  const char* project_name_new_C = PyBytes_AS_STRING(project_name_new_unicode);
1021  std::string project_name_new_str = ( project_name_new_C );
1022 
1023  // convert to python string
1024  self->gqml->set_project_name(project_name_new_str);
1025 
1026  return Py_BuildValue("i", 0);
1027 }
1028 
1029 
1035 static PyObject *
1037 
1038  // initiate variables for input arguments
1039  PyObject* gate_structure_py;
1040 
1041  // parsing input arguments
1042  if (!PyArg_ParseTuple(args, "|O", &gate_structure_py )) return Py_BuildValue("i", -1);
1043 
1044 
1045  // convert gate structure from PyObject to qgd_Circuit_Wrapper
1046  qgd_Circuit_Wrapper* qgd_op_block = (qgd_Circuit_Wrapper*) gate_structure_py;
1047 
1048  try {
1049  self->gqml->set_custom_gate_structure( qgd_op_block->gate );
1050  }
1051  catch (std::string err ) {
1052  PyErr_SetString(PyExc_Exception, err.c_str());
1053  return NULL;
1054  }
1055  catch(...) {
1056  std::string err( "Invalid pointer to decomposition class");
1057  PyErr_SetString(PyExc_Exception, err.c_str());
1058  return NULL;
1059  }
1060 
1061 
1062  return Py_BuildValue("i", 0);
1063 
1064 
1065 }
1066 
1071  {NULL} /* Sentinel */
1072 };
1073 
1078  {"Start_Optimization", (PyCFunction) qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_Start_Optimization, METH_NOARGS,
1079  "Method to start the decomposition."
1080  },
1081  {"get_Optimized_Parameters", (PyCFunction) qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_get_Optimized_Parameters, METH_NOARGS,
1082  "Method to get the array of optimized parameters."
1083  },
1084  {"set_Optimized_Parameters", (PyCFunction) qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_set_Optimized_Parameters, METH_VARARGS,
1085  "Method to set the array of optimized parameters."
1086  },
1087  {"set_Optimization_Tolerance", (PyCFunction) qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_set_Optimization_Tolerance, METH_VARARGS,
1088  "Method to set optimization tolerance"
1089  },
1090  {"get_Circuit", (PyCFunction) qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_get_circuit, METH_NOARGS,
1091  "Method to get the incorporated circuit."
1092  },
1093  {"set_Project_Name", (PyCFunction) qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_set_Project_Name, METH_VARARGS,
1094  "method to set project name."
1095  },
1096  {"set_Gate_Structure_From_Binary", (PyCFunction) qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_set_Gate_Structure_From_Binary, METH_VARARGS,
1097  "Method to set the gate structure from a file created in SQUANDER."
1098  },
1099  {"apply_to", (PyCFunction) qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_apply_to, METH_VARARGS,
1100  "Call to apply the gate on the input matrix."
1101  },
1102  {"set_Optimizer", (PyCFunction) qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_set_Optimizer, METH_VARARGS | METH_KEYWORDS,
1103  "Method to set optimizer."
1104  },
1105  {"set_Ansatz", (PyCFunction) qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_set_Ansatz, METH_VARARGS | METH_KEYWORDS,
1106  "Method to set ansatz type."
1107  },
1108  {"get_Parameter_Num", (PyCFunction) qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_get_Parameter_Num, METH_NOARGS,
1109  "Call to get the number of free parameters in the gate structure used for the decomposition"
1110  },
1111  {"Generate_Circuit", (PyCFunction) qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_Generate_Circuit, METH_VARARGS,
1112  "Method to set the circuit based on the ansatz type."
1113  },
1114  {"Optimization_Problem", (PyCFunction) qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_Optimization_Problem, METH_VARARGS,
1115  "Method to get the expected energy of the circuit at parameters."
1116  },
1117  {"get_Second_Renyi_Entropy", (PyCFunction) qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_get_Second_Renyi_Entropy, METH_VARARGS,
1118  "Wrapper function to evaluate the second Rényi entropy of a quantum circuit at a specific parameter set."
1119  },
1120  {"get_Qbit_Num", (PyCFunction) qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_get_Qbit_Num, METH_NOARGS,
1121  "Call to get the number of qubits in the circuit"
1122  },
1123  {"set_Initial_State", (PyCFunction) qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_set_Initial_State, METH_VARARGS,
1124  "Call to set the initial state used in the VQE process."
1125  },
1126  {"set_Gate_Structure", (PyCFunction) qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_set_Gate_Structure, METH_VARARGS,
1127  "Call to set custom gate structure for VQE experiments."
1128  },
1129  {NULL} /* Sentinel */
1130 };
1131 
1136  PyVarObject_HEAD_INIT(NULL, 0)
1137  "qgd_N_Qubit_Decomposition_Wrapper.qgd_N_Qubit_Decomposition_Wrapper", /*tp_name*/
1139  0, /*tp_itemsize*/
1141  #if PY_VERSION_HEX < 0x030800b4
1142  0, /*tp_print*/
1143  #endif
1144  #if PY_VERSION_HEX >= 0x030800b4
1145  0, /*tp_vectorcall_offset*/
1146  #endif
1147  0, /*tp_getattr*/
1148  0, /*tp_setattr*/
1149  #if PY_MAJOR_VERSION < 3
1150  0, /*tp_compare*/
1151  #endif
1152  #if PY_MAJOR_VERSION >= 3
1153  0, /*tp_as_async*/
1154  #endif
1155  0, /*tp_repr*/
1156  0, /*tp_as_number*/
1157  0, /*tp_as_sequence*/
1158  0, /*tp_as_mapping*/
1159  0, /*tp_hash*/
1160  0, /*tp_call*/
1161  0, /*tp_str*/
1162  0, /*tp_getattro*/
1163  0, /*tp_setattro*/
1164  0, /*tp_as_buffer*/
1165  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
1166  "Object to represent a Gates_block class of the QGD package.", /*tp_doc*/
1167  0, /*tp_traverse*/
1168  0, /*tp_clear*/
1169  0, /*tp_richcompare*/
1170  0, /*tp_weaklistoffset*/
1171  0, /*tp_iter*/
1172  0, /*tp_iternext*/
1175  0, /*tp_getset*/
1176  0, /*tp_base*/
1177  0, /*tp_dict*/
1178  0, /*tp_descr_get*/
1179  0, /*tp_descr_set*/
1180  0, /*tp_dictoffset*/
1182  0, /*tp_alloc*/
1184  0, /*tp_free*/
1185  0, /*tp_is_gc*/
1186  0, /*tp_bases*/
1187  0, /*tp_mro*/
1188  0, /*tp_cache*/
1189  0, /*tp_subclasses*/
1190  0, /*tp_weaklist*/
1191  0, /*tp_del*/
1192  0, /*tp_version_tag*/
1193  #if PY_VERSION_HEX >= 0x030400a1
1194  0, /*tp_finalize*/
1195  #endif
1196  #if PY_VERSION_HEX >= 0x030800b1
1197  0, /*tp_vectorcall*/
1198  #endif
1199  #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000
1200  0, /*tp_print*/
1201  #endif
1202 };
1203 
1208  PyModuleDef_HEAD_INIT,
1209  "qgd_N_Qubit_Decomposition_Wrapper",
1210  "Python binding for QGD N_Qubit_Decomposition class",
1211  -1,
1212 };
1213 
1214 
1218 PyMODINIT_FUNC
1220 {
1221  // initialize Numpy API
1222  import_array();
1223 
1224  PyObject *m;
1225  if (PyType_Ready(&qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_Type) < 0)
1226  return NULL;
1227 
1228  m = PyModule_Create(&qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_Module);
1229  if (m == NULL)
1230  return NULL;
1231 
1232  Py_INCREF(&qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_Type);
1233  if (PyModule_AddObject(m, "qgd_Generative_Quantum_Machine_Learning_Base_Wrapper", (PyObject *) &qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_Type) < 0) {
1234  Py_DECREF(&qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_Type);
1235  Py_DECREF(m);
1236  return NULL;
1237  }
1238 
1239  return m;
1240 }
1241 
1242 
1243 } //extern C
1244 
1245 
Gates_block * get_flat_circuit()
Method to generate a flat circuit.
Type definition of the qgd_N_Qubit_Decomposition_Wrapper Python class of the qgd_N_Qubit_Decompositio...
parameter_num
[set adaptive gate structure]
ansatz_type
Type definition of the fifferent types of ansatz.
key
Definition: noise.py:86
return Py_BuildValue("i", 0)
Matrix_real numpy2matrix_real(PyArrayObject *arr)
Call to create a PIC matrix_real representation of a numpy array.
PyMODINIT_FUNC PyInit_qgd_Generative_Quantum_Machine_Learning_Base_Wrapper(void)
Method called when the Python module is initialized.
scalar * data
pointer to the stored data
Definition: matrix_base.hpp:48
PyObject * matrix_real_to_numpy(Matrix_real &mtx)
Call to make a numpy array from an instance of matrix class.
static void qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_dealloc(qgd_Generative_Quantum_Machine_Learning_Base_Wrapper *self)
Method called when a python instance of the class qgd_Generative_Quantum_Machine_Learning_Base_Wrappe...
U3 RX RZ H Y SX S T CNOT CH SYC CRZ PyObject PyObject * kwds
A class describing a universal configuration element.
static PyObject * qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_Generate_Circuit(qgd_Generative_Quantum_Machine_Learning_Base_Wrapper *self, PyObject *args)
scalar * get_data() const
Call to get the pointer to the stored data.
Generative_Quantum_Machine_Learning_Base * create_qgd_Generative_Quantum_Machine_Learning_Base(std::vector< int > x_vectors, std::vector< std::vector< int >> x_bitstrings, Matrix_real P_star, Matrix_real sigma, int qbit_num, bool use_lookup_table, std::vector< std::vector< int >> cliques, bool use_exact, std::map< std::string, Config_Element > &config)
Creates an instance of class Generative_Quantum_Machine_Learning_Base and return with a pointer point...
static PyObject * qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_set_Gate_Structure_From_Binary(qgd_Generative_Quantum_Machine_Learning_Base_Wrapper *self, PyObject *args)
Wrapper function to set custom layers to the gate structure that are intended to be used in the decom...
static PyObject * qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_get_Optimized_Parameters(qgd_Generative_Quantum_Machine_Learning_Base_Wrapper *self)
Extract the optimized parameters.
static PyObject * qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_set_Ansatz(qgd_Generative_Quantum_Machine_Learning_Base_Wrapper *self, PyObject *args, PyObject *kwds)
bool use_exact
Definition: GQML_test.py:55
optimization_aglorithms
implemented optimization strategies
static PyMemberDef qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_members[]
Structure containing metadata about the members of class qgd_N_Qubit_Decomposition_Wrapper.
static PyObject * qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_apply_to(qgd_Generative_Quantum_Machine_Learning_Base_Wrapper *self, PyObject *args)
static PyObject * qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_set_Project_Name(qgd_Generative_Quantum_Machine_Learning_Base_Wrapper *self, PyObject *args)
Call to set a project name.
U3 RX RZ H Y SX S T CNOT CH SYC CRZ PyObject * args
PyObject_HEAD Gates_block * gate
A base class to solve GQML problems This class can be used to approximate a given distribution via a ...
static PyObject * qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_get_Second_Renyi_Entropy(qgd_Generative_Quantum_Machine_Learning_Base_Wrapper *self, PyObject *args)
Wrapper function to evaluate the second Rényi entropy of a quantum circuit at a specific parameter s...
static PyObject * qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_Optimization_Problem(qgd_Generative_Quantum_Machine_Learning_Base_Wrapper *self, PyObject *args)
static PyObject * qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_get_Qbit_Num(qgd_Generative_Quantum_Machine_Learning_Base_Wrapper *self)
Call to retrieve the number of qubits in the circuit.
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...
Generative_Quantum_Machine_Learning_Base * gqml
An object to decompose the unitary.
Structure type representing complex numbers in the SQUANDER package.
Definition: QGDTypes.h:38
static int qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_init(qgd_Generative_Quantum_Machine_Learning_Base_Wrapper *self, PyObject *args, PyObject *kwds)
Method called when a python instance of the class qgd_Generative_Quantum_Machine_Learning_Base_Wrappe...
int Power_of_2(int n)
Calculates the n-th power of 2.
Definition: common.cpp:136
Double-precision complex matrix (float64).
Definition: matrix.h:38
dictionary config
int size() const
Call to get the number of the allocated elements.
PyObject_HEAD PyObject * x_vectors
pointer to the unitary to be decomposed to keep it alive
void release_Generative_Quantum_Machine_Learning_Base(Generative_Quantum_Machine_Learning_Base *instance)
Call to deallocate an instance of Generative_Quantum_Machine_Learning_Base class. ...
A class responsible for grouping two-qubit (CNOT,CZ,CH) and one-qubit gates into layers.
Definition: Gates_block.h:44
list sigma
Definition: GQML_test.py:51
bool use_lookup_table
Definition: GQML_test.py:54
Class to solve GQML problems.
void set_property(std::string name_, double val_)
Call to set a double value.
static PyObject * qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_get_circuit(qgd_Generative_Quantum_Machine_Learning_Base_Wrapper *self)
Wrapper function to retrieve the circuit (Squander format) incorporated in the instance.
static PyObject * qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Method called when a python instance of the class qgd_Generative_Quantum_Machine_Learning_Base_Wrappe...
Matrix numpy2matrix(PyArrayObject *arr)
Call to create a PIC matrix representation of a numpy array.
static PyMethodDef qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_methods[]
Structure containing metadata about the methods of class qgd_N_Qubit_Decomposition_Wrapper.
PyObject_HEAD Gates_block * circuit
Pointer to the C++ class of the base Gate_block module.
static PyTypeObject qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_Type
A structure describing the type of the class qgd_N_Qubit_Decomposition_Wrapper.
static PyObject * qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_set_Optimized_Parameters(qgd_Generative_Quantum_Machine_Learning_Base_Wrapper *self, PyObject *args)
Set parameters for the solver.
int get_qbit_num()
Call to get the number of qubits composing the unitary.
Definition: Gate.cpp:1342
Type definition for qgd_Circuit_Wrapper.
static PyObject * qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_set_Optimization_Tolerance(qgd_Generative_Quantum_Machine_Learning_Base_Wrapper *self, PyObject *args)
static PyObject * qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_set_Initial_State(qgd_Generative_Quantum_Machine_Learning_Base_Wrapper *self, PyObject *args)
Set the initial state used in the VQE process.
static PyModuleDef qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_Module
Structure containing metadata about the module.
static PyObject * qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_set_Optimizer(qgd_Generative_Quantum_Machine_Learning_Base_Wrapper *self, PyObject *args, PyObject *kwds)
static PyObject * qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_get_Parameter_Num(qgd_Generative_Quantum_Machine_Learning_Base_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:41
static PyObject * qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_Start_Optimization(qgd_Generative_Quantum_Machine_Learning_Base_Wrapper *self)
static PyObject * qgd_Generative_Quantum_Machine_Learning_Base_Wrapper_set_Gate_Structure(qgd_Generative_Quantum_Machine_Learning_Base_Wrapper *self, PyObject *args)
Wrapper function to set custom gate structure for the decomposition.