Sequential Quantum Gate Decomposer  v1.9.3
Powerful decomposition of general unitarias into one- and two-qubit gates gates
qgd_VQE_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 
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 *Hamiltonian;
56 
58 
59 
60 
70 create_qgd_Variational_Quantum_Eigensolver_Base( Matrix_sparse Hamiltonian, int qbit_num, std::map<std::string, Config_Element>& config, int accelerator_num) {
71 
72  return new Variational_Quantum_Eigensolver_Base( Hamiltonian, qbit_num, config, accelerator_num);
73 }
74 
75 
80 void
82 
83  if (instance != NULL ) {
84  delete instance;
85  }
86  return;
87 }
88 
89 
90 
91 extern "C"
92 {
93 
94 
99 static void
101 {
102 
103  if ( self->vqe != NULL ) {
104  // deallocate the instance of class N_Qubit_Decomposition
106  self->vqe = NULL;
107  }
108 
109  if ( self->Hamiltonian != NULL ) {
110  // release the unitary to be decomposed
111  Py_DECREF(self->Hamiltonian);
112  self->Hamiltonian = NULL;
113  }
114 
115  Py_TYPE(self)->tp_free((PyObject *) self);
116 
117 }
118 
123 static PyObject *
125 {
127  self = (qgd_Variational_Quantum_Eigensolver_Base_Wrapper *) type->tp_alloc(type, 0);
128  if (self != NULL) {}
129 
130  self->vqe = NULL;
131  self->Hamiltonian = NULL;
132 
133  return (PyObject *) self;
134 }
135 
136 
143 static int
145 {
146  // The tuple of expected keywords
147  static char *kwlist[] = {(char*)"Hamiltonian_data", (char*)"Hamiltonian_indices", (char*)"Hamiltonian_indptr", (char*)"qbit_num", (char*)"config", (char*)"accelerator_num", NULL};
148 
149  // initiate variables for input arguments
150  PyArrayObject *Hamiltonian_data_arg = NULL;
151  PyArrayObject *Hamiltonian_indices_arg = NULL;
152  PyArrayObject *Hamiltonian_indptr_arg = NULL;
153  int qbit_num = -1;
154  PyObject *config_arg = NULL;
155  int accelerator_num = 0;
156 
157  // parsing input arguments
158  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOiOi", kwlist,
159  &Hamiltonian_data_arg, &Hamiltonian_indices_arg, &Hamiltonian_indptr_arg, &qbit_num, &config_arg, &accelerator_num))
160  return -1;
161 
162  int shape = Power_of_2(qbit_num);
163  // convert python object array to numpy C API array
164  if ( Hamiltonian_data_arg == NULL ) return -1;
165 
166  Hamiltonian_data_arg = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)Hamiltonian_data_arg, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
167  QGD_Complex16* Hamiltonian_data = (QGD_Complex16*)PyArray_DATA(Hamiltonian_data_arg);
168  int NNZ = PyArray_DIMS(Hamiltonian_data_arg)[0];
169 
170  if ( Hamiltonian_indices_arg == NULL ) return -1;
171 
172  Hamiltonian_indices_arg = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)Hamiltonian_indices_arg, NPY_INT32, NPY_ARRAY_IN_ARRAY);
173  int* Hamiltonian_indices = (int*)PyArray_DATA(Hamiltonian_indices_arg);
174 
175  if ( Hamiltonian_indptr_arg == NULL ) return -1;
176 
177  Hamiltonian_indptr_arg = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)Hamiltonian_indptr_arg, NPY_INT32, NPY_ARRAY_IN_ARRAY);
178  int* Hamiltonian_indptr = (int*)PyArray_DATA(Hamiltonian_indptr_arg);
179 
180  Matrix_sparse Hamiltonian_mtx = Matrix_sparse(Hamiltonian_data, shape, shape, NNZ, Hamiltonian_indices, Hamiltonian_indptr);
181 
182  // integer type config metadata utilized during the optimization
183  std::map<std::string, Config_Element> config;
184 
185 
186  // keys and values of the config dict
187  PyObject *key, *value;
188  Py_ssize_t pos = 0;
189 
190  while (PyDict_Next(config_arg, &pos, &key, &value)) {
191 
192  // determine the initial guess type
193  PyObject* key_string = PyObject_Str(key);
194  PyObject* key_string_unicode = PyUnicode_AsEncodedString(key_string, "utf-8", "~E~");
195  const char* key_C = PyBytes_AS_STRING(key_string_unicode);
196 
197  std::string key_Cpp( key_C );
198  Config_Element element;
199 
200  if ( PyLong_Check( value ) ) {
201  element.set_property( key_Cpp, PyLong_AsLongLong( value ) );
202  config[ key_Cpp ] = element;
203  }
204  else if ( PyFloat_Check( value ) ) {
205  element.set_property( key_Cpp, PyFloat_AsDouble( value ) );
206  config[ key_Cpp ] = element;
207  }
208  else {
209 
210  }
211 
212  }
213 
214 
215  // create an instance of the class N_Qubit_Decomposition
216  if (qbit_num > 0 ) {
217  self->vqe = create_qgd_Variational_Quantum_Eigensolver_Base(Hamiltonian_mtx, qbit_num, config, accelerator_num);
218  }
219  else {
220  std::cout << "The number of qubits should be given as a positive integer, " << qbit_num << " was given" << std::endl;
221  return -1;
222  }
223 
224 
225  return 0;
226 }
227 
228 
229 
234 static PyObject *
236 
237  int parameter_num = self->vqe->get_parameter_num();
238 
239  Matrix_real parameters_mtx(1, parameter_num);
240  double* parameters = parameters_mtx.get_data();
241  self->vqe->get_optimized_parameters(parameters);
242 
243 
244  // convert to numpy array
245  parameters_mtx.set_owner(false);
246  PyObject * parameter_arr = matrix_real_to_numpy( parameters_mtx );
247 
248  return parameter_arr;
249 }
250 
251 
252 static PyObject *
254 {
255 
256  // starting the decomposition
257  try {
258  self->vqe->start_optimization();
259  }
260  catch (std::string err) {
261  PyErr_SetString(PyExc_Exception, err.c_str());
262  std::cout << err << std::endl;
263  return NULL;
264  }
265  catch(...) {
266  std::string err( "Invalid pointer to decomposition class");
267  PyErr_SetString(PyExc_Exception, err.c_str());
268  return NULL;
269  }
270 
271 
272 
273  return Py_BuildValue("i", 0);
274 
275 }
276 
277 
281 static PyObject *
283 
284  int qbit_num = 0;
285 
286  try {
287  qbit_num = self->vqe->get_qbit_num();
288  }
289  catch (std::string err) {
290  PyErr_SetString(PyExc_Exception, err.c_str());
291  std::cout << err << std::endl;
292  return NULL;
293  }
294  catch(...) {
295  std::string err( "Invalid pointer to decomposition class");
296  PyErr_SetString(PyExc_Exception, err.c_str());
297  return NULL;
298  }
299 
300 
301  return Py_BuildValue("i", qbit_num );
302 
303 }
304 
305 
306 
310 static PyObject *
312 
313  PyArrayObject * parameters_arr = NULL;
314 
315 
316  // parsing input arguments
317  if (!PyArg_ParseTuple(args, "|O", &parameters_arr ))
318  return Py_BuildValue("i", -1);
319 
320 
321  if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
322  Py_INCREF(parameters_arr);
323  }
324  else {
325  parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
326  }
327 
328 
329  Matrix_real parameters_mtx = numpy2matrix_real( parameters_arr );
330 
331 
332 
333  try {
334  self->vqe->set_optimized_parameters(parameters_mtx.get_data(), parameters_mtx.size());
335  }
336  catch (std::string err ) {
337  PyErr_SetString(PyExc_Exception, err.c_str());
338  return NULL;
339  }
340  catch(...) {
341  std::string err( "Invalid pointer to decomposition class");
342  PyErr_SetString(PyExc_Exception, err.c_str());
343  return NULL;
344  }
345 
346  Py_DECREF(parameters_arr);
347 
348  return Py_BuildValue("i", 0);
349 }
350 
351 
352 
356 static PyObject *
358 
359  PyArrayObject * initial_state_arg = NULL;
360 
361  // parsing input arguments
362  if (!PyArg_ParseTuple(args, "|O", &initial_state_arg )) {
363  PyErr_SetString(PyExc_Exception, "error occured during input parsing");
364  return NULL;
365  }
366 
367  if ( PyArray_IS_C_CONTIGUOUS(initial_state_arg) ) {
368  Py_INCREF(initial_state_arg);
369  }
370  else {
371  initial_state_arg = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)initial_state_arg, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
372  }
373 
374 
375  Matrix initial_state_mtx = numpy2matrix( initial_state_arg );
376 
377 
378 
379  try {
380  self->vqe->set_initial_state( initial_state_mtx );
381  }
382  catch (std::string err ) {
383  PyErr_SetString(PyExc_Exception, err.c_str());
384  return NULL;
385  }
386  catch(...) {
387  std::string err( "Invalid pointer to decomposition class");
388  PyErr_SetString(PyExc_Exception, err.c_str());
389  return NULL;
390  }
391 
392 
393 
394 
395  Py_DECREF(initial_state_arg);
396 
397  return Py_BuildValue("i", 0);
398 }
399 
400 
404 static PyObject *
406 
407 
408 
409  // initiate variables for input arguments
410  PyObject* filename_py=NULL;
411 
412  // parsing input arguments
413  if (!PyArg_ParseTuple(args, "|O", &filename_py )) return Py_BuildValue("i", -1);
414 
415  // determine the optimizaton method
416  PyObject* filename_string = PyObject_Str(filename_py);
417  PyObject* filename_string_unicode = PyUnicode_AsEncodedString(filename_string, "utf-8", "~E~");
418  const char* filename_C = PyBytes_AS_STRING(filename_string_unicode);
419  std::string filename_str( filename_C );
420 
421 
422  try {
423  self->vqe->set_gate_structure( filename_str );
424  }
425  catch (std::string err ) {
426  PyErr_SetString(PyExc_Exception, err.c_str());
427  return NULL;
428  }
429  catch(...) {
430  std::string err( "Invalid pointer to decomposition class");
431  PyErr_SetString(PyExc_Exception, err.c_str());
432  return NULL;
433  }
434 
435 
436 
437  return Py_BuildValue("i", 0);
438 
439 }
440 
441 static PyObject *
443 
444  // initiate variables for input arguments
445  double tolerance;
446 
447  // parsing input arguments
448  if (!PyArg_ParseTuple(args, "|d", &tolerance )) return Py_BuildValue("i", -1);
449 
450 
451  // set maximal layer nums on the C++ side
452  self->vqe->set_optimization_tolerance( tolerance );
453 
454 
455  return Py_BuildValue("i", 0);
456 }
457 
458 
459 
460 static PyObject *
462 
463  PyArrayObject * parameters_arr = NULL;
464  PyArrayObject * unitary_arg = NULL;
465 
466 
467  // parsing input arguments
468  if (!PyArg_ParseTuple(args, "|OO", &parameters_arr, &unitary_arg ))
469  return Py_BuildValue("i", -1);
470 
471 
472  if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
473  Py_INCREF(parameters_arr);
474  }
475  else {
476  parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
477  }
478 
479  // get the C++ wrapper around the data
480  Matrix_real&& parameters_mtx = numpy2matrix_real( parameters_arr );
481 
482 
483  // convert python object array to numpy C API array
484  if ( unitary_arg == NULL ) {
485  PyErr_SetString(PyExc_Exception, "Input matrix was not given");
486  return NULL;
487  }
488 
489  PyArrayObject* unitary = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)unitary_arg, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
490 
491  // test C-style contiguous memory allocation of the array
492  if ( !PyArray_IS_C_CONTIGUOUS(unitary) ) {
493  PyErr_SetString(PyExc_Exception, "input mtrix is not memory contiguous");
494  return NULL;
495  }
496 
497 
498  // create QGD version of the input matrix
499  Matrix unitary_mtx = numpy2matrix(unitary);
500 
501 
502  self->vqe->apply_to( parameters_mtx, unitary_mtx );
503 
504  if (unitary_mtx.data != PyArray_DATA(unitary)) {
505  memcpy(PyArray_DATA(unitary), unitary_mtx.data, unitary_mtx.size() * sizeof(QGD_Complex16));
506  }
507 
508  Py_DECREF(parameters_arr);
509  Py_DECREF(unitary);
510 
511  return Py_BuildValue("i", 0);
512 }
513 
514 
515 
516 static PyObject *
518 {
519 
520  // The tuple of expected keywords
521  static char *kwlist[] = {(char*)"optimizer", NULL};
522 
523  PyObject* optimizer_arg = NULL;
524 
525 
526  // parsing input arguments
527  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &optimizer_arg)) {
528 
529  std::string err( "Unsuccessful argument parsing not ");
530  PyErr_SetString(PyExc_Exception, err.c_str());
531  return NULL;
532 
533  }
534 
535  if ( optimizer_arg == NULL ) {
536  std::string err( "optimizer argument not set");
537  PyErr_SetString(PyExc_Exception, err.c_str());
538  return NULL;
539  }
540 
541 
542  PyObject* optimizer_string = PyObject_Str(optimizer_arg);
543  PyObject* optimizer_string_unicode = PyUnicode_AsEncodedString(optimizer_string, "utf-8", "~E~");
544  const char* optimizer_C = PyBytes_AS_STRING(optimizer_string_unicode);
545 
546  optimization_aglorithms qgd_optimizer;
547  if ( strcmp("agents", optimizer_C) == 0 || strcmp("AGENTS", optimizer_C) == 0) {
548  qgd_optimizer = AGENTS;
549  }
550  else if ( strcmp("agents_combined", optimizer_C)==0 || strcmp("AGENTS_COMBINED", optimizer_C)==0) {
551  qgd_optimizer = AGENTS_COMBINED;
552  }
553  else if ( strcmp("cosined", optimizer_C)==0 || strcmp("COSINE", optimizer_C)==0) {
554  qgd_optimizer = COSINE;
555  }
556  else if ( strcmp("grad_descend_phase_shift_rule", optimizer_C)==0 || strcmp("GRAD_DESCEND_PARAMETER_SHIFT_RULE", optimizer_C)==0) {
557  qgd_optimizer = GRAD_DESCEND_PARAMETER_SHIFT_RULE;
558  }
559  else if ( strcmp("bfgs", optimizer_C)==0 || strcmp("BFGS", optimizer_C)==0) {
560  qgd_optimizer = BFGS;
561  }
562  else if ( strcmp("adam", optimizer_C)==0 || strcmp("ADAM", optimizer_C)==0) {
563  qgd_optimizer = ADAM;
564  }
565  else if ( strcmp("grad_descend", optimizer_C)==0 || strcmp("GRAD_DESCEND", optimizer_C)==0) {
566  qgd_optimizer = GRAD_DESCEND;
567  }
568  else if ( strcmp("bayes_opt", optimizer_C)==0 || strcmp("BAYES_OPT", optimizer_C)==0) {
569  qgd_optimizer = BAYES_OPT;
570  }
571  else if ( strcmp("bayes_agents", optimizer_C)==0 || strcmp("BAYES_AGENTS", optimizer_C)==0) {
572  qgd_optimizer = BAYES_AGENTS;
573  }
574  else {
575  std::cout << "Wrong optimizer. Using default: AGENTS" << std::endl;
576  qgd_optimizer = AGENTS;
577  }
578 
579 
580  try {
581  self->vqe->set_optimizer(qgd_optimizer);
582  }
583  catch (std::string err) {
584  PyErr_SetString(PyExc_Exception, err.c_str());
585  std::cout << err << std::endl;
586  return NULL;
587  }
588  catch(...) {
589  std::string err( "Invalid pointer to decomposition class");
590  PyErr_SetString(PyExc_Exception, err.c_str());
591  return NULL;
592  }
593 
594 
595  return Py_BuildValue("i", 0);
596 
597 }
598 
599 static PyObject *
601 {
602 
603  // The tuple of expected keywords
604  static char *kwlist[] = {(char*)"optimizer", NULL};
605 
606  PyObject* ansatz_arg = NULL;
607 
608 
609  // parsing input arguments
610  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &ansatz_arg)) {
611 
612  std::string err( "Unsuccessful argument parsing not ");
613  PyErr_SetString(PyExc_Exception, err.c_str());
614  return NULL;
615 
616  }
617 
618 
619  if ( ansatz_arg == NULL ) {
620  std::string err( "optimizer argument not set");
621  PyErr_SetString(PyExc_Exception, err.c_str());
622  return NULL;
623  }
624 
625 
626 
627  PyObject* ansatz_string = PyObject_Str(ansatz_arg);
628  PyObject* ansatz_string_unicode = PyUnicode_AsEncodedString(ansatz_string, "utf-8", "~E~");
629  const char* ansatz_C = PyBytes_AS_STRING(ansatz_string_unicode);
630 
631 
632  ansatz_type qgd_ansatz;
633 
634  if ( strcmp("hea", ansatz_C) == 0 || strcmp("HEA", ansatz_C) == 0) {
635  qgd_ansatz = HEA;
636  }
637  else if ( strcmp("hea_zyz", ansatz_C) == 0 || strcmp("HEA_ZYZ", ansatz_C) == 0) {
638  qgd_ansatz = HEA_ZYZ;
639  }
640  else {
641  std::cout << "Wrong ansatz. Using default: HEA" << std::endl;
642  qgd_ansatz = HEA;
643  }
644 
645 
646  try {
647  self->vqe->set_ansatz(qgd_ansatz);
648  }
649  catch (std::string err) {
650  PyErr_SetString(PyExc_Exception, err.c_str());
651  std::cout << err << std::endl;
652  return NULL;
653  }
654  catch(...) {
655  std::string err( "Invalid pointer to decomposition class");
656  PyErr_SetString(PyExc_Exception, err.c_str());
657  return NULL;
658  }
659 
660 
661  return Py_BuildValue("i", 0);
662 
663 }
664 
665 
669 static PyObject *
671 {
672 
673 
674  PyArrayObject * parameters_arr = NULL;
675  PyArrayObject * input_state_arg = NULL;
676  PyObject * qubit_list_arg = NULL;
677 
678 
679  // parsing input arguments
680  if (!PyArg_ParseTuple(args, "|OOO", &parameters_arr, &input_state_arg, &qubit_list_arg ))
681  return Py_BuildValue("i", -1);
682 
683 
684  if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
685  Py_INCREF(parameters_arr);
686  }
687  else {
688  parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
689  }
690 
691  // get the C++ wrapper around the data
692  Matrix_real&& parameters_mtx = numpy2matrix_real( parameters_arr );
693 
694  // convert python object array to numpy C API array
695  if ( input_state_arg == NULL ) {
696  PyErr_SetString(PyExc_Exception, "Input matrix was not given");
697  return NULL;
698  }
699 
700  PyArrayObject* input_state = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)input_state_arg, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
701 
702  // test C-style contiguous memory allocation of the array
703  if ( !PyArray_IS_C_CONTIGUOUS(input_state) ) {
704  PyErr_SetString(PyExc_Exception, "input mtrix is not memory contiguous");
705  return NULL;
706  }
707 
708 
709  // create QGD version of the input matrix
710  Matrix input_state_mtx = numpy2matrix(input_state);
711 
712 
713  // check input argument qbit_list
714  if ( qubit_list_arg == NULL || (!PyList_Check( qubit_list_arg )) ) {
715  PyErr_SetString(PyExc_Exception, "qubit_list should be a list");
716  return NULL;
717  }
718 
719  Py_ssize_t reduced_qbit_num = PyList_Size( qubit_list_arg );
720 
721  matrix_base<int> qbit_list_mtx( (int)reduced_qbit_num, 1);
722  for ( int idx=0; idx<reduced_qbit_num; idx++ ) {
723 
724  PyObject* item = PyList_GET_ITEM( qubit_list_arg, idx );
725  qbit_list_mtx[idx] = (int) PyLong_AsLong( item );
726 
727  }
728 
729 
730  double entropy = -1;
731 
732 
733  try {
734  entropy = self->vqe->get_second_Renyi_entropy( parameters_mtx, input_state_mtx, qbit_list_mtx );
735  }
736  catch (std::string err) {
737  PyErr_SetString(PyExc_Exception, err.c_str());
738  std::cout << err << std::endl;
739  return NULL;
740  }
741  catch(...) {
742  std::string err( "Invalid pointer to decomposition class");
743  PyErr_SetString(PyExc_Exception, err.c_str());
744  return NULL;
745  }
746 
747 
748  Py_DECREF(parameters_arr);
749  Py_DECREF(input_state);
750 
751 
752 
753  PyObject* p = Py_BuildValue("d", entropy);
754 
755  return p;
756 }
757 
758 
759 static PyObject *
761 
762  // initiate variables for input arguments
763  int layers;
764  int inner_blocks;
765 
766  // parsing input arguments
767  if (!PyArg_ParseTuple(args, "|ii", &layers, &inner_blocks )) return Py_BuildValue("i", -1);
768 
769 
770  try {
771  self->vqe->generate_circuit( layers, inner_blocks );
772  }
773  catch (std::string err) {
774  PyErr_SetString(PyExc_Exception, err.c_str());
775  std::cout << err << std::endl;
776  return NULL;
777  }
778  catch(...) {
779  std::string err( "Invalid pointer to decomposition class");
780  PyErr_SetString(PyExc_Exception, err.c_str());
781  return NULL;
782  }
783 
784  return Py_BuildValue("i", 0);
785 
786 
787 }
788 
789 static PyObject *
791 {
792 
793 
794  PyArrayObject* parameters_arg = NULL;
795 
796 
797  // parsing input arguments
798  if (!PyArg_ParseTuple(args, "|O", &parameters_arg )) {
799 
800  std::string err( "Unsuccessful argument parsing not ");
801  PyErr_SetString(PyExc_Exception, err.c_str());
802  return NULL;
803 
804  }
805 
806  // establish memory contiguous arrays for C calculations
807  if ( PyArray_IS_C_CONTIGUOUS(parameters_arg) && PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ){
808  Py_INCREF(parameters_arg);
809  }
810  else if (PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ) {
811  parameters_arg = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arg, NPY_FLOAT64, NPY_ARRAY_IN_ARRAY);
812  }
813  else {
814  std::string err( "Parameters should be should be real (given in float64 format)");
815  PyErr_SetString(PyExc_Exception, err.c_str());
816  return NULL;
817  }
818 
819 
820  Matrix_real parameters_mtx = numpy2matrix_real( parameters_arg );
821  double f0;
822 
823  try {
824  f0 = self->vqe->optimization_problem(parameters_mtx );
825  }
826  catch (std::string err ) {
827  PyErr_SetString(PyExc_Exception, err.c_str());
828  return NULL;
829  }
830  catch (...) {
831  std::string err( "Invalid pointer to decomposition class");
832  PyErr_SetString(PyExc_Exception, err.c_str());
833  return NULL;
834  }
835 
836  Py_DECREF(parameters_arg);
837 
838 
839  return Py_BuildValue("d", f0);
840 }
841 
842 
843 
844 
845 
850 static PyObject *
852 {
853 
854 
855  PyObject* parameter_list = NULL;
856 
857 
858  // parsing input arguments
859  if (!PyArg_ParseTuple(args, "|O", &parameter_list )) {
860 
861  std::string err( "Unsuccessful argument parsing not ");
862  PyErr_SetString(PyExc_Exception, err.c_str());
863  return NULL;
864 
865  }
866 
867  // check input argument qbit_list
868  if ( parameter_list == NULL || (!PyList_Check( parameter_list )) ) {
869  PyErr_SetString(PyExc_Exception, "Parameters should be given as a list of parameter arrays");
870  return NULL;
871  }
872 
873  int tasks = (int)PyList_Size( parameter_list );
874  Matrix_real result_mtx;
875 
876 
877  try {
878  std::vector<Matrix_real> parameters_vec;
879  parameters_vec.resize(tasks);
880 
881  for( int idx=0; idx<tasks; idx++ ) {
882  PyArrayObject* parameters_py = (PyArrayObject*)PyList_GET_ITEM( parameter_list, idx );
883 
884  // establish memory contiguous arrays for C calculations
885  if ( PyArray_IS_C_CONTIGUOUS(parameters_py) && PyArray_TYPE(parameters_py) == NPY_FLOAT64 ){
886  Py_INCREF(parameters_py);
887  }
888  else if (PyArray_TYPE(parameters_py) == NPY_FLOAT64 ) {
889  parameters_py = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_py, NPY_FLOAT64, NPY_ARRAY_IN_ARRAY);
890  }
891  else {
892  Py_DECREF(parameters_py);
893  std::string err( "Parameters should be should be real (given in float64 format)");
894  PyErr_SetString(PyExc_Exception, err.c_str());
895  return NULL;
896  }
897 
898  Matrix_real parameters_mtx = numpy2matrix_real( parameters_py );
899  parameters_vec[idx] = parameters_mtx;
900 
901  Py_DECREF(parameters_py);
902 
903  }
904 
905 
906  result_mtx = self->vqe->optimization_problem_batched( parameters_vec );
907  }
908  catch (std::string err ) {
909  PyErr_SetString(PyExc_Exception, err.c_str());
910  return NULL;
911  }
912  catch (...) {
913  std::string err( "Invalid pointer to decomposition class");
914  PyErr_SetString(PyExc_Exception, err.c_str());
915  return NULL;
916  }
917 
918  // convert to numpy array
919  result_mtx.set_owner(false);
920  PyObject *result_py = matrix_real_to_numpy( result_mtx );
921 
922 
923  return result_py;
924 }
925 
926 
927 
928 
932 static PyObject *
934 
935  int parameter_num = self->vqe->get_parameter_num();
936 
937  return Py_BuildValue("i", parameter_num);
938 }
939 
940 
941 
942 
943 
948 static PyObject *
950 
951 
952  PyObject* qgd_Circuit = PyImport_ImportModule("squander.gates.qgd_Circuit");
953 
954  if ( qgd_Circuit == NULL ) {
955  PyErr_SetString(PyExc_Exception, "Module import error: squander.gates.qgd_Circuit" );
956  return NULL;
957  }
958 
959  // retrieve the C++ variant of the flat circuit (flat circuit does not conatain any sub-circuits)
960  Gates_block* circuit = self->vqe->get_flat_circuit();
961 
962 
963 
964  // construct python interfarce for the circuit
965  PyObject* qgd_circuit_Dict = PyModule_GetDict( qgd_Circuit );
966 
967  // 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
968  PyObject* py_circuit_class = PyDict_GetItemString( qgd_circuit_Dict, "qgd_Circuit");
969 
970  // create gate parameters
971  PyObject* qbit_num = Py_BuildValue("i", circuit->get_qbit_num() );
972  PyObject* circuit_input = Py_BuildValue("(O)", qbit_num);
973 
974  PyObject* py_circuit = PyObject_CallObject(py_circuit_class, circuit_input);
975  qgd_Circuit_Wrapper* py_circuit_C = reinterpret_cast<qgd_Circuit_Wrapper*>( py_circuit );
976 
977 
978  // replace the empty circuit with the extracted one
979 
980  delete( py_circuit_C->gate );
981  py_circuit_C->gate = circuit;
982 
983 
984  return py_circuit;
985 
986 }
987 
992 static PyObject *
994 {
995 
996 
997  PyArrayObject* parameters_arg = NULL;
998 
999 
1000  // parsing input arguments
1001  if (!PyArg_ParseTuple(args, "|O", &parameters_arg )) {
1002 
1003  std::string err( "Unsuccessful argument parsing not ");
1004  PyErr_SetString(PyExc_Exception, err.c_str());
1005  return NULL;
1006 
1007  }
1008 
1009  // establish memory contiguous arrays for C calculations
1010  if ( PyArray_IS_C_CONTIGUOUS(parameters_arg) && PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ){
1011  Py_INCREF(parameters_arg);
1012  }
1013  else if (PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ) {
1014  parameters_arg = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arg, NPY_FLOAT64, NPY_ARRAY_IN_ARRAY);
1015  }
1016  else {
1017  std::string err( "Parameters should be should be real (given in float64 format)");
1018  PyErr_SetString(PyExc_Exception, err.c_str());
1019  return NULL;
1020  }
1021 
1022 
1023  Matrix_real parameters_mtx = numpy2matrix_real( parameters_arg );
1024  Matrix_real grad_mtx(parameters_mtx.size(), 1);
1025 
1026  try {
1027  self->vqe->optimization_problem_grad(parameters_mtx, self->vqe, grad_mtx );
1028  }
1029  catch (std::string err ) {
1030  PyErr_SetString(PyExc_Exception, err.c_str());
1031  return NULL;
1032  }
1033  catch (...) {
1034  std::string err( "Invalid pointer to decomposition class");
1035  PyErr_SetString(PyExc_Exception, err.c_str());
1036  return NULL;
1037  }
1038 
1039  // convert to numpy array
1040  grad_mtx.set_owner(false);
1041  PyObject *grad_py = matrix_real_to_numpy( grad_mtx );
1042 
1043  Py_DECREF(parameters_arg);
1044 
1045 
1046  return grad_py;
1047 }
1048 
1049 
1053 static PyObject *
1055  // initiate variables for input arguments
1056  PyObject* project_name_new=NULL;
1057 
1058  // parsing input arguments
1059  if (!PyArg_ParseTuple(args, "|O", &project_name_new)) return Py_BuildValue("i", -1);
1060 
1061 
1062  PyObject* project_name_new_string = PyObject_Str(project_name_new);
1063  PyObject* project_name_new_unicode = PyUnicode_AsEncodedString(project_name_new_string, "utf-8", "~E~");
1064  const char* project_name_new_C = PyBytes_AS_STRING(project_name_new_unicode);
1065  std::string project_name_new_str = ( project_name_new_C );
1066 
1067  // convert to python string
1068  self->vqe->set_project_name(project_name_new_str);
1069 
1070  return Py_BuildValue("i", 0);
1071 }
1072 
1073 
1079 static PyObject *
1081 
1082  // initiate variables for input arguments
1083  PyObject* gate_structure_py;
1084 
1085  // parsing input arguments
1086  if (!PyArg_ParseTuple(args, "|O", &gate_structure_py )) return Py_BuildValue("i", -1);
1087 
1088 
1089  // convert gate structure from PyObject to qgd_Circuit_Wrapper
1090  qgd_Circuit_Wrapper* qgd_op_block = (qgd_Circuit_Wrapper*) gate_structure_py;
1091 
1092  try {
1093  self->vqe->set_custom_gate_structure( qgd_op_block->gate );
1094  }
1095  catch (std::string err ) {
1096  PyErr_SetString(PyExc_Exception, err.c_str());
1097  return NULL;
1098  }
1099  catch(...) {
1100  std::string err( "Invalid pointer to decomposition class");
1101  PyErr_SetString(PyExc_Exception, err.c_str());
1102  return NULL;
1103  }
1104 
1105 
1106  return Py_BuildValue("i", 0);
1107 
1108 
1109 }
1110 
1115  {NULL} /* Sentinel */
1116 };
1117 
1122  {"Start_Optimization", (PyCFunction) qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Start_Optimization, METH_NOARGS,
1123  "Method to start the decomposition."
1124  },
1125  {"get_Optimized_Parameters", (PyCFunction) qgd_Variational_Quantum_Eigensolver_Base_Wrapper_get_Optimized_Parameters, METH_NOARGS,
1126  "Method to get the array of optimized parameters."
1127  },
1128  {"set_Optimized_Parameters", (PyCFunction) qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Optimized_Parameters, METH_VARARGS,
1129  "Method to set the array of optimized parameters."
1130  },
1131  {"set_Optimization_Tolerance", (PyCFunction) qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Optimization_Tolerance, METH_VARARGS,
1132  "Method to set optimization tolerance"
1133  },
1134  {"get_Circuit", (PyCFunction) qgd_Variational_Quantum_Eigensolver_Base_Wrapper_get_circuit, METH_NOARGS,
1135  "Method to get the incorporated circuit."
1136  },
1137  {"set_Project_Name", (PyCFunction) qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Project_Name, METH_VARARGS,
1138  "method to set project name."
1139  },
1140  {"set_Gate_Structure_From_Binary", (PyCFunction) qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Gate_Structure_From_Binary, METH_VARARGS,
1141  "Method to set the gate structure from a file created in SQUANDER."
1142  },
1143  {"apply_to", (PyCFunction) qgd_Variational_Quantum_Eigensolver_Base_Wrapper_apply_to, METH_VARARGS,
1144  "Call to apply the gate on the input matrix."
1145  },
1146  {"set_Optimizer", (PyCFunction) qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Optimizer, METH_VARARGS | METH_KEYWORDS,
1147  "Method to set optimizer."
1148  },
1149  {"set_Ansatz", (PyCFunction) qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Ansatz, METH_VARARGS | METH_KEYWORDS,
1150  "Method to set ansatz type."
1151  },
1152  {"get_Parameter_Num", (PyCFunction) qgd_Variational_Quantum_Eigensolver_Base_Wrapper_get_Parameter_Num, METH_NOARGS,
1153  "Call to get the number of free parameters in the gate structure used for the decomposition"
1154  },
1155  {"Generate_Circuit", (PyCFunction) qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Generate_Circuit, METH_VARARGS,
1156  "Method to set the circuit based on the ansatz type."
1157  },
1158  {"Optimization_Problem", (PyCFunction) qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Optimization_Problem, METH_VARARGS,
1159  "Method to get the expected energy of the circuit at parameters."
1160  },
1161  {"Optimization_Problem_Batch", (PyCFunction) qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Optimization_Problem_Batch, METH_VARARGS,
1162  "Wrapper function to evaluate the cost function for a batch of input parameters."
1163  },
1164  {"get_Second_Renyi_Entropy", (PyCFunction) qgd_Variational_Quantum_Eigensolver_Base_Wrapper_get_Second_Renyi_Entropy, METH_VARARGS,
1165  "Wrapper function to evaluate the second Rényi entropy of a quantum circuit at a specific parameter set."
1166  },
1167  {"get_Qbit_Num", (PyCFunction) qgd_Variational_Quantum_Eigensolver_Base_Wrapper_get_Qbit_Num, METH_NOARGS,
1168  "Call to get the number of qubits in the circuit"
1169  },
1170  {"set_Initial_State", (PyCFunction) qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Initial_State, METH_VARARGS,
1171  "Call to set the initial state used in the VQE process."
1172  },
1173  {"set_Gate_Structure", (PyCFunction) qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Gate_Structure, METH_VARARGS,
1174  "Call to set custom gate structure for VQE experiments."
1175  },
1176  {"Optimization_Problem_Grad", (PyCFunction) qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Optimization_Problem_Grad, METH_VARARGS,
1177  "Method to get the expected energy of the circuit at parameters."
1178  },
1179  {NULL} /* Sentinel */
1180 };
1181 
1186  PyVarObject_HEAD_INIT(NULL, 0)
1187  "qgd_N_Qubit_Decomposition_Wrapper.qgd_N_Qubit_Decomposition_Wrapper", /*tp_name*/
1188  sizeof(qgd_Variational_Quantum_Eigensolver_Base_Wrapper), /*tp_basicsize*/
1189  0, /*tp_itemsize*/
1191  #if PY_VERSION_HEX < 0x030800b4
1192  0, /*tp_print*/
1193  #endif
1194  #if PY_VERSION_HEX >= 0x030800b4
1195  0, /*tp_vectorcall_offset*/
1196  #endif
1197  0, /*tp_getattr*/
1198  0, /*tp_setattr*/
1199  #if PY_MAJOR_VERSION < 3
1200  0, /*tp_compare*/
1201  #endif
1202  #if PY_MAJOR_VERSION >= 3
1203  0, /*tp_as_async*/
1204  #endif
1205  0, /*tp_repr*/
1206  0, /*tp_as_number*/
1207  0, /*tp_as_sequence*/
1208  0, /*tp_as_mapping*/
1209  0, /*tp_hash*/
1210  0, /*tp_call*/
1211  0, /*tp_str*/
1212  0, /*tp_getattro*/
1213  0, /*tp_setattro*/
1214  0, /*tp_as_buffer*/
1215  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
1216  "Object to represent a Gates_block class of the QGD package.", /*tp_doc*/
1217  0, /*tp_traverse*/
1218  0, /*tp_clear*/
1219  0, /*tp_richcompare*/
1220  0, /*tp_weaklistoffset*/
1221  0, /*tp_iter*/
1222  0, /*tp_iternext*/
1225  0, /*tp_getset*/
1226  0, /*tp_base*/
1227  0, /*tp_dict*/
1228  0, /*tp_descr_get*/
1229  0, /*tp_descr_set*/
1230  0, /*tp_dictoffset*/
1232  0, /*tp_alloc*/
1234  0, /*tp_free*/
1235  0, /*tp_is_gc*/
1236  0, /*tp_bases*/
1237  0, /*tp_mro*/
1238  0, /*tp_cache*/
1239  0, /*tp_subclasses*/
1240  0, /*tp_weaklist*/
1241  0, /*tp_del*/
1242  0, /*tp_version_tag*/
1243  #if PY_VERSION_HEX >= 0x030400a1
1244  0, /*tp_finalize*/
1245  #endif
1246  #if PY_VERSION_HEX >= 0x030800b1
1247  0, /*tp_vectorcall*/
1248  #endif
1249  #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000
1250  0, /*tp_print*/
1251  #endif
1252 };
1253 
1258  PyModuleDef_HEAD_INIT,
1259  "qgd_N_Qubit_Decomposition_Wrapper",
1260  "Python binding for QGD N_Qubit_Decomposition class",
1261  -1,
1262 };
1263 
1264 
1268 PyMODINIT_FUNC
1270 {
1271  // initialize Numpy API
1272  import_array();
1273 
1274  PyObject *m;
1275  if (PyType_Ready(&qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Type) < 0)
1276  return NULL;
1277 
1278  m = PyModule_Create(&qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Module);
1279  if (m == NULL)
1280  return NULL;
1281 
1282  Py_INCREF(&qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Type);
1283  if (PyModule_AddObject(m, "qgd_Variational_Quantum_Eigensolver_Base_Wrapper", (PyObject *) &qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Type) < 0) {
1284  Py_DECREF(&qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Type);
1285  Py_DECREF(m);
1286  return NULL;
1287  }
1288 
1289  return m;
1290 }
1291 
1292 
1293 } //extern C
1294 
1295 
void release_Variational_Quantum_Eigensolver_Base(Variational_Quantum_Eigensolver_Base *instance)
Call to deallocate an instance of N_Qubit_Decomposition class.
Gates_block * get_flat_circuit()
Method to generate a flat circuit.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Optimization_Problem(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Ansatz(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args, PyObject *kwds)
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Optimization_Tolerance(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
parameter_num
[set adaptive gate structure]
PyMODINIT_FUNC PyInit_qgd_Variational_Quantum_Eigensolver_Base_Wrapper(void)
Method called when the Python module is initialized.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Optimized_Parameters(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Set parameters for the solver.
Type definition of the qgd_N_Qubit_Decomposition_Wrapper Python class of the qgd_N_Qubit_Decompositio...
Class to solve VQE problems.
Variational_Quantum_Eigensolver_Base * create_qgd_Variational_Quantum_Eigensolver_Base(Matrix_sparse Hamiltonian, int qbit_num, std::map< std::string, Config_Element > &config, int accelerator_num)
Creates an instance of class N_Qubit_Decomposition and return with a pointer pointing to the class in...
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_apply_to(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Matrix_real numpy2matrix_real(PyArrayObject *arr)
Call to create a PIC matrix_real representation of a numpy array.
scalar * data
pointer to the stored data
Definition: matrix_base.hpp:48
static void qgd_Variational_Quantum_Eigensolver_Base_Wrapper_dealloc(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self)
Method called when a python instance of the class qgd_N_Qubit_Decomposition_Wrapper is destroyed...
PyObject * matrix_real_to_numpy(Matrix_real &mtx)
Call to make a numpy array from an instance of matrix class.
Class to store data of complex arrays and its properties.
Definition: matrix_sparse.h:38
A class describing a universal configuration element.
scalar * get_data() const
Call to get the pointer to the stored data.
PyObject_HEAD PyObject * Hamiltonian
pointer to the unitary to be decomposed to keep it alive
optimization_aglorithms
implemented optimization strategies
static PyModuleDef qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Module
Structure containing metadata about the module.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_get_Optimized_Parameters(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self)
Extract the optimized parameters.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_get_circuit(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self)
Wrapper function to retrieve the circuit (Squander format) incorporated in the instance.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_get_Qbit_Num(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self)
Call to retrieve the number of qubits in the circuit.
ansatz_type
Type definition of the fifferent types of ansatz.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Start_Optimization(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self)
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_get_Second_Renyi_Entropy(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Wrapper function to evaluate the second Rényi entropy of a quantum circuit at a specific parameter s...
void set_owner(bool owner_in)
Call to set the current class instance to be (or not to be) the owner of the stored data array...
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Gate_Structure_From_Binary(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Wrapper function to set custom layers to the gate structure that are intended to be used in the decom...
Structure type representing complex numbers in the SQUANDER package.
Definition: QGDTypes.h:38
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Gate_Structure(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Wrapper function to set custom gate structure for the decomposition.
A base class to solve VQE problems This class can be used to approximate the ground state of the inpu...
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Optimization_Problem_Grad(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Wrapper function to evaluate the cost function an dthe gradient components.
int Power_of_2(int n)
Calculates the n-th power of 2.
Definition: common.cpp:117
dictionary config
gate systhesis #####################################
Class to store data of complex arrays and its properties.
Definition: matrix.h:38
int size() const
Call to get the number of the allocated elements.
A class responsible for grouping two-qubit (CNOT,CZ,CH) and one-qubit gates into layers.
Definition: Gates_block.h:41
Variational_Quantum_Eigensolver_Base * vqe
An object to decompose the unitary.
void set_property(std::string name_, double val_)
Call to set a double value.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Method called when a python instance of the class qgd_N_Qubit_Decomposition_Wrapper is allocated...
static PyTypeObject qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Type
A structure describing the type of the class qgd_N_Qubit_Decomposition_Wrapper.
Matrix numpy2matrix(PyArrayObject *arr)
Call to create a PIC matrix representation of a numpy array.
PyObject_HEAD Gates_block * circuit
Pointer to the C++ class of the base Gate_block module.
static PyMemberDef qgd_Variational_Quantum_Eigensolver_Base_Wrapper_members[]
Structure containing metadata about the members of class qgd_N_Qubit_Decomposition_Wrapper.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Optimizer(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args, PyObject *kwds)
int get_qbit_num()
Call to get the number of qubits composing the unitary.
Definition: Gate.cpp:504
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Initial_State(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Set the initial state used in the VQE process.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Generate_Circuit(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Type definition of the qgd_Circuit_Wrapper Python class of the qgd_Circuit_Wrapper module...
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Optimization_Problem_Batch(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Wrapper function to evaluate the cost function for many input paramaters at once. ...
static PyMethodDef qgd_Variational_Quantum_Eigensolver_Base_Wrapper_methods[]
Structure containing metadata about the methods of class qgd_N_Qubit_Decomposition_Wrapper.
Class to store data of complex arrays and its properties.
Definition: matrix_real.h:39
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Project_Name(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Call to set a project name.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_get_Parameter_Num(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self)
Get the number of free parameters in the gate structure used for the decomposition.
static int qgd_Variational_Quantum_Eigensolver_Base_Wrapper_init(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args, PyObject *kwds)
Method called when a python instance of the class qgd_N_Qubit_Decomposition_Wrapper is initialized...