Sequential Quantum Gate Decomposer  v1.9.3
Powerful decomposition of general unitarias into one- and two-qubit gates gates
qgd_nn_Wrapper.cpp
Go to the documentation of this file.
1 /*
2 Created on Fri Jun 26 14:42:56 2020
3 Copyright 2020 Peter Rakyta, Ph.D.
4 
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8 
9  http://www.apache.org/licenses/LICENSE-2.0
10 
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see http://www.gnu.org/licenses/.
19 
20 @author: Peter Rakyta, Ph.D.
21 */
22 /*
23 \file qgd_nn_Wrapper.cpp
24 \brief Python interface for the N_Qubit_Decomposition class
25 */
26 
27 #define PY_SSIZE_T_CLEAN
28 
29 
30 #include <Python.h>
31 #include <numpy/arrayobject.h>
32 #include "structmember.h"
33 #include <stdio.h>
34 #include "NN.h"
35 
36 
37 #include "numpy_interface.h"
38 
39 
40 
44 typedef struct qgd_nn_Wrapper {
45  PyObject_HEAD
47  NN* nn;
48 
50 
51 
52 
53 
58 NN*
60 
61  return new NN();
62 }
63 
64 
65 
66 
71 void
72 release_NN( NN* instance ) {
73 
74  if (instance != NULL ) {
75  delete instance;
76  }
77  return;
78 }
79 
80 
81 extern "C"
82 {
83 
84 
89 static void
91 {
92 
93 
94  if ( self->nn != NULL ) {
95  // deallocate the instance of class N_Qubit_Decomposition
96  release_NN( self->nn );
97  self->nn = NULL;
98  }
99 
100  Py_TYPE(self)->tp_free((PyObject *) self);
101 
102 }
103 
108 static PyObject *
109 qgd_nn_Wrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
110 {
111  qgd_nn_Wrapper *self;
112  self = (qgd_nn_Wrapper *) type->tp_alloc(type, 0);
113  if (self != NULL) {
114 
115  self->nn = NULL;
116 
117  }
118 
119 
120  return (PyObject *) self;
121 }
122 
123 
130 static int
131 qgd_nn_Wrapper_init(qgd_nn_Wrapper *self, PyObject *args, PyObject *kwds)
132 {
133  // The tuple of expected keywords
134  static char *kwlist[] = {NULL};
135 
136 
137  // parsing input arguments
138  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|", kwlist ))
139  return -1;
140 
141 
142  try {
143  self->nn = create_NN();
144  }
145  catch (std::string err) {
146  PyErr_SetString(PyExc_Exception, err.c_str());
147  std::cout << err << std::endl;
148  return 1;
149  }
150 
151 
152 
153  return 0;
154 }
155 
162 static PyObject *
163 qgd_nn_Wrapper_get_nn_chanels(qgd_nn_Wrapper *self, PyObject *args, PyObject *kwds)
164 {
165 
166  // The tuple of expected keywords
167  static char *kwlist[] = {(char*)"qbit_num", (char*)"levels", (char*)"samples_num", NULL};
168 
169  // initiate variables for input arguments
170  int qbit_num = -1;
171  int levels = -1;
172  int samples_num = -1;
173 
174 
175 
176  // parsing input arguments
177  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iii", kwlist, &qbit_num, &levels, &samples_num) ) {
178  std::string err( "Invalid parameters" );
179  PyErr_SetString(PyExc_Exception, err.c_str());
180  std::cout << err << std::endl;
181  return NULL;
182  }
183 
184 
185 
186  // preallocate output variables
187  Matrix_real chanels(0,0);
188  matrix_base<int8_t> nontrivial_adaptive_layers;
189 
190 
191  // calculate the neural network chanels
192  try {
193  if ( qbit_num > 0 && levels >= 0 && samples_num <= 1) {
194  std::cout << "qbit_num: " << qbit_num << ", levels: " << levels << std::endl;
195 
196  // preallocate output variables
197  //Matrix_real parameters(0,0);
198 
199 
200  self->nn->get_nn_chanels(qbit_num, levels, chanels, nontrivial_adaptive_layers);
201 
202  }
203  else if ( qbit_num > 0 && levels >= 0 && samples_num > 1) {
204  std::cout << "qbit_num: " << qbit_num << ", levels: " << levels << ", samples num:" << samples_num << std::endl;
205 
206  // preallocate output variables
207  //Matrix_real parameters(0,0);
208 
209  self->nn->get_nn_chanels(qbit_num, levels, samples_num, chanels, nontrivial_adaptive_layers);
210 
211  }
212  else {
213  std::string err( "Not enough input parameters");
214  PyErr_SetString(PyExc_Exception, err.c_str());
215  return NULL;
216  }
217  }
218  catch (std::string err) {
219  PyErr_SetString(PyExc_Exception, err.c_str());
220  std::cout << err << std::endl;
221  return NULL;
222  }
223  catch(...) {
224  std::string err( "Invalid pointer to decomposition class");
225  PyErr_SetString(PyExc_Exception, err.c_str());
226  return NULL;
227  }
228 
229 
230  PyObject* chanels_py = matrix_real_to_numpy( chanels );
231  chanels.set_owner( false );
232 
233  PyObject* nontrivial_adaptive_layers_py;
234  if ( nontrivial_adaptive_layers.size() > 0 ) {
235  nontrivial_adaptive_layers_py = matrix_int8_to_numpy( nontrivial_adaptive_layers );
236  nontrivial_adaptive_layers.set_owner( false );
237  }
238  else {
239  nontrivial_adaptive_layers_py = Py_None;
240  }
241 
242 
243 
244  return Py_BuildValue("(OO)", chanels_py, nontrivial_adaptive_layers_py);
245  //return chanels_py;
246 
247 
248 
249 }
250 
251 
252 
253 
254 
255 
256 
260 static PyMemberDef qgd_nn_Wrapper_members[] = {
261  {NULL} /* Sentinel */
262 };
263 
267 static PyMethodDef qgd_nn_Wrapper_methods[] = {
268  {"get_NN_Chanels", (PyCFunction) qgd_nn_Wrapper_get_nn_chanels, METH_VARARGS | METH_KEYWORDS,
269  "Method to retrieve the data chanels for the neural network."
270  },
271  {NULL} /* Sentinel */
272 };
273 
278  PyVarObject_HEAD_INIT(NULL, 0)
279  "qgd_nn_Wrapper.qgd_nn_Wrapper", /*tp_name*/
280  sizeof(qgd_nn_Wrapper), /*tp_basicsize*/
281  0, /*tp_itemsize*/
282  (destructor) qgd_nn_Wrapper_dealloc, /*tp_dealloc*/
283  #if PY_VERSION_HEX < 0x030800b4
284  0, /*tp_print*/
285  #endif
286  #if PY_VERSION_HEX >= 0x030800b4
287  0, /*tp_vectorcall_offset*/
288  #endif
289  0, /*tp_getattr*/
290  0, /*tp_setattr*/
291  #if PY_MAJOR_VERSION < 3
292  0, /*tp_compare*/
293  #endif
294  #if PY_MAJOR_VERSION >= 3
295  0, /*tp_as_async*/
296  #endif
297  0, /*tp_repr*/
298  0, /*tp_as_number*/
299  0, /*tp_as_sequence*/
300  0, /*tp_as_mapping*/
301  0, /*tp_hash*/
302  0, /*tp_call*/
303  0, /*tp_str*/
304  0, /*tp_getattro*/
305  0, /*tp_setattro*/
306  0, /*tp_as_buffer*/
307  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
308  "Object to represent a Gates_block class of the QGD package.", /*tp_doc*/
309  0, /*tp_traverse*/
310  0, /*tp_clear*/
311  0, /*tp_richcompare*/
312  0, /*tp_weaklistoffset*/
313  0, /*tp_iter*/
314  0, /*tp_iternext*/
315  qgd_nn_Wrapper_methods, /*tp_methods*/
316  qgd_nn_Wrapper_members, /*tp_members*/
317  0, /*tp_getset*/
318  0, /*tp_base*/
319  0, /*tp_dict*/
320  0, /*tp_descr_get*/
321  0, /*tp_descr_set*/
322  0, /*tp_dictoffset*/
323  (initproc) qgd_nn_Wrapper_init, /*tp_init*/
324  0, /*tp_alloc*/
325  qgd_nn_Wrapper_new, /*tp_new*/
326  0, /*tp_free*/
327  0, /*tp_is_gc*/
328  0, /*tp_bases*/
329  0, /*tp_mro*/
330  0, /*tp_cache*/
331  0, /*tp_subclasses*/
332  0, /*tp_weaklist*/
333  0, /*tp_del*/
334  0, /*tp_version_tag*/
335  #if PY_VERSION_HEX >= 0x030400a1
336  0, /*tp_finalize*/
337  #endif
338  #if PY_VERSION_HEX >= 0x030800b1
339  0, /*tp_vectorcall*/
340  #endif
341  #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000
342  0, /*tp_print*/
343  #endif
344 };
345 
349 static PyModuleDef qgd_nn_Wrapper_Module = {
350  PyModuleDef_HEAD_INIT,
351  "qgd_nn_Wrapper",
352  "Python binding for the neural network component of SQUANDER",
353  -1,
354 };
355 
356 
360 PyMODINIT_FUNC
362 {
363  // initialize Numpy API
364  import_array();
365 
366  PyObject *m;
367  if (PyType_Ready(&qgd_nn_Wrapper_Type) < 0)
368  return NULL;
369 
370  m = PyModule_Create(&qgd_nn_Wrapper_Module);
371  if (m == NULL)
372  return NULL;
373 
374  Py_INCREF(&qgd_nn_Wrapper_Type);
375  if (PyModule_AddObject(m, "qgd_nn_Wrapper", (PyObject *) &qgd_nn_Wrapper_Type) < 0) {
376  Py_DECREF(&qgd_nn_Wrapper_Type);
377  Py_DECREF(m);
378  return NULL;
379  }
380 
381  return m;
382 }
383 
384 
385 } //extern C
386 
PyMODINIT_FUNC PyInit_qgd_nn_Wrapper(void)
Method called when the Python module is initialized.
NN * create_NN()
Creates an instance of class NN and return with a pointer pointing to the class instance (C++ linking...
int levels
[creating decomp class]
static void qgd_nn_Wrapper_dealloc(qgd_nn_Wrapper *self)
Method called when a python instance of the class qgd_nn_Wrapper is destroyed.
PyObject * matrix_real_to_numpy(Matrix_real &mtx)
Call to make a numpy array from an instance of matrix class.
static PyMethodDef qgd_nn_Wrapper_methods[]
Structure containing metadata about the methods of class qgd_nn_Wrapper.
static PyTypeObject qgd_nn_Wrapper_Type
A structure describing the type of the class qgd_nn_Wrapper.
Base Class to store data of arrays and its properties.
Definition: matrix_base.hpp:38
static PyMemberDef qgd_nn_Wrapper_members[]
Structure containing metadata about the members of class qgd_nn_Wrapper.
static PyObject * qgd_nn_Wrapper_get_nn_chanels(qgd_nn_Wrapper *self, PyObject *args, PyObject *kwds)
Wrapper function to call the start_decomposition method of C++ class N_Qubit_Decomposition.
static int qgd_nn_Wrapper_init(qgd_nn_Wrapper *self, PyObject *args, PyObject *kwds)
Method called when a python instance of the class qgd_nn_Wrapper is initialized.
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...
int size() const
Call to get the number of the allocated elements.
Type definition of the qgd_nn_Wrapper Python class of the qgd_nn_Wrapper module.
PyObject_HEAD NN * nn
pointer to the C++ side NN component
void release_NN(NN *instance)
Call to deallocate an instance of N_Qubit_Decomposition_adaptive class.
static PyObject * qgd_nn_Wrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Method called when a python instance of the class qgd_nn_Wrapper is allocated.
A class containing basic methods for the decomposition process.
Definition: NN.h:61
PyObject * matrix_int8_to_numpy(matrix_base< int8_t > &mtx)
Call to make a numpy array from an instance of matrix_base<int8_t> class.
Class to store data of complex arrays and its properties.
Definition: matrix_real.h:39
static PyModuleDef qgd_nn_Wrapper_Module
Structure containing metadata about the module.