27 #define PY_SSIZE_T_CLEAN 31 #include <numpy/arrayobject.h> 32 #include "structmember.h" 87 if (instance != NULL ) {
107 if ( self->decomp != NULL ) {
113 if ( self->Umtx != NULL ) {
115 Py_DECREF(self->Umtx);
119 Py_TYPE(
self)->tp_free((PyObject *)
self);
137 return (PyObject *)
self;
151 static char *kwlist[] = {(
char*)
"Umtx", (
char*)
"qbit_num", (
char*)
"optimize_layer_num", (
char*)
"initial_guess", NULL};
154 PyArrayObject *Umtx_arg = NULL;
156 bool optimize_layer_num =
false;
157 PyObject *initial_guess = NULL;
160 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|OibO", kwlist,
161 &Umtx_arg, &qbit_num, &optimize_layer_num, &initial_guess))
165 if ( Umtx_arg == NULL )
return -1;
166 self->Umtx = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)Umtx_arg, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
169 if ( !PyArray_IS_C_CONTIGUOUS((PyArrayObject*)
self->Umtx) ) {
170 std::cout <<
"Umtx is not memory contiguous" << std::endl;
179 PyObject* initial_guess_string = PyObject_Str(initial_guess);
180 PyObject* initial_guess_string_unicode = PyUnicode_AsEncodedString(initial_guess_string,
"utf-8",
"~E~");
181 const char* initial_guess_C = PyBytes_AS_STRING(initial_guess_string_unicode);
184 if ( strcmp(
"zeros", initial_guess_C) == 0 || strcmp(
"ZEROS", initial_guess_C) == 0) {
185 qgd_initial_guess =
ZEROS;
187 else if ( strcmp(
"random", initial_guess_C)==0 || strcmp(
"RANDOM", initial_guess_C)==0) {
188 qgd_initial_guess =
RANDOM;
190 else if ( strcmp(
"close_to_zero", initial_guess_C)==0 || strcmp(
"CLOSE_TO_ZERO", initial_guess_C)==0) {
194 std::cout <<
"Wrong initial guess format. Using default ZEROS." << std::endl;
195 qgd_initial_guess =
ZEROS;
201 std::map<std::string, Config_Element>
config;
209 std::cout <<
"The number of qubits should be given as a positive integer, " << qbit_num <<
" was given" << std::endl;
215 Py_XDECREF(initial_guess_string);
216 Py_XDECREF(initial_guess_string_unicode);
231 static char *kwlist[] = {NULL};
235 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|", kwlist))
236 return Py_BuildValue(
"i", -1);
240 self->decomp->start_decomposition(
true);
243 return Py_BuildValue(
"i", 0);
260 int ret =
self->decomp->get_gate_num();
263 return Py_BuildValue(
"i", ret);
279 PyObject* qgd_Circuit = PyImport_ImportModule(
"squander.gates.qgd_Circuit");
281 if ( qgd_Circuit == NULL ) {
282 PyErr_SetString(PyExc_Exception,
"Module import error: squander.gates.qgd_Circuit" );
292 PyObject* qgd_circuit_Dict = PyModule_GetDict( qgd_Circuit );
295 PyObject* py_circuit_class = PyDict_GetItemString( qgd_circuit_Dict,
"qgd_Circuit");
299 PyObject* circuit_input = Py_BuildValue(
"(O)", qbit_num);
301 PyObject* py_circuit = PyObject_CallObject(py_circuit_class, circuit_input);
307 delete( py_circuit_C->
gate );
323 self->decomp->list_gates( 0 );
342 self->decomp->get_optimized_parameters(parameters);
348 return parameter_arr;
364 PyObject* max_layer_num;
367 if (!PyArg_ParseTuple(args,
"|O", &max_layer_num ))
return Py_BuildValue(
"i", -1);
370 if (!PyDict_Check(max_layer_num)) {
371 printf(
"Input must be dictionary!\n");
372 return Py_BuildValue(
"i", -1);
376 PyObject* key = NULL;
377 PyObject* value = NULL;
381 while (PyDict_Next(max_layer_num, &pos, &key, &value)) {
384 assert(PyLong_Check(value) == 1);
385 int value_int = (
int) PyLong_AsLong(value);
388 assert(PyLong_Check(key) == 1);
389 int key_int = (
int) PyLong_AsLong(key);
392 self->decomp->set_max_layer_num( key_int, value_int );
395 return Py_BuildValue(
"i", 0);
409 PyObject* identical_blocks;
412 if (!PyArg_ParseTuple(args,
"|O", &identical_blocks ))
return Py_BuildValue(
"i", -1);
415 if (!PyDict_Check(identical_blocks)) {
416 printf(
"Input must be dictionary!\n");
417 return Py_BuildValue(
"i", -1);
421 PyObject* key = NULL;
422 PyObject* value = NULL;
426 while (PyDict_Next(identical_blocks, &pos, &key, &value)) {
429 assert(PyLong_Check(value) == 1);
430 int value_int = (
int) PyLong_AsLong(value);
433 assert(PyLong_Check(key) == 1);
434 int key_int = (
int) PyLong_AsLong(key);
437 self->decomp->set_identical_blocks( key_int, value_int );
440 return Py_BuildValue(
"i", 0);
457 PyObject* iteration_loops;
460 if (!PyArg_ParseTuple(args,
"|O", &iteration_loops ))
return Py_BuildValue(
"i", -1);
463 if (!PyDict_Check(iteration_loops)) {
464 printf(
"Input must be dictionary!\n");
465 return Py_BuildValue(
"i", -1);
469 PyObject* key = NULL;
470 PyObject* value = NULL;
474 while (PyDict_Next(iteration_loops, &pos, &key, &value)) {
477 assert(PyLong_Check(value) == 1);
478 int value_int = (
int) PyLong_AsLong(value);
481 assert(PyLong_Check(key) == 1);
482 int key_int = (
int) PyLong_AsLong(key);
485 self->decomp->set_iteration_loops( key_int, value_int );
488 return Py_BuildValue(
"i", 0);
506 if (!PyArg_ParseTuple(args,
"|i", &verbose ))
return Py_BuildValue(
"i", -1);
510 self->decomp->set_verbose( verbose );
512 return Py_BuildValue(
"i", 0);
525 PyObject *debugfile = NULL;
528 if (!PyArg_ParseTuple(args,
"|O", &debugfile ))
return Py_BuildValue(
"s", -1);
531 PyObject* debugfile_string = PyObject_Str(debugfile);
532 PyObject* debugfile_string_unicode = PyUnicode_AsEncodedString(debugfile_string,
"utf-8",
"~E~");
533 const char* debugfile_C = PyBytes_AS_STRING(debugfile_string_unicode);
536 Py_XDECREF(debugfile_string);
537 Py_XDECREF(debugfile_string_unicode);
540 Py_ssize_t string_length = PyBytes_Size(debugfile_string_unicode);
541 std::string debugfile_Cpp(debugfile_C, string_length);
544 self->decomp->set_debugfile( debugfile_Cpp );
547 return Py_BuildValue(
"s", NULL);
563 if (!PyArg_ParseTuple(args,
"|d", &tolerance ))
return Py_BuildValue(
"i", -1);
567 self->decomp->set_optimization_tolerance( tolerance );
569 return Py_BuildValue(
"i", 0);
586 if (!PyArg_ParseTuple(args,
"|d", &threshold ))
return Py_BuildValue(
"i", -1);
590 self->decomp->set_convergence_threshold( threshold );
592 return Py_BuildValue(
"i", 0);
607 double optimization_block;
610 if (!PyArg_ParseTuple(args,
"|d", &optimization_block ))
return Py_BuildValue(
"i", -1);
614 self->decomp->set_optimization_blocks( optimization_block );
616 return Py_BuildValue(
"i", 0);
633 PyObject* gate_structure_dict;
636 if (!PyArg_ParseTuple(args,
"|O", &gate_structure_dict ))
return Py_BuildValue(
"i", -1);
639 if (!PyDict_Check(gate_structure_dict)) {
640 printf(
"Input must be dictionary!\n");
641 return Py_BuildValue(
"i", -1);
645 PyObject* key = NULL;
646 PyObject* value = NULL;
652 while (PyDict_Next(gate_structure_dict, &pos, &key, &value)) {
655 assert(PyLong_Check(key) == 1);
656 int key_int = (
int) PyLong_AsLong(key);
661 gate_structure.insert( std::pair<int, Gates_block*>( key_int, qgd_op_block->
gate ));
665 self->decomp->set_custom_gate_structure( gate_structure );
667 return Py_BuildValue(
"i", 0);
683 if (!PyArg_ParseTuple(args,
"|O", &qbit_list ))
return Py_BuildValue(
"i", -1);
685 bool is_tuple = PyTuple_Check(qbit_list);
686 bool is_list = PyList_Check(qbit_list);
689 if (!is_list && !is_tuple) {
690 printf(
"Input must be tuple or list!\n");
691 return Py_BuildValue(
"i", -1);
695 Py_ssize_t element_num;
698 element_num = PyTuple_GET_SIZE(qbit_list);
701 element_num = PyList_GET_SIZE(qbit_list);
706 std::vector<int> qbit_list_C( (
int) element_num);
707 for ( Py_ssize_t idx=0; idx<element_num; idx++ ) {
709 qbit_list_C[(
int) idx] = (
int) PyLong_AsLong( PyTuple_GetItem(qbit_list, idx ) );
712 qbit_list_C[(
int) idx] = (
int) PyLong_AsLong( PyList_GetItem(qbit_list, idx ) );
719 self->decomp->reorder_qubits( qbit_list_C );
723 return Py_BuildValue(
"i", 0);
740 "Method to start the decomposition." 743 "Method to get the number of decomposing gates." 746 "Method to get the array of optimized parameters." 749 "Method to get the incorporated circuit." 752 "Call to print the decomposing nitaries on standard output" 755 "Call to set the maximal number of layers used in the subdecomposition of the qbit-th qubit." 758 "Call to set the number of identical successive blocks during the subdecomposition of the qbit-th qubit." 761 "Call to set the number of iteration loops during the subdecomposition of the qbit-th qubit." 764 "Call to set the verbosity of the qgd_N_Qubit_Decomposition class." 767 "Set the debugfile name of the N_Qubit_Decomposition class." 770 "Call to set custom gate structure in the decomposition." 773 "Wrapper method to reorder the qubits in the decomposition class." 776 "Wrapper method to set the optimization tolerance of the optimization process during the decomposition." 779 "Wrapper method to set the threshold of convergence in the optimization processes." 782 "Wrapper method to to set the number of gate blocks to be optimized in one shot." 791 PyVarObject_HEAD_INIT(NULL, 0)
792 "qgd_N_Qubit_Decomposition_Wrapper.qgd_N_Qubit_Decomposition_Wrapper",
796 #if PY_VERSION_HEX < 0x030800b4 799 #if PY_VERSION_HEX >= 0x030800b4 804 #if PY_MAJOR_VERSION < 3 807 #if PY_MAJOR_VERSION >= 3 820 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
821 "Object to represent a Circuit class of the QGD package.",
848 #
if PY_VERSION_HEX >= 0x030400a1
851 #
if PY_VERSION_HEX >= 0x030800b1
854 #
if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000
863 PyModuleDef_HEAD_INIT,
864 "qgd_N_Qubit_Decomposition_Wrapper",
865 "Python binding for QGD N_Qubit_Decomposition class",
880 if (PyType_Ready(&qgd_N_Qubit_Decomposition_Wrapper_Type) < 0)
883 m = PyModule_Create(&qgd_N_Qubit_Decomposition_Wrapper_Module);
887 Py_INCREF(&qgd_N_Qubit_Decomposition_Wrapper_Type);
888 if (PyModule_AddObject(m,
"qgd_N_Qubit_Decomposition_Wrapper", (PyObject *) &qgd_N_Qubit_Decomposition_Wrapper_Type) < 0) {
889 Py_DECREF(&qgd_N_Qubit_Decomposition_Wrapper_Type);
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Optimization_Blocks(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Wrapper method to to set the number of gate blocks to be optimized in one shot.
Gates_block * get_flat_circuit()
Method to generate a flat circuit.
parameter_num
[set adaptive gate structure]
N_Qubit_Decomposition * decomp
An object to decompose the unitary.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Gate_Structure(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Wrapper function to set custom gate structure for the decomposition.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Debugfile(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Set the debugfile name of the N_Qubit_Decomposition class.
static PyMethodDef qgd_N_Qubit_Decomposition_Wrapper_methods[]
Structure containing metadata about the methods of class qgd_N_Qubit_Decomposition_Wrapper.
PyObject * matrix_real_to_numpy(Matrix_real &mtx)
Call to make a numpy array from an instance of matrix class.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_Start_Decomposition(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args, PyObject *kwds)
Wrapper function to call the start_decomposition method of C++ class N_Qubit_Decomposition.
N_Qubit_Decomposition * create_N_Qubit_Decomposition(Matrix &Umtx, int qbit_num, bool optimize_layer_num, std::map< std::string, Config_Element > &config, guess_type initial_guess)
Creates an instance of class N_Qubit_Decomposition and return with a pointer pointing to the class in...
static void qgd_N_Qubit_Decomposition_Wrapper_dealloc(qgd_N_Qubit_Decomposition_Wrapper *self)
Method called when a python instance of the class qgd_N_Qubit_Decomposition_Wrapper is destroyed...
static PyModuleDef qgd_N_Qubit_Decomposition_Wrapper_Module
Structure containing metadata about the module.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Method called when a python instance of the class qgd_N_Qubit_Decomposition_Wrapper is allocated...
scalar * get_data() const
Call to get the pointer to the stored data.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Max_Layer_Num(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Set the maximal number of layers used in the subdecomposition of the qbit-th qubit.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Iteration_Loops(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Set the number of iteration loops during the subdecomposition of the qbit-th qubit.
PyObject_HEAD Gates_block * gate
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_get_gate_num(qgd_N_Qubit_Decomposition_Wrapper *self)
Wrapper function to get the number of decomposing gates.
Umtx
The unitary to be decomposed.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_get_circuit(qgd_N_Qubit_Decomposition_Wrapper *self)
Wrapper function to retrieve the circuit (Squander format) incorporated in the instance.
void set_owner(bool owner_in)
Call to set the current class instance to be (or not to be) the owner of the stored data array...
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Optimization_Tolerance(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Wrapper method to set the optimization tolerance of the optimization process during the decomposition...
PyObject_HEAD PyArrayObject * Umtx
pointer to the unitary to be decomposed to keep it alive
dictionary config
gate systhesis #####################################
Class to store data of complex arrays and its properties.
A class responsible for grouping two-qubit (CNOT,CZ,CH) and one-qubit gates into layers.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_List_Gates(qgd_N_Qubit_Decomposition_Wrapper *self)
Lists the gates decomposing the initial unitary.
PyMODINIT_FUNC PyInit_qgd_N_Qubit_Decomposition_Wrapper(void)
Method called when the Python module is initialized.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Verbose(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Set the verbosity of the N_Qubit_Decomposition class.
static int qgd_N_Qubit_Decomposition_Wrapper_init(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args, PyObject *kwds)
Method called when a python instance of the class qgd_N_Qubit_Decomposition_Wrapper is initialized...
guess_type
Type definition of the types of the initial guess.
dictionary gate_structure
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Identical_Blocks(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Set the number of identical successive blocks during the subdecomposition of the qbit-th qubit...
static PyMemberDef qgd_N_Qubit_Decomposition_Wrapper_members[]
Structure containing metadata about the members of 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.
void release_N_Qubit_Decomposition(N_Qubit_Decomposition *instance)
Call to deallocate an instance of N_Qubit_Decomposition class.
int get_qbit_num()
Call to get the number of qubits composing the unitary.
Type definition of the qgd_Circuit_Wrapper Python class of the qgd_Circuit_Wrapper module...
static PyTypeObject qgd_N_Qubit_Decomposition_Wrapper_Type
A structure describing the type of the class qgd_N_Qubit_Decomposition_Wrapper.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_set_Convergence_Threshold(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Wrapper method to set the threshold of convergence in the optimization processes. ...
Header file for a class to determine the decomposition of an N-qubit unitary into a sequence of CNOT ...
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_Reorder_Qubits(qgd_N_Qubit_Decomposition_Wrapper *self, PyObject *args)
Wrapper method to reorder the qubits in the decomposition class.
static PyObject * qgd_N_Qubit_Decomposition_Wrapper_get_Optimized_Parameters(qgd_N_Qubit_Decomposition_Wrapper *self)
Extract the optimized parameters.
Type definition of the qgd_N_Qubit_Decomposition_Wrapper Python class of the qgd_N_Qubit_Decompositio...
Class to store data of complex arrays and its properties.
A base class to determine the decomposition of an N-qubit unitary into a sequence of CNOT and U3 gate...