26 #define PY_SSIZE_T_CLEAN 29 #include "structmember.h" 65 #include <numpy/arrayobject.h> 125 Py_TYPE(
self)->tp_free((PyObject *)
self);
137 static char *kwlist[] = {(
char*)
"qbit_num", NULL};
143 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|i", kwlist, &qbit_num)) {
144 std::string err(
"Unable to parse arguments");
145 PyErr_SetString(PyExc_Exception, err.c_str());
156 return (PyObject *)
self;
182 #define qgd_Circuit_Wrapper_add_one_qubit_gate(gate_name, GATE_NAME)\ 184 qgd_Circuit_Wrapper_add_##GATE_NAME(qgd_Circuit_Wrapper *self, PyObject *args, PyObject *kwds) \ 186 static char *kwlist[] = {(char*)"target_qbit", NULL};\ 188 int target_qbit = -1; \ 190 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist,\ 192 return Py_BuildValue("i", -1);\ 194 if (target_qbit != -1 ) {\ 195 self->circuit->add_##gate_name(target_qbit);\ 198 return Py_BuildValue("i", 0);\ 201 #define qgd_Circuit_Wrapper_add_qbit_only_gate(gate_name, GATE_NAME)\ 203 qgd_Circuit_Wrapper_add_##GATE_NAME(qgd_Circuit_Wrapper *self, PyObject *args, PyObject *kwds) \ 207 self->circuit->add_##gate_name();\ 208 return Py_BuildValue("i", 0);\ 211 #define qgd_Circuit_Wrapper_add_two_qubit_gate(gate_name, GATE_NAME)\ 213 qgd_Circuit_Wrapper_add_##GATE_NAME(qgd_Circuit_Wrapper *self, PyObject *args, PyObject *kwds) \ 215 static char *kwlist[] = {(char*)"target_qbit", (char*)"control_qbit", NULL};\ 216 int target_qbit = -1; \ 217 int control_qbit = -1; \ 218 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwlist,\ 219 &target_qbit, &control_qbit))\ 220 return Py_BuildValue("i", -1);\ 221 if (target_qbit != -1 ) {\ 222 self->circuit->add_##gate_name(target_qbit, control_qbit);\ 224 return Py_BuildValue("i", 0);\ 282 static char *kwlist[] = {(
char*)
"target_qbits", NULL};
285 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|O", kwlist, &target_qbits_py))
288 if (target_qbits_py != NULL && PyList_Check(target_qbits_py)) {
289 std::vector<int> target_qbits;
290 Py_ssize_t list_size = PyList_Size(target_qbits_py);
291 for (Py_ssize_t i = 0; i < list_size; i++) {
292 PyObject* item = PyList_GetItem(target_qbits_py, i);
293 target_qbits.push_back(PyLong_AsLong(item));
295 self->circuit->add_swap(target_qbits);
305 static char *kwlist[] = {(
char*)
"target_qbits", NULL};
306 PyObject* target_qbits_py = NULL;
308 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|O", kwlist, &target_qbits_py))
311 if (target_qbits_py != NULL && PyList_Check(target_qbits_py)) {
312 std::vector<int> target_qbits;
313 Py_ssize_t list_size = PyList_Size(target_qbits_py);
314 for (Py_ssize_t i = 0; i < list_size; i++) {
315 PyObject* item = PyList_GetItem(target_qbits_py, i);
316 target_qbits.push_back(PyLong_AsLong(item));
318 self->circuit->add_rxx(target_qbits);
328 static char *kwlist[] = {(
char*)
"target_qbits", NULL};
329 PyObject* target_qbits_py = NULL;
331 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|O", kwlist, &target_qbits_py))
334 if (target_qbits_py != NULL && PyList_Check(target_qbits_py)) {
335 std::vector<int> target_qbits;
336 Py_ssize_t list_size = PyList_Size(target_qbits_py);
337 for (Py_ssize_t i = 0; i < list_size; i++) {
338 PyObject* item = PyList_GetItem(target_qbits_py, i);
339 target_qbits.push_back(PyLong_AsLong(item));
341 self->circuit->add_ryy(target_qbits);
351 static char *kwlist[] = {(
char*)
"target_qbits", NULL};
352 PyObject* target_qbits_py = NULL;
354 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|O", kwlist, &target_qbits_py))
357 if (target_qbits_py != NULL && PyList_Check(target_qbits_py)) {
358 std::vector<int> target_qbits;
359 Py_ssize_t list_size = PyList_Size(target_qbits_py);
360 for (Py_ssize_t i = 0; i < list_size; i++) {
361 PyObject* item = PyList_GetItem(target_qbits_py, i);
362 target_qbits.push_back(PyLong_AsLong(item));
364 self->circuit->add_rzz(target_qbits);
390 static char *kwlist[] = {(
char*)
"target_qbit", (
char*)
"control_qbits", NULL};
394 PyObject* control_qbits_py = NULL;
397 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|iO", kwlist,
398 &target_qbit, &control_qbits_py))
402 if (target_qbit != -1 && control_qbits_py != NULL && PyList_Check(control_qbits_py)) {
403 std::vector<int> control_qbits;
404 Py_ssize_t list_size = PyList_Size(control_qbits_py);
405 for (Py_ssize_t i = 0; i < list_size; i++) {
406 PyObject* item = PyList_GetItem(control_qbits_py, i);
407 if (PyLong_Check(item)) {
408 control_qbits.push_back(PyLong_AsLong(item));
411 if (control_qbits.size() >= 2) {
412 self->circuit->add_ccx(target_qbit, control_qbits);
432 static char *kwlist[] = {(
char*)
"target_qbits", (
char*)
"control_qbits", NULL};
435 PyObject* target_qbits_py = NULL;
436 PyObject* control_qbits_py = NULL;
439 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|OO", kwlist,
440 &target_qbits_py, &control_qbits_py))
444 if (target_qbits_py != NULL && PyList_Check(target_qbits_py) &&
445 control_qbits_py != NULL && PyList_Check(control_qbits_py)) {
447 std::vector<int> target_qbits;
448 Py_ssize_t target_size = PyList_Size(target_qbits_py);
449 for (Py_ssize_t i = 0; i < target_size; i++) {
450 PyObject* item = PyList_GetItem(target_qbits_py, i);
451 if (PyLong_Check(item)) {
452 target_qbits.push_back(PyLong_AsLong(item));
456 std::vector<int> control_qbits;
457 Py_ssize_t control_size = PyList_Size(control_qbits_py);
458 for (Py_ssize_t i = 0; i < control_size; i++) {
459 PyObject* item = PyList_GetItem(control_qbits_py, i);
460 if (PyLong_Check(item)) {
461 control_qbits.push_back(PyLong_AsLong(item));
465 if (target_qbits.size() >= 2 && control_qbits.size() >= 1) {
466 self->circuit->add_cswap(target_qbits, control_qbits);
485 PyObject *Py_Circuit;
488 if (!PyArg_ParseTuple(args,
"|O",
514 static char *kwlist[] = {(
char*)
"operation_mtx", (
char*)
"target_qbits", (
char*)
"control_qbits", (
char*)
"is_f32", NULL};
516 PyObject* operation_mtx_obj = NULL;
517 PyObject* target_qbits_py = NULL;
518 PyObject* control_qbits_py = NULL;
521 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"O|OOp", kwlist,
522 &operation_mtx_obj, &target_qbits_py, &control_qbits_py, &is_f32)) {
526 if (operation_mtx_obj == NULL) {
527 PyErr_SetString(PyExc_ValueError,
"operation_mtx must be provided");
531 PyArrayObject* operation_mtx = NULL;
533 operation_mtx = (PyArrayObject*)PyArray_FROM_OTF(operation_mtx_obj, NPY_COMPLEX64, NPY_ARRAY_IN_ARRAY);
535 operation_mtx = (PyArrayObject*)PyArray_FROM_OTF(operation_mtx_obj, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
538 if (operation_mtx == NULL) {
542 if (PyArray_NDIM(operation_mtx) != 2) {
543 Py_DECREF(operation_mtx);
544 PyErr_SetString(PyExc_ValueError,
"operation_mtx must be a 2D square matrix");
548 const npy_intp* shape = PyArray_DIMS(operation_mtx);
549 if (shape[0] != shape[1]) {
550 Py_DECREF(operation_mtx);
551 PyErr_SetString(PyExc_ValueError,
"operation_mtx must be square");
555 const int matrix_size = 1 <<
self->circuit->get_qbit_num();
556 if ((
int)shape[0] != matrix_size) {
557 Py_DECREF(operation_mtx);
558 PyErr_SetString(PyExc_ValueError,
"operation_mtx size does not match circuit qubit count");
562 std::vector<int> target_qbits;
563 if (target_qbits_py != NULL && target_qbits_py != Py_None) {
564 if (!PyList_Check(target_qbits_py)) {
565 Py_DECREF(operation_mtx);
566 PyErr_SetString(PyExc_TypeError,
"target_qbits must be a list of integers");
570 Py_ssize_t list_size = PyList_Size(target_qbits_py);
571 for (Py_ssize_t i = 0; i < list_size; i++) {
572 PyObject* item = PyList_GetItem(target_qbits_py, i);
573 if (!PyLong_Check(item)) {
574 Py_DECREF(operation_mtx);
575 PyErr_SetString(PyExc_TypeError,
"target_qbits must contain integers");
578 int qbit = (
int)PyLong_AsLong(item);
579 if (qbit < 0 || qbit >= self->circuit->get_qbit_num()) {
580 Py_DECREF(operation_mtx);
581 PyErr_SetString(PyExc_ValueError,
"target_qbits contains out-of-range index");
584 target_qbits.push_back(qbit);
588 std::vector<int> control_qbits;
589 if (control_qbits_py != NULL && control_qbits_py != Py_None) {
590 if (!PyList_Check(control_qbits_py)) {
591 Py_DECREF(operation_mtx);
592 PyErr_SetString(PyExc_TypeError,
"control_qbits must be a list of integers");
596 Py_ssize_t list_size = PyList_Size(control_qbits_py);
597 for (Py_ssize_t i = 0; i < list_size; i++) {
598 PyObject* item = PyList_GetItem(control_qbits_py, i);
599 if (!PyLong_Check(item)) {
600 Py_DECREF(operation_mtx);
601 PyErr_SetString(PyExc_TypeError,
"control_qbits must contain integers");
604 int qbit = (
int)PyLong_AsLong(item);
605 if (qbit < 0 || qbit >= self->circuit->get_qbit_num()) {
606 Py_DECREF(operation_mtx);
607 PyErr_SetString(PyExc_ValueError,
"control_qbits contains out-of-range index");
610 control_qbits.push_back(qbit);
623 self->circuit->add_general_operation(operation_qgd, target_qbits, control_qbits);
625 catch (std::string err) {
626 Py_DECREF(operation_mtx);
627 PyErr_SetString(PyExc_Exception, err.c_str());
631 Py_DECREF(operation_mtx);
632 PyErr_SetString(PyExc_Exception,
"Failed to add GENERAL_OPERATION gate");
636 Py_DECREF(operation_mtx);
645 PyObject* o = PyList_New(0);
646 for (
int i = 0; i < gatesNum; i++) {
649 DFEgates[i].
gate_type, DFEgates[i].metadata);
651 if (gate == NULL || PyList_Append(o, gate) != 0) {
665 DFEgatePython_to_QGD(PyObject* obj)
667 Py_ssize_t gatesNum = PyList_Size(obj);
669 for (Py_ssize_t i = 0; i < gatesNum; i++) {
670 PyObject* t = PyList_GetItem(obj, i);
672 DFEgates[i].
ThetaOver2 = PyLong_AsLong(PyTuple_GetItem(t, 0));
673 DFEgates[i].
Phi = PyLong_AsLong(PyTuple_GetItem(t, 1));
674 DFEgates[i].
Lambda = PyLong_AsLong(PyTuple_GetItem(t, 2));
675 DFEgates[i].
target_qbit = PyLong_AsLong(PyTuple_GetItem(t, 3));
676 DFEgates[i].
control_qbit = PyLong_AsLong(PyTuple_GetItem(t, 4));
677 DFEgates[i].
gate_type = PyLong_AsLong(PyTuple_GetItem(t, 5));
678 DFEgates[i].
metadata = PyLong_AsLong(PyTuple_GetItem(t, 6));
684 qgd_Circuit_Wrapper_convert_to_DFE_gates_with_derivates(
qgd_Circuit_Wrapper *
self, PyObject *args)
686 bool only_derivates =
false;
687 PyArrayObject* parameters_mtx_np = NULL;
689 if (!PyArg_ParseTuple(args,
"|Ob",
690 ¶meters_mtx_np, &only_derivates))
693 if ( parameters_mtx_np == NULL ) {
697 PyArrayObject* parameters_mtx = (PyArrayObject*)PyArray_FROM_OTF((PyObject*)parameters_mtx_np, NPY_FLOAT64, NPY_ARRAY_IN_ARRAY);
700 if ( !PyArray_IS_C_CONTIGUOUS(parameters_mtx) ) {
701 std::cout <<
"parameters_mtx is not memory contiguous" << std::endl;
707 int gatesNum = -1, gateSetNum = -1, redundantGateSets = -1;
708 DFEgate_kernel_type* ret =
self->circuit->convert_to_DFE_gates_with_derivates(parameters_mtx_mtx, gatesNum, gateSetNum, redundantGateSets, only_derivates);
709 return Py_BuildValue(
"Oii", DFEgateQGD_to_Python(ret, gatesNum), gateSetNum, redundantGateSets);
713 qgd_Circuit_Wrapper_adjust_parameters_for_derivation(
qgd_Circuit_Wrapper *
self, PyObject *args)
716 PyObject* dfegates = NULL;
717 if (!PyArg_ParseTuple(args,
"|Oi",
718 &dfegates, &gatesNum))
720 int gate_idx = -1, gate_set_index = -1;
722 self->circuit->adjust_parameters_for_derivation(dfegates_qgd, gatesNum, gate_idx, gate_set_index);
723 return Py_BuildValue(
"Oii", DFEgateQGD_to_Python(dfegates_qgd, gatesNum), gate_idx, gate_set_index);
753 int start_index = -1;
754 PyArrayObject* parameters_mtx_np = NULL;
755 PyObject* dfegates = NULL;
757 if (!PyArg_ParseTuple(args,
"|OOi",
758 ¶meters_mtx_np, &dfegates, &start_index))
762 if ( parameters_mtx_np == NULL ) {
766 PyArrayObject* parameters_mtx = (PyArrayObject*)PyArray_FROM_OTF((PyObject*)parameters_mtx_np, NPY_FLOAT64, NPY_ARRAY_IN_ARRAY);
769 if ( !PyArray_IS_C_CONTIGUOUS(parameters_mtx) ) {
770 std::cout <<
"parameters_mtx is not memory contiguous" << std::endl;
777 Py_ssize_t gatesNum = PyList_Size(dfegates);
779 self->circuit->convert_to_DFE_gates(parameters_mtx_mtx, dfegates_qgd, start_index);
781 return DFEgateQGD_to_Python(dfegates_qgd, gatesNum);
795 PyArrayObject * parameters_arr = NULL;
798 static char *kwlist[] = {(
char*)
"", (
char*)
"is_f32", NULL};
801 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"O|p", kwlist, ¶meters_arr, &is_f32))
805 if (!PyArray_IS_C_CONTIGUOUS(parameters_arr)) {
806 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF((PyObject*)parameters_arr, NPY_FLOAT, NPY_ARRAY_IN_ARRAY);
808 Py_INCREF(parameters_arr);
811 Matrix_float mtx =
self->circuit->get_matrix(parameters_mtx);
814 Py_DECREF(parameters_arr);
818 if (PyArray_IS_C_CONTIGUOUS(parameters_arr)) {
819 Py_INCREF(parameters_arr);
821 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF((PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
827 Matrix mtx =
self->circuit->get_matrix(parameters_mtx);
833 Py_DECREF(parameters_arr);
863 PyArrayObject * parameters_arr = NULL;
864 PyArrayObject * unitary_arg = NULL;
869 static char *kwlist[] = {(
char*)
"", (
char*)
"", (
char*)
"parallel", (
char*)
"is_f32", NULL};
873 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"OO|ip", kwlist, ¶meters_arr, &unitary_arg, ¶llel, &is_f32 )) {
874 PyErr_SetString(PyExc_Exception,
"Unable to parse input");
880 if ( unitary_arg == NULL ) {
881 PyErr_SetString(PyExc_Exception,
"Input matrix was not given");
886 if ( parameters_arr == NULL ) {
887 PyErr_SetString(PyExc_Exception,
"Parameters were not given");
892 if ( !PyArray_IS_C_CONTIGUOUS(unitary_arg) ) {
893 PyErr_SetString(PyExc_Exception,
"input matrix is not memory contiguous");
901 if ( PyArray_TYPE(unitary_arg) != NPY_COMPLEX64 ) {
902 PyErr_SetString(PyExc_TypeError,
"input matrix or state should be complex64 when is_f32=True");
906 if ( PyArray_TYPE(parameters_arr) != NPY_FLOAT ) {
907 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be float32 when is_f32=True");
911 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
912 Py_INCREF(parameters_arr);
915 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_FLOAT, NPY_ARRAY_IN_ARRAY);
922 self->circuit->apply_to( parameters_mtx, input_mtx, parallel );
924 catch (std::string err) {
925 Py_DECREF(parameters_arr);
926 PyErr_SetString(PyExc_Exception, err.c_str());
930 Py_DECREF(parameters_arr);
931 std::string err(
"Invalid pointer to circuit class");
932 PyErr_SetString(PyExc_Exception, err.c_str());
936 if (input_mtx.
data != PyArray_DATA(unitary_arg)) {
940 Py_DECREF(parameters_arr);
946 if ( PyArray_TYPE(parameters_arr) != NPY_DOUBLE ) {
947 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be float64 when is_f32=False");
952 if ( PyArray_TYPE(unitary_arg) != NPY_COMPLEX128 ) {
953 PyErr_SetString(PyExc_TypeError,
"input matrix or state should be complex128 when is_f32=False");
958 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
959 Py_INCREF(parameters_arr);
962 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
973 self->circuit->apply_to( parameters_mtx, unitary_mtx, parallel );
975 catch (std::string err) {
977 Py_DECREF(parameters_arr);
979 PyErr_SetString(PyExc_Exception, err.c_str());
984 Py_DECREF(parameters_arr);
986 std::string err(
"Invalid pointer to circuit class");
987 PyErr_SetString(PyExc_Exception, err.c_str());
991 if (unitary_mtx.
data != PyArray_DATA(unitary_arg)) {
995 Py_DECREF(parameters_arr);
1012 PyArrayObject * parameters_arr = NULL;
1013 PyArrayObject * unitary_arg = NULL;
1018 static char *kwlist[] = {(
char*)
"", (
char*)
"", (
char*)
"parallel", (
char*)
"is_f32", NULL};
1020 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"OO|ip", kwlist, ¶meters_arr, &unitary_arg, ¶llel, &is_f32 )) {
1021 PyErr_SetString(PyExc_Exception,
"Unable to parse input");
1025 if ( unitary_arg == NULL ) {
1026 PyErr_SetString(PyExc_Exception,
"Input matrix was not given");
1030 if ( parameters_arr == NULL ) {
1031 PyErr_SetString(PyExc_Exception,
"Parameters were not given");
1035 if ( !PyArray_IS_C_CONTIGUOUS(unitary_arg) ) {
1036 PyErr_SetString(PyExc_Exception,
"input matrix is not memory contiguous");
1043 if ( PyArray_TYPE(unitary_arg) != NPY_COMPLEX64 ) {
1044 PyErr_SetString(PyExc_TypeError,
"input matrix should be complex64 when is_f32=True");
1048 if ( PyArray_TYPE(parameters_arr) != NPY_FLOAT ) {
1049 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be float32 when is_f32=True");
1053 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
1054 Py_INCREF(parameters_arr);
1057 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_FLOAT, NPY_ARRAY_IN_ARRAY);
1064 self->circuit->apply_from_right( parameters_mtx, input_mtx );
1066 catch (std::string err) {
1067 Py_DECREF(parameters_arr);
1068 PyErr_SetString(PyExc_Exception, err.c_str());
1072 Py_DECREF(parameters_arr);
1073 std::string err(
"Invalid pointer to circuit class");
1074 PyErr_SetString(PyExc_Exception, err.c_str());
1078 if (input_mtx.
data != PyArray_DATA(unitary_arg)) {
1082 Py_DECREF(parameters_arr);
1087 if ( PyArray_TYPE(parameters_arr) != NPY_DOUBLE ) {
1088 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be float64 when is_f32=False");
1092 if ( PyArray_TYPE(unitary_arg) != NPY_COMPLEX128 ) {
1093 PyErr_SetString(PyExc_TypeError,
"input matrix should be complex128 when is_f32=False");
1097 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
1098 Py_INCREF(parameters_arr);
1101 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
1108 self->circuit->apply_from_right( parameters_mtx, unitary_mtx );
1110 catch (std::string err) {
1111 Py_DECREF(parameters_arr);
1112 PyErr_SetString(PyExc_Exception, err.c_str());
1116 Py_DECREF(parameters_arr);
1117 std::string err(
"Invalid pointer to circuit class");
1118 PyErr_SetString(PyExc_Exception, err.c_str());
1122 if (unitary_mtx.
data != PyArray_DATA(unitary_arg)) {
1126 Py_DECREF(parameters_arr);
1138 Matrix* m =
static_cast<Matrix*
>( PyCapsule_GetPointer(cap,
"squander.circuit_matrix_owner") );
1163 static char *kwlist[] = {(
char*)
"inputs", (
char*)
"parameters", (
char*)
"parallel", (
char*)
"is_f32", NULL};
1165 PyObject * inputs_obj = NULL;
1166 PyArrayObject * parameters_arr = NULL;
1170 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"OO|ip", kwlist, &inputs_obj, ¶meters_arr, ¶llel, &is_f32 )) {
1171 PyErr_SetString(PyExc_Exception,
"Unable to parse input");
1175 if ( inputs_obj == NULL ) {
1176 PyErr_SetString(PyExc_Exception,
"Input list was not given");
1180 if ( parameters_arr == NULL ) {
1181 PyErr_SetString(PyExc_Exception,
"Parameters were not given");
1185 PyObject* seq = PySequence_Fast(inputs_obj,
"inputs must be a sequence of numpy arrays");
1190 const Py_ssize_t
n = PySequence_Fast_GET_SIZE(seq);
1191 PyObject** items = PySequence_Fast_ITEMS(seq);
1196 if ( PyArray_TYPE(parameters_arr) != NPY_FLOAT ) {
1198 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be float32 when is_f32=True");
1202 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
1203 Py_INCREF(parameters_arr);
1206 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_FLOAT, NPY_ARRAY_IN_ARRAY);
1211 std::vector<Matrix_float> inputs;
1212 inputs.reserve((
size_t)n);
1214 for (Py_ssize_t idx = 0; idx <
n; idx++) {
1215 PyObject* item = items[idx];
1216 if (!PyArray_Check(item)) {
1218 Py_DECREF(parameters_arr);
1219 PyErr_SetString(PyExc_TypeError,
"All inputs should be numpy arrays");
1223 PyArrayObject* input = (PyArrayObject*)item;
1224 if ( PyArray_TYPE(input) != NPY_COMPLEX64 ) {
1226 Py_DECREF(parameters_arr);
1227 PyErr_SetString(PyExc_TypeError,
"All inputs should be complex64 when is_f32=True");
1231 if ( !PyArray_IS_C_CONTIGUOUS(input) ) {
1233 Py_DECREF(parameters_arr);
1234 PyErr_SetString(PyExc_TypeError,
"All inputs should be C-contiguous");
1242 self->circuit->apply_to_list( parameters_mtx, inputs, parallel );
1244 catch (std::string err) {
1246 Py_DECREF(parameters_arr);
1247 PyErr_SetString(PyExc_Exception, err.c_str());
1252 Py_DECREF(parameters_arr);
1253 std::string err(
"Invalid pointer to circuit class");
1254 PyErr_SetString(PyExc_Exception, err.c_str());
1259 for (Py_ssize_t idx = 0; idx <
n; idx++) {
1260 PyArrayObject* input = (PyArrayObject*)items[idx];
1262 if (mtx.
data != PyArray_DATA(input)) {
1268 Py_DECREF(parameters_arr);
1273 if ( PyArray_TYPE(parameters_arr) != NPY_DOUBLE ) {
1275 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be float64 when is_f32=False");
1279 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
1280 Py_INCREF(parameters_arr);
1283 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
1288 std::vector<Matrix> inputs;
1289 inputs.reserve((
size_t)n);
1291 for (Py_ssize_t idx = 0; idx <
n; idx++) {
1292 PyObject* item = items[idx];
1293 if (!PyArray_Check(item)) {
1295 Py_DECREF(parameters_arr);
1296 PyErr_SetString(PyExc_TypeError,
"All inputs should be numpy arrays");
1300 PyArrayObject* input = (PyArrayObject*)item;
1301 if ( PyArray_TYPE(input) != NPY_COMPLEX128 ) {
1303 Py_DECREF(parameters_arr);
1304 PyErr_SetString(PyExc_TypeError,
"All inputs should be complex128 when is_f32=False");
1308 if ( !PyArray_IS_C_CONTIGUOUS(input) ) {
1310 Py_DECREF(parameters_arr);
1311 PyErr_SetString(PyExc_TypeError,
"All inputs should be C-contiguous");
1319 self->circuit->apply_to_list( parameters_mtx, inputs, parallel );
1321 catch (std::string err) {
1323 Py_DECREF(parameters_arr);
1324 PyErr_SetString(PyExc_Exception, err.c_str());
1329 Py_DECREF(parameters_arr);
1330 std::string err(
"Invalid pointer to circuit class");
1331 PyErr_SetString(PyExc_Exception, err.c_str());
1336 for (Py_ssize_t idx = 0; idx <
n; idx++) {
1337 PyArrayObject* input = (PyArrayObject*)items[idx];
1338 Matrix& mtx = inputs[(size_t)idx];
1339 if (mtx.
data != PyArray_DATA(input)) {
1345 Py_DECREF(parameters_arr);
1360 static char *kwlist[] = {(
char*)
"parameters", (
char*)
"unitary", (
char*)
"parallel", (
char*)
"is_f32", NULL};
1362 PyArrayObject * parameters_arr = NULL;
1363 PyArrayObject * unitary_arg = NULL;
1367 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"OO|ip", kwlist, ¶meters_arr, &unitary_arg, ¶llel, &is_f32 )) {
1368 PyErr_SetString(PyExc_Exception,
"Unable to parse input");
1372 if ( unitary_arg == NULL ) {
1373 PyErr_SetString(PyExc_Exception,
"Input matrix was not given");
1377 if ( parameters_arr == NULL ) {
1378 PyErr_SetString(PyExc_Exception,
"Parameters were not given");
1382 if ( !PyArray_IS_C_CONTIGUOUS(unitary_arg) ) {
1383 PyErr_SetString(PyExc_Exception,
"input matrix is not memory contiguous");
1390 if ( PyArray_TYPE(parameters_arr) != NPY_FLOAT ) {
1391 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be float32 when is_f32=True");
1395 if ( PyArray_TYPE(unitary_arg) != NPY_COMPLEX64 ) {
1396 PyErr_SetString(PyExc_TypeError,
"Input matrix should be complex64 when is_f32=True");
1400 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
1401 Py_INCREF(parameters_arr);
1404 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_FLOAT, NPY_ARRAY_IN_ARRAY);
1410 std::vector<Matrix_float> derivs;
1412 derivs =
self->circuit->apply_derivate_to( parameters_mtx, unitary_mtx, parallel );
1414 catch (std::string err) {
1415 Py_DECREF(parameters_arr);
1416 PyErr_SetString(PyExc_Exception, err.c_str());
1420 Py_DECREF(parameters_arr);
1421 std::string err(
"Invalid pointer to circuit class");
1422 PyErr_SetString(PyExc_Exception, err.c_str());
1426 PyObject* deriv_list = PyList_New((Py_ssize_t)derivs.size());
1427 if (deriv_list == NULL) {
1428 Py_DECREF(parameters_arr);
1432 for (Py_ssize_t idx = 0; idx < (Py_ssize_t)derivs.size(); ++idx) {
1434 PyObject* cap = PyCapsule_New(
1435 owned,
"squander.circuit_matrix_float_owner",
1439 Py_DECREF(deriv_list);
1440 Py_DECREF(parameters_arr);
1443 npy_intp shape[2] = { (npy_intp)owned->
rows, (npy_intp)owned->
cols };
1444 PyObject* deriv_py = PyArray_SimpleNewFromData(
1445 2, shape, NPY_COMPLEX64, owned->
get_data());
1446 if (deriv_py == NULL) {
1448 Py_DECREF(deriv_list);
1449 Py_DECREF(parameters_arr);
1452 PyArray_SetBaseObject((PyArrayObject*)deriv_py, cap);
1453 PyList_SET_ITEM(deriv_list, idx, deriv_py);
1456 Py_DECREF(parameters_arr);
1461 if ( PyArray_TYPE(parameters_arr) != NPY_DOUBLE ) {
1462 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be float64 when is_f32=False");
1466 if ( PyArray_TYPE(unitary_arg) != NPY_COMPLEX128 ) {
1467 PyErr_SetString(PyExc_TypeError,
"Input matrix should be complex128 when is_f32=False");
1471 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
1472 Py_INCREF(parameters_arr);
1475 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
1481 std::vector<Matrix> derivs;
1483 derivs =
self->circuit->apply_derivate_to( parameters_mtx, unitary_mtx, parallel );
1485 catch (std::string err) {
1486 Py_DECREF(parameters_arr);
1487 PyErr_SetString(PyExc_Exception, err.c_str());
1491 Py_DECREF(parameters_arr);
1492 std::string err(
"Invalid pointer to circuit class");
1493 PyErr_SetString(PyExc_Exception, err.c_str());
1497 PyObject* deriv_list = PyList_New((Py_ssize_t)derivs.size());
1498 if (deriv_list == NULL) {
1499 Py_DECREF(parameters_arr);
1503 for (Py_ssize_t idx = 0; idx < (Py_ssize_t)derivs.size(); ++idx) {
1505 PyObject* cap = PyCapsule_New(
1506 owned,
"squander.circuit_matrix_owner",
1510 Py_DECREF(deriv_list);
1511 Py_DECREF(parameters_arr);
1514 npy_intp shape[2] = { (npy_intp)owned->
rows, (npy_intp)owned->
cols };
1515 PyObject* deriv_py = PyArray_SimpleNewFromData(
1516 2, shape, NPY_COMPLEX128, owned->
get_data());
1517 if (deriv_py == NULL) {
1519 Py_DECREF(deriv_list);
1520 Py_DECREF(parameters_arr);
1523 PyArray_SetBaseObject((PyArrayObject*)deriv_py, cap);
1524 PyList_SET_ITEM(deriv_list, idx, deriv_py);
1527 Py_DECREF(parameters_arr);
1543 static char *kwlist[] = {(
char*)
"parameters", (
char*)
"unitary", (
char*)
"parallel", (
char*)
"is_f32", NULL};
1545 PyArrayObject * parameters_arr = NULL;
1546 PyArrayObject * unitary_arg = NULL;
1550 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"OO|ip", kwlist, ¶meters_arr, &unitary_arg, ¶llel, &is_f32 )) {
1551 PyErr_SetString(PyExc_Exception,
"Unable to parse input");
1555 if ( unitary_arg == NULL ) {
1556 PyErr_SetString(PyExc_Exception,
"Input matrix was not given");
1560 if ( parameters_arr == NULL ) {
1561 PyErr_SetString(PyExc_Exception,
"Parameters were not given");
1565 if ( !PyArray_IS_C_CONTIGUOUS(unitary_arg) ) {
1566 PyErr_SetString(PyExc_Exception,
"input matrix is not memory contiguous");
1573 if ( PyArray_TYPE(parameters_arr) != NPY_FLOAT ) {
1574 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be float32 when is_f32=True");
1578 if ( PyArray_TYPE(unitary_arg) != NPY_COMPLEX64 ) {
1579 PyErr_SetString(PyExc_TypeError,
"Input matrix should be complex64 when is_f32=True");
1583 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
1584 Py_INCREF(parameters_arr);
1587 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_FLOAT, NPY_ARRAY_IN_ARRAY);
1593 std::vector<Matrix_float> combined;
1595 combined =
self->circuit->apply_to_combined( parameters_mtx, unitary_mtx, parallel );
1597 catch (std::string err) {
1598 Py_DECREF(parameters_arr);
1599 PyErr_SetString(PyExc_Exception, err.c_str());
1603 Py_DECREF(parameters_arr);
1604 std::string err(
"Invalid pointer to circuit class");
1605 PyErr_SetString(PyExc_Exception, err.c_str());
1609 PyObject* combined_list = PyList_New((Py_ssize_t)combined.size());
1610 if (combined_list == NULL) {
1611 Py_DECREF(parameters_arr);
1615 for (Py_ssize_t idx = 0; idx < (Py_ssize_t)combined.size(); ++idx) {
1617 PyObject* cap = PyCapsule_New(
1618 owned,
"squander.circuit_matrix_float_owner",
1622 Py_DECREF(combined_list);
1623 Py_DECREF(parameters_arr);
1626 npy_intp shape[2] = { (npy_intp)owned->
rows, (npy_intp)owned->
cols };
1627 PyObject* out_py = PyArray_SimpleNewFromData(
1628 2, shape, NPY_COMPLEX64, owned->
get_data());
1629 if (out_py == NULL) {
1631 Py_DECREF(combined_list);
1632 Py_DECREF(parameters_arr);
1635 PyArray_SetBaseObject((PyArrayObject*)out_py, cap);
1636 PyList_SET_ITEM(combined_list, idx, out_py);
1639 Py_DECREF(parameters_arr);
1640 return combined_list;
1644 if ( PyArray_TYPE(parameters_arr) != NPY_DOUBLE ) {
1645 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be float64 when is_f32=False");
1649 if ( PyArray_TYPE(unitary_arg) != NPY_COMPLEX128 ) {
1650 PyErr_SetString(PyExc_TypeError,
"Input matrix should be complex128 when is_f32=False");
1654 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
1655 Py_INCREF(parameters_arr);
1658 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
1664 std::vector<Matrix> combined;
1666 combined =
self->circuit->apply_to_combined( parameters_mtx, unitary_mtx, parallel );
1668 catch (std::string err) {
1669 Py_DECREF(parameters_arr);
1670 PyErr_SetString(PyExc_Exception, err.c_str());
1674 Py_DECREF(parameters_arr);
1675 std::string err(
"Invalid pointer to circuit class");
1676 PyErr_SetString(PyExc_Exception, err.c_str());
1680 PyObject* combined_list = PyList_New((Py_ssize_t)combined.size());
1681 if (combined_list == NULL) {
1682 Py_DECREF(parameters_arr);
1686 for (Py_ssize_t idx = 0; idx < (Py_ssize_t)combined.size(); ++idx) {
1688 PyObject* cap = PyCapsule_New(
1689 owned,
"squander.circuit_matrix_owner",
1693 Py_DECREF(combined_list);
1694 Py_DECREF(parameters_arr);
1697 npy_intp shape[2] = { (npy_intp)owned->
rows, (npy_intp)owned->
cols };
1698 PyObject* out_py = PyArray_SimpleNewFromData(
1699 2, shape, NPY_COMPLEX128, owned->
get_data());
1700 if (out_py == NULL) {
1702 Py_DECREF(combined_list);
1703 Py_DECREF(parameters_arr);
1706 PyArray_SetBaseObject((PyArrayObject*)out_py, cap);
1707 PyList_SET_ITEM(combined_list, idx, out_py);
1710 Py_DECREF(parameters_arr);
1711 return combined_list;
1727 PyArrayObject * parameters_arr = NULL;
1728 PyArrayObject * input_state_arg = NULL;
1729 PyObject * qubit_list_arg = NULL;
1733 if (!PyArg_ParseTuple(args,
"|OOO", ¶meters_arr, &input_state_arg, &qubit_list_arg ))
1737 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
1738 Py_INCREF(parameters_arr);
1741 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
1749 if ( input_state_arg == NULL ) {
1750 PyErr_SetString(PyExc_Exception,
"Input matrix was not given");
1754 PyArrayObject* input_state = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)input_state_arg, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
1757 if ( !PyArray_IS_C_CONTIGUOUS(input_state) ) {
1758 PyErr_SetString(PyExc_Exception,
"input matrix is not memory contiguous");
1770 if ( qubit_list_arg == NULL || (!PyList_Check( qubit_list_arg )) ) {
1771 PyErr_SetString(PyExc_Exception,
"qubit_list should be a list");
1775 Py_ssize_t reduced_qbit_num = PyList_Size( qubit_list_arg );
1778 for (
int idx=0; idx<reduced_qbit_num; idx++ ) {
1780 PyObject* item = PyList_GET_ITEM( qubit_list_arg, idx );
1781 qbit_list_mtx[idx] = (
int) PyLong_AsLong( item );
1790 entropy =
self->circuit->get_second_Renyi_entropy( parameters_mtx, input_state_mtx, qbit_list_mtx );
1792 catch (std::string err) {
1793 PyErr_SetString(PyExc_Exception, err.c_str());
1797 std::string err(
"Invalid pointer to circuit class");
1798 PyErr_SetString(PyExc_Exception, err.c_str());
1803 Py_DECREF(parameters_arr);
1804 Py_DECREF(input_state);
1826 qbit_num =
self->circuit->get_qbit_num();
1828 catch (std::string err) {
1829 PyErr_SetString(PyExc_Exception, err.c_str());
1830 std::cout << err << std::endl;
1834 std::string err(
"Invalid pointer to circuit class");
1835 PyErr_SetString(PyExc_Exception, err.c_str());
1859 if (!PyArg_ParseTuple(args,
"|i", &qbit_num )) {
1860 std::string err(
"Unable to parse arguments");
1861 PyErr_SetString(PyExc_Exception, err.c_str());
1867 self->circuit->set_qbit_num( qbit_num );
1869 catch (std::string err) {
1870 PyErr_SetString(PyExc_Exception, err.c_str());
1871 std::cout << err << std::endl;
1875 std::string err(
"Invalid pointer to circuit class");
1876 PyErr_SetString(PyExc_Exception, err.c_str());
1895 PyObject* ret = PyList_New(0);
1898 std::vector<int>&& qbits =
self->circuit->get_involved_qubits();
1899 for (
size_t idx = 0; idx < qbits.size(); idx++) {
1901 if ( qbit == NULL || PyList_Append(ret, qbit) != 0 ) {
1910 catch (std::string err) {
1911 PyErr_SetString(PyExc_Exception, err.c_str());
1912 std::cout << err << std::endl;
1917 std::string err(
"Invalid pointer to circuit class");
1918 PyErr_SetString(PyExc_Exception, err.c_str());
1931 int min_fusion = -1;
1934 if (!PyArg_ParseTuple(args,
"|i", &min_fusion )) {
1935 std::string err(
"Unable to parse arguments");
1936 PyErr_SetString(PyExc_Exception, err.c_str());
1942 self->circuit->set_min_fusion( min_fusion );
1944 catch (std::string err) {
1945 PyErr_SetString(PyExc_Exception, err.c_str());
1946 std::cout << err << std::endl;
1950 std::string err(
"Invalid pointer to circuit class");
1951 PyErr_SetString(PyExc_Exception, err.c_str());
1971 PyObject* qbit_map_arg = NULL;
1976 if (!PyArg_ParseTuple(args,
"|Oi", &qbit_map_arg, &qbit_num ))
1982 bool is_dict = (PyDict_Check( qbit_map_arg ) != 0);
1984 printf(
"Qubit map object must be a python dictionary!\n");
1989 std::map<int, int> qbit_map;
1993 PyObject *
key, *value;
1996 while (PyDict_Next(qbit_map_arg, &pos, &key, &value)) {
1999 if ( PyLong_Check( value ) && PyLong_Check( key ) ) {
2000 int key_Cpp = (
int)PyLong_AsLongLong( key );
2001 qbit_map[ key_Cpp ] = (
int)PyLong_AsLongLong( value );
2004 std::string err(
"Key and value in the qbit_map should be integers");
2005 PyErr_SetString(PyExc_Exception, err.c_str());
2018 catch (std::string err) {
2019 PyErr_SetString(PyExc_Exception, err.c_str());
2020 std::cout << err << std::endl;
2024 std::string err(
"Invalid pointer to circuit class");
2025 PyErr_SetString(PyExc_Exception, err.c_str());
2032 PyObject* qgd_circuit = PyImport_ImportModule(
"squander.gates.qgd_Circuit");
2034 if ( qgd_circuit == NULL ) {
2035 PyErr_SetString(PyExc_Exception,
"Module import error: squander.gates.qgd_Circuit" );
2039 PyObject* qgd_circuit_Dict = PyModule_GetDict( qgd_circuit );
2042 PyObject* py_circuit_class = PyDict_GetItemString( qgd_circuit_Dict,
"qgd_Circuit");
2045 if ( qbit_num_py == NULL ) {
2046 Py_DECREF( qgd_circuit );
2050 PyObject* circuit_input =
Py_BuildValue(
"(O)", qbit_num_py);
2051 Py_DECREF( qbit_num_py );
2052 if ( circuit_input == NULL ) {
2053 Py_DECREF( qgd_circuit );
2056 PyObject* py_circuit = PyObject_CallObject(py_circuit_class, circuit_input);
2062 delete( py_circuit_C->
circuit );
2063 py_circuit_C->
circuit = remapped_circuit;
2065 Py_DECREF( qgd_circuit );
2066 Py_DECREF( circuit_input );
2074 #define get_gate_template_two_qubit(GATE_NAME) \ 2075 else if (gate->get_type() == GATE_NAME##_OPERATION) { \ 2076 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate ); \ 2077 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict, #GATE_NAME); \ 2078 PyObject* gate_input = Py_BuildValue("(OOO)", qbit_num, target_qbit, control_qbit); \ 2079 py_gate = PyObject_CallObject(py_gate_class, gate_input); \ 2080 qgd_Gate* py_gate_C = reinterpret_cast<qgd_Gate*>( py_gate ); \ 2081 delete( py_gate_C->gate ); \ 2082 py_gate_C->gate = static_cast<Gate*>( gate->clone() ); \ 2083 Py_DECREF( qgd_gate ); \ 2084 Py_DECREF( gate_input ); \ 2087 #define get_gate_template_one_qubit(GATE_NAME) \ 2088 else if (gate->get_type() == GATE_NAME##_OPERATION) { \ 2089 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate ); \ 2090 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict, #GATE_NAME); \ 2091 PyObject* gate_input = Py_BuildValue("(OO)", qbit_num, target_qbit); \ 2092 py_gate = PyObject_CallObject(py_gate_class, gate_input); \ 2093 qgd_Gate* py_gate_C = reinterpret_cast<qgd_Gate*>( py_gate ); \ 2094 delete( py_gate_C->gate ); \ 2095 py_gate_C->gate = static_cast<Gate*>( gate->clone() ); \ 2096 Py_DECREF( qgd_gate ); \ 2097 Py_DECREF( gate_input ); \ 2119 PyObject* py_gate = NULL;
2122 PyObject* qgd_gate = PyImport_ImportModule(
"squander.gates.gates_Wrapper");
2124 if ( qgd_gate == NULL ) {
2125 PyErr_SetString(PyExc_Exception,
"Module import error: squander.gates.gates_Wrapper" );
2131 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2133 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"CNOT");
2135 PyObject* gate_input =
Py_BuildValue(
"(OOO)", qbit_num, target_qbit, control_qbit);
2136 py_gate = PyObject_CallObject(py_gate_class, gate_input);
2140 delete( py_gate_C->
gate );
2143 Py_DECREF( qgd_gate );
2144 Py_DECREF( gate_input );
2161 PyObject* target_qbits_list = PyList_New((Py_ssize_t)target_qbits_vec.size());
2162 for (
size_t i = 0; i < target_qbits_vec.size(); i++) {
2163 PyList_SetItem(target_qbits_list, (Py_ssize_t)i,
Py_BuildValue(
"i", target_qbits_vec[i]));
2166 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2167 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"SWAP");
2169 PyObject* gate_input =
Py_BuildValue(
"(OO)", qbit_num, target_qbits_list);
2170 py_gate = PyObject_CallObject(py_gate_class, gate_input);
2174 delete( py_gate_C->
gate );
2177 Py_DECREF( qgd_gate );
2178 Py_DECREF( gate_input );
2179 Py_DECREF( target_qbits_list );
2185 PyObject* target_qbits_list = PyList_New((Py_ssize_t)target_qbits_vec.size());
2186 for (
size_t i = 0; i < target_qbits_vec.size(); i++) {
2187 PyList_SetItem(target_qbits_list, (Py_ssize_t)i,
Py_BuildValue(
"i", target_qbits_vec[i]));
2190 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2191 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"RXX");
2193 PyObject* gate_input =
Py_BuildValue(
"(OO)", qbit_num, target_qbits_list);
2194 py_gate = PyObject_CallObject(py_gate_class, gate_input);
2198 delete( py_gate_C->
gate );
2201 Py_DECREF( qgd_gate );
2202 Py_DECREF( gate_input );
2203 Py_DECREF( target_qbits_list );
2209 PyObject* target_qbits_list = PyList_New((Py_ssize_t)target_qbits_vec.size());
2210 for (
size_t i = 0; i < target_qbits_vec.size(); i++) {
2211 PyList_SetItem(target_qbits_list, (Py_ssize_t)i,
Py_BuildValue(
"i", target_qbits_vec[i]));
2214 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2215 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"RYY");
2217 PyObject* gate_input =
Py_BuildValue(
"(OO)", qbit_num, target_qbits_list);
2218 py_gate = PyObject_CallObject(py_gate_class, gate_input);
2222 delete( py_gate_C->
gate );
2225 Py_DECREF( qgd_gate );
2226 Py_DECREF( gate_input );
2227 Py_DECREF( target_qbits_list );
2233 PyObject* target_qbits_list = PyList_New((Py_ssize_t)target_qbits_vec.size());
2234 for (
size_t i = 0; i < target_qbits_vec.size(); i++) {
2235 PyList_SetItem(target_qbits_list, (Py_ssize_t)i,
Py_BuildValue(
"i", target_qbits_vec[i]));
2238 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2239 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"RZZ");
2241 PyObject* gate_input =
Py_BuildValue(
"(OO)", qbit_num, target_qbits_list);
2242 py_gate = PyObject_CallObject(py_gate_class, gate_input);
2246 delete( py_gate_C->
gate );
2249 Py_DECREF( qgd_gate );
2250 Py_DECREF( gate_input );
2251 Py_DECREF( target_qbits_list );
2271 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2273 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"Sdg");
2275 PyObject* gate_input =
Py_BuildValue(
"(OO)", qbit_num, target_qbit);
2276 py_gate = PyObject_CallObject(py_gate_class, gate_input);
2280 delete( py_gate_C->
gate );
2283 Py_DECREF( qgd_gate );
2284 Py_DECREF( gate_input );
2291 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2293 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"SXdg");
2295 PyObject* gate_input =
Py_BuildValue(
"(OO)", qbit_num, target_qbit);
2296 py_gate = PyObject_CallObject(py_gate_class, gate_input);
2300 delete( py_gate_C->
gate );
2303 Py_DECREF( qgd_gate );
2304 Py_DECREF( gate_input );
2311 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2313 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"Tdg");
2315 PyObject* gate_input =
Py_BuildValue(
"(OO)", qbit_num, target_qbit);
2316 py_gate = PyObject_CallObject(py_gate_class, gate_input);
2320 delete( py_gate_C->
gate );
2323 Py_DECREF( qgd_gate );
2324 Py_DECREF( gate_input );
2331 PyObject* control_qbits_list = PyList_New((Py_ssize_t)control_qbits_vec.size());
2332 for (
size_t i = 0; i < control_qbits_vec.size(); i++) {
2333 PyList_SetItem(control_qbits_list, (Py_ssize_t)i,
Py_BuildValue(
"i", control_qbits_vec[i]));
2336 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2338 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"CCX");
2340 PyObject* gate_input =
Py_BuildValue(
"(OOO)", qbit_num, target_qbit, control_qbits_list);
2341 py_gate = PyObject_CallObject(py_gate_class, gate_input);
2345 delete( py_gate_C->
gate );
2348 Py_DECREF( qgd_gate );
2349 Py_DECREF( gate_input );
2350 Py_DECREF( control_qbits_list );
2352 Py_XDECREF(qbit_num);
2353 Py_XDECREF(target_qbit);
2354 Py_XDECREF(control_qbit);
2362 PyObject* target_qbits_list = PyList_New((Py_ssize_t)target_qbits_vec.size());
2363 for (
size_t i = 0; i < target_qbits_vec.size(); i++) {
2364 PyList_SetItem(target_qbits_list, (Py_ssize_t)i,
Py_BuildValue(
"i", target_qbits_vec[i]));
2368 PyObject* control_qbits_list = PyList_New((Py_ssize_t)control_qbits_vec.size());
2369 for (
size_t i = 0; i < control_qbits_vec.size(); i++) {
2370 PyList_SetItem(control_qbits_list, (Py_ssize_t)i,
Py_BuildValue(
"i", control_qbits_vec[i]));
2373 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2375 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"CSWAP");
2377 PyObject* gate_input =
Py_BuildValue(
"(OOO)", qbit_num, target_qbits_list, control_qbits_list);
2378 py_gate = PyObject_CallObject(py_gate_class, gate_input);
2382 delete( py_gate_C->
gate );
2385 Py_DECREF( qgd_gate );
2386 Py_DECREF( gate_input );
2387 Py_DECREF( target_qbits_list );
2388 Py_DECREF( control_qbits_list );
2390 Py_XDECREF(qbit_num);
2391 Py_XDECREF(target_qbit);
2392 Py_XDECREF(control_qbit);
2400 PyObject* qgd_circuit = PyImport_ImportModule(
"squander.gates.qgd_Circuit");
2402 if ( qgd_circuit == NULL ) {
2403 PyErr_SetString(PyExc_Exception,
"Module import error: squander.gates.qgd_Circuit" );
2407 PyObject* qgd_circuit_Dict = PyModule_GetDict( qgd_circuit );
2410 PyObject* py_circuit_class = PyDict_GetItemString( qgd_circuit_Dict,
"qgd_Circuit");
2413 py_gate = PyObject_CallObject(py_circuit_class, circuit_input);
2422 Py_DECREF( qgd_circuit );
2423 Py_DECREF( circuit_input );
2428 Py_DECREF( qgd_gate );
2429 Py_XDECREF(qbit_num);
2430 Py_XDECREF(target_qbit);
2431 Py_XDECREF(control_qbit);
2432 PyErr_SetString(PyExc_Exception,
"qgd_Circuit_Wrapper::get_gate: unimplemented gate type" );
2436 Py_XDECREF(qbit_num);
2437 Py_XDECREF(target_qbit);
2438 Py_XDECREF(control_qbit);
2459 if (!PyArg_ParseTuple(args,
"|i", &idx ))
return Py_BuildValue(
"i", -1);
2462 return get_gate( self->circuit, idx );
2476 std::map< std::string, int > gate_nums;
2479 gate_nums =
self->circuit->get_gate_nums();
2481 catch (std::string err) {
2482 PyErr_SetString(PyExc_Exception, err.c_str());
2486 std::string err(
"Invalid pointer to circuit class");
2487 PyErr_SetString(PyExc_Exception, err.c_str());
2492 PyObject* gate_nums_py = PyDict_New();
2493 if( gate_nums_py == NULL ) {
2494 std::string err(
"Failed to create dictionary");
2495 PyErr_SetString(PyExc_Exception, err.c_str());
2499 for(
auto it = gate_nums.begin(); it != gate_nums.end(); it++ ) {
2504 if ( key == NULL || val == NULL ) {
2507 Py_DECREF(gate_nums_py);
2511 if ( PyDict_SetItem(gate_nums_py, key, val) != 0 ) {
2514 Py_DECREF(gate_nums_py);
2522 return gate_nums_py;
2541 int op_num =
self->circuit->get_gate_num();
2544 PyObject* ret = PyTuple_New( (Py_ssize_t) op_num );
2549 for (
int idx = 0; idx < op_num; idx++ ) {
2555 PyTuple_SetItem( ret, (Py_ssize_t) idx, gate );
2576 PyObject* py_gate = NULL;
2579 if (!PyArg_ParseTuple(args,
"|O", &py_gate ))
return Py_BuildValue(
"i", -1);
2582 if( py_gate == NULL ) {
2583 return PyTuple_New( 0 );
2590 PyObject* parent_tuple = PyTuple_New( (Py_ssize_t) parents.size() );
2592 std::vector<Gate*>&& gates =
self->circuit->get_gates();
2596 for(
size_t idx=0; idx<parents.size(); idx++) {
2598 Gate* parent_gate = parents[idx];
2601 int parent_idx = -1;
2602 for(
size_t jdx=0; jdx<gates.size(); jdx++ ) {
2606 if( parent_gate == gate ) {
2607 parent_idx =
static_cast<int>(jdx);
2611 if( jdx == static_cast<size_t>(gates.size()-1) ) {
2612 std::string err(
"Parent gate did not found in the circuit. May be the gate is not in the circuit");
2613 PyErr_SetString(PyExc_Exception, err.c_str());
2620 PyTuple_SetItem( parent_tuple, (Py_ssize_t) idx,
Py_BuildValue(
"i", parent_idx) );
2626 return parent_tuple;
2644 PyObject* py_gate = NULL;
2647 if (!PyArg_ParseTuple(args,
"|O", &py_gate ))
return Py_BuildValue(
"i", -1);
2650 if( py_gate == NULL ) {
2651 return PyTuple_New( 0 );
2658 PyObject* children_tuple = PyTuple_New( (Py_ssize_t) children.size() );
2660 std::vector<Gate*>&& gates =
self->circuit->get_gates();
2664 for(
size_t idx=0; idx<children.size(); idx++) {
2666 Gate* child_gate = children[idx];
2670 for(
size_t jdx=0; jdx<gates.size(); jdx++ ) {
2674 if( child_gate == gate ) {
2675 child_idx =
static_cast<int>(jdx);
2679 if( jdx == static_cast<size_t>(gates.size()-1) ) {
2680 std::string err(
"Child gate did not found in the circuit. May be the gate is not in the circuit");
2681 PyErr_SetString(PyExc_Exception, err.c_str());
2688 PyTuple_SetItem( children_tuple, (Py_ssize_t) idx,
Py_BuildValue(
"i", child_idx) );
2694 return children_tuple;
2710 PyArrayObject * parameters_arr = NULL;
2714 if (!PyArg_ParseTuple(args,
"|O", ¶meters_arr ))
2718 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
2719 Py_INCREF(parameters_arr);
2722 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
2733 extracted_parameters =
self->circuit->extract_parameters( parameters_mtx );
2735 catch (std::string err) {
2736 PyErr_SetString(PyExc_Exception, err.c_str());
2740 std::string err(
"Invalid pointer to circuit class");
2741 PyErr_SetString(PyExc_Exception, err.c_str());
2751 return extracted_parameters_py;
2768 PyObject* qgd_circuit = PyImport_ImportModule(
"squander.gates.qgd_Circuit");
2770 if ( qgd_circuit == NULL ) {
2771 PyErr_SetString(PyExc_Exception,
"Module import error: squander.gates.qgd_Circuit" );
2775 PyObject* qgd_circuit_Dict = PyModule_GetDict( qgd_circuit );
2778 PyObject* py_circuit_class = PyDict_GetItemString( qgd_circuit_Dict,
"qgd_Circuit");
2781 if ( qbit_num_py == NULL ) {
2782 Py_DECREF( qgd_circuit );
2786 PyObject* circuit_input =
Py_BuildValue(
"(O)", qbit_num_py);
2787 Py_DECREF( qbit_num_py );
2788 if ( circuit_input == NULL ) {
2789 Py_DECREF( qgd_circuit );
2792 PyObject* py_circuit = PyObject_CallObject(py_circuit_class, circuit_input);
2796 delete( py_circuit_C->
circuit );
2797 py_circuit_C->
circuit = flat_circuit;
2800 Py_DECREF( qgd_circuit );
2801 Py_DECREF( circuit_input );
2819 int op_num =
self->circuit->get_gate_num();
2822 PyObject* ret = PyTuple_New( (Py_ssize_t) op_num+1 );
2828 PyObject* qbit_num_dict = PyDict_New();
2830 if( qbit_num_dict == NULL ) {
2831 std::string err(
"Failed to create dictionary");
2832 PyErr_SetString(PyExc_Exception, err.c_str());
2836 int qbit_num =
self->circuit->get_qbit_num();
2838 if (qbit_num_val == NULL || PyDict_SetItemString(qbit_num_dict,
"qbit_num", qbit_num_val) != 0) {
2839 Py_XDECREF(qbit_num_val);
2840 Py_DECREF(qbit_num_dict);
2845 PyTuple_SetItem( ret, 0, qbit_num_dict );
2847 Py_DECREF( qbit_num_val );
2850 PyObject* method_name = PyUnicode_FromString(
"__getstate__");
2851 if (method_name == NULL) {
2856 PyObject* qbit_num_key = PyUnicode_FromString(
"qbit_num");
2857 if (qbit_num_key == NULL) {
2858 Py_DECREF(method_name);
2864 for (
int idx = 0; idx < op_num; idx++ ) {
2869 Py_DECREF(qbit_num_key);
2870 Py_DECREF(method_name);
2875 PyObject* gate_state = PyObject_CallMethodObjArgs( gate, method_name, NULL );
2876 if (gate_state == NULL) {
2878 Py_DECREF(qbit_num_key);
2879 Py_DECREF(method_name);
2886 if ( PyDict_Contains(gate_state, qbit_num_key) == 1 ) {
2888 if ( PyDict_DelItem(gate_state, qbit_num_key) != 0 ) {
2889 std::string err(
"Failed to delete item qbit_num from gate state");
2890 PyErr_SetString(PyExc_Exception, err.c_str());
2891 Py_DECREF(gate_state);
2893 Py_DECREF(qbit_num_key);
2894 Py_DECREF(method_name);
2903 PyTuple_SetItem( ret, (Py_ssize_t) idx+1, gate_state );
2912 Py_DECREF( qbit_num_key );
2913 Py_DECREF( method_name );
2929 PyObject*
state = NULL;
2932 if (!PyArg_ParseTuple(args,
"|O", &state )) {
2933 std::string err(
"Unable to parse state argument");
2934 PyErr_SetString(PyExc_Exception, err.c_str());
2938 if ( PyTuple_Size(state) == 0 ) {
2939 std::string err(
"State should contain at least one element");
2940 PyErr_SetString(PyExc_Exception, err.c_str());
2944 PyObject* qbit_num_dict = PyTuple_GetItem( state, 0);
2949 if ( PyDict_Contains(qbit_num_dict, qbit_num_key) == 0 ) {
2950 std::string err(
"The first entry of the circuit state should be the number of qubits");
2951 PyErr_SetString(PyExc_Exception, err.c_str());
2953 Py_DECREF( qbit_num_key );
2957 PyObject* qbit_num_py = PyDict_GetItem(qbit_num_dict, qbit_num_key);
2959 if( !PyLong_Check(qbit_num_py) ) {
2960 std::string err(
"The number of qubits should be an integer value");
2961 PyErr_SetString(PyExc_Exception, err.c_str());
2963 Py_DECREF( qbit_num_key );
2972 PyObject* qgd_gate = PyImport_ImportModule(
"squander.gates.gates_Wrapper");
2974 if ( qgd_gate == NULL ) {
2975 PyErr_SetString(PyExc_Exception,
"Module import error: squander.gates.gates_Wrapper" );
2976 Py_DECREF( qbit_num_key );
2980 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2981 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"Gate");
2982 PyObject* setstate_name =
Py_BuildValue(
"s",
"__setstate__" );
2988 self->circuit->release_gates();
2989 self->circuit->set_qbit_num( qbit_num );
2991 int gates_idx_max = (
int) PyTuple_Size(state);
2993 for(
int gate_idx=1; gate_idx < gates_idx_max; gate_idx++ ) {
2997 PyObject* gate_state_dict = PyTuple_GetItem( state, gate_idx);
2999 if( !PyDict_Check( gate_state_dict ) ) {
3000 std::string err(
"Gate state should be given by a dictionary");
3001 PyErr_SetString(PyExc_Exception, err.c_str());
3003 Py_DECREF( qgd_gate );
3004 Py_DECREF( qbit_num_key );
3005 Py_DECREF( setstate_name );
3006 Py_DECREF( dummy_target_qbit );
3010 PyDict_SetItem(gate_state_dict, qbit_num_key, qbit_num_py);
3013 PyObject* py_gate = PyObject_CallObject(py_gate_class, gate_input);
3014 if (py_gate == NULL) {
3015 Py_DECREF(gate_input);
3016 Py_DECREF( qgd_gate );
3017 Py_DECREF( qbit_num_key );
3018 Py_DECREF( setstate_name );
3019 Py_DECREF( dummy_target_qbit );
3024 PyObject* setstate_ret = PyObject_CallMethodObjArgs( py_gate, setstate_name, gate_state_dict, NULL );
3025 if (setstate_ret == NULL) {
3026 Py_DECREF( gate_input );
3027 Py_DECREF( py_gate );
3028 Py_DECREF( qgd_gate );
3029 Py_DECREF( qbit_num_key );
3030 Py_DECREF( setstate_name );
3031 Py_DECREF( dummy_target_qbit );
3034 Py_DECREF(setstate_ret);
3036 Gate* gate_loc =
static_cast<Gate*
>( ((
qgd_Gate*)py_gate)->gate->clone() );
3037 self->circuit->add_gate( gate_loc );
3040 Py_DECREF( gate_input );
3041 Py_DECREF( py_gate );
3049 catch (std::string err) {
3050 Py_DECREF( qgd_gate );
3051 Py_DECREF( qbit_num_key );
3052 Py_DECREF( setstate_name );
3053 Py_DECREF( dummy_target_qbit );
3054 PyErr_SetString(PyExc_Exception, err.c_str());
3058 Py_DECREF( qgd_gate );
3059 Py_DECREF( qbit_num_key );
3060 Py_DECREF( setstate_name );
3061 Py_DECREF( dummy_target_qbit );
3062 std::string err(
"Invalid pointer to circuit class");
3063 PyErr_SetString(PyExc_Exception, err.c_str());
3070 Py_DECREF( qgd_gate );
3072 Py_DECREF( qbit_num_key );
3073 Py_DECREF( setstate_name );
3074 Py_DECREF( dummy_target_qbit );
3090 int start_index =
self->circuit->get_parameter_start_idx();
3098 {
"add_U1", (PyCFunction) qgd_Circuit_Wrapper_add_U1, METH_VARARGS | METH_KEYWORDS,
3099 "Call to add a U1 gate to the front of the gate structure" 3101 {
"add_U2", (PyCFunction) qgd_Circuit_Wrapper_add_U2, METH_VARARGS | METH_KEYWORDS,
3102 "Call to add a U2 gate to the front of the gate structure" 3104 {
"add_U3", (PyCFunction) qgd_Circuit_Wrapper_add_U3, METH_VARARGS | METH_KEYWORDS,
3105 "Call to add a U3 gate to the front of the gate structure" 3107 {
"add_RX", (PyCFunction) qgd_Circuit_Wrapper_add_RX, METH_VARARGS | METH_KEYWORDS,
3108 "Call to add a RX gate to the front of the gate structure" 3111 "Call to add a RXX gate to the front of the gate structure" 3114 "Call to add a RYY gate to the front of the gate structure" 3117 "Call to add a RZZ gate to the front of the gate structure" 3119 {
"add_R", (PyCFunction) qgd_Circuit_Wrapper_add_R, METH_VARARGS | METH_KEYWORDS,
3120 "Call to add a R gate to the front of the gate structure" 3122 {
"add_RY", (PyCFunction) qgd_Circuit_Wrapper_add_RY, METH_VARARGS | METH_KEYWORDS,
3123 "Call to add a RY gate to the front of the gate structure" 3125 {
"add_RZ", (PyCFunction) qgd_Circuit_Wrapper_add_RZ, METH_VARARGS | METH_KEYWORDS,
3126 "Call to add a RZ gate to the front of the gate structure" 3128 {
"add_CNOT", (PyCFunction) qgd_Circuit_Wrapper_add_CNOT, METH_VARARGS | METH_KEYWORDS,
3129 "Call to add a CNOT gate to the front of the gate structure" 3131 {
"add_CZ", (PyCFunction) qgd_Circuit_Wrapper_add_CZ, METH_VARARGS | METH_KEYWORDS,
3132 "Call to add a CZ gate to the front of the gate structure" 3134 {
"add_CU", (PyCFunction) qgd_Circuit_Wrapper_add_CU, METH_VARARGS | METH_KEYWORDS,
3135 "Call to add a CU gate to the front of the gate structure" 3137 {
"add_CH", (PyCFunction) qgd_Circuit_Wrapper_add_CH, METH_VARARGS | METH_KEYWORDS,
3138 "Call to add a CH gate to the front of the gate structure" 3140 {
"add_SYC", (PyCFunction) qgd_Circuit_Wrapper_add_SYC, METH_VARARGS | METH_KEYWORDS,
3141 "Call to add a Sycamore gate to the front of the gate structure" 3143 {
"add_H", (PyCFunction) qgd_Circuit_Wrapper_add_H, METH_VARARGS | METH_KEYWORDS,
3144 "Call to add a Hadamard gate to the front of the gate structure" 3146 {
"add_X", (PyCFunction) qgd_Circuit_Wrapper_add_X, METH_VARARGS | METH_KEYWORDS,
3147 "Call to add a X gate to the front of the gate structure" 3149 {
"add_Y", (PyCFunction) qgd_Circuit_Wrapper_add_Y, METH_VARARGS | METH_KEYWORDS,
3150 "Call to add a Y gate to the front of the gate structure" 3152 {
"add_Z", (PyCFunction) qgd_Circuit_Wrapper_add_Z, METH_VARARGS | METH_KEYWORDS,
3153 "Call to add a Z gate to the front of the gate structure" 3155 {
"add_SX", (PyCFunction) qgd_Circuit_Wrapper_add_SX, METH_VARARGS | METH_KEYWORDS,
3156 "Call to add a SX gate to the front of the gate structure" 3158 {
"add_SXdg", (PyCFunction) qgd_Circuit_Wrapper_add_SXdg, METH_VARARGS | METH_KEYWORDS,
3159 "Call to add a SXdg gate to the front of the gate structure" 3161 {
"add_S", (PyCFunction) qgd_Circuit_Wrapper_add_S, METH_VARARGS | METH_KEYWORDS,
3162 "Call to add a S gate to the front of the gate structure" 3164 {
"add_Sdg", (PyCFunction) qgd_Circuit_Wrapper_add_Sdg, METH_VARARGS | METH_KEYWORDS,
3165 "Call to add a Sdg gate to the front of the gate structure" 3167 {
"add_T", (PyCFunction) qgd_Circuit_Wrapper_add_T, METH_VARARGS | METH_KEYWORDS,
3168 "Call to add a T gate to the front of the gate structure" 3170 {
"add_Tdg", (PyCFunction) qgd_Circuit_Wrapper_add_Tdg, METH_VARARGS | METH_KEYWORDS,
3171 "Call to add a Tdg gate to the front of the gate structure" 3173 {
"add_CRY", (PyCFunction) qgd_Circuit_Wrapper_add_CRY, METH_VARARGS | METH_KEYWORDS,
3174 "Call to add a CRY gate to the front of the gate structure" 3176 {
"add_CRX", (PyCFunction) qgd_Circuit_Wrapper_add_CRX, METH_VARARGS | METH_KEYWORDS,
3177 "Call to add a CRY gate to the front of the gate structure" 3179 {
"add_CRZ", (PyCFunction) qgd_Circuit_Wrapper_add_CRZ, METH_VARARGS | METH_KEYWORDS,
3180 "Call to add a CRY gate to the front of the gate structure" 3182 {
"add_CP", (PyCFunction) qgd_Circuit_Wrapper_add_CP, METH_VARARGS | METH_KEYWORDS,
3183 "Call to add a CRY gate to the front of the gate structure" 3186 "Call to add a CCX gate to the front of the gate structure" 3188 {
"add_SWAP", (PyCFunction) qgd_Circuit_Wrapper_add_SWAP, METH_VARARGS | METH_KEYWORDS,
3189 "Call to add a SWAP gate to the front of the gate structure" 3192 "Call to add a CSWAP gate to the front of the gate structure" 3194 {
"add_CROT", (PyCFunction) qgd_Circuit_Wrapper_add_CROT, METH_VARARGS | METH_KEYWORDS,
3195 "Call to add a CROT gate to the front of the gate structure" 3197 {
"add_CR", (PyCFunction) qgd_Circuit_Wrapper_add_CR, METH_VARARGS | METH_KEYWORDS,
3198 "Call to add a CR gate to the front of the gate structure" 3200 {
"add_adaptive", (PyCFunction) qgd_Circuit_Wrapper_add_adaptive, METH_VARARGS | METH_KEYWORDS,
3201 "Call to add an adaptive gate to the front of the gate structure" 3204 "Call to add a block of operations to the front of the gate structure." 3207 "Call to add a GENERAL_OPERATION gate from an explicit matrix." 3210 {
"convert_to_DFE_gates_with_derivates", (PyCFunction) qgd_Circuit_Wrapper_convert_to_DFE_gates_with_derivates, METH_VARARGS,
3211 "Call to convert to DFE gates with derivates." 3213 {
"adjust_parameters_for_derivation", (PyCFunction) qgd_Circuit_Wrapper_adjust_parameters_for_derivation, METH_VARARGS,
3214 "Call to adjust parameters for derivation." 3216 {
"convert_to_DFE_gates", (PyCFunction) qgd_Circuit_Wrapper_convert_to_DFE_gates, METH_VARARGS,
3217 "Call to convert to DFE gates." 3219 {
"convert_to_DFE_gates", (PyCFunction) qgd_Circuit_Wrapper_convert_to_DFE_gates, METH_VARARGS,
3220 "Call to convert to DFE gates." 3224 "Method to get the matrix of the operation." 3227 "Call to get the number of free parameters in the circuit" 3230 "Call to apply the gate on the input matrix (or state). Keyword is_f32=True selects float32/complex64 path." 3233 "Call to apply the gate from the right on the input matrix. Keyword is_f32=True selects float32/complex64 path." 3236 "Call to apply the circuit on a list of input matrices (float64/complex128 only)." 3239 "Call to evaluate the derivative of the circuit on an input matrix. Returns a list of derivative matrices." 3242 "Call to evaluate forward action and derivatives of the circuit on an input matrix. Returns [forward, derivatives...]." 3245 "Wrapper function to evaluate the second Rényi entropy of a quantum circuit at a specific parameter set." 3248 "Call to get the number of qubits in the circuit" 3251 "Call to set the number of qubits in the circuit" 3254 "Call to get the list of qubits involved in the circuit" 3257 "Call to set the min fusion in the circuit" 3260 "Call to remap the qubits in the circuit." 3263 "Method to get the i-th decomposing gates." 3266 "Method to get the tuple of decomposing gates." 3269 "Method to get statistics on the gate counts in the circuit." 3272 "Call to get the starting index of the parameters in the parameter array corresponding to the circuit in which the current gate is incorporated." 3275 "Call to extract the parameters corresponding to the gate from a parameter array associated with the circuit in which the gate is embedded." 3278 "Method to generate a flat circuit. A flat circuit does not contain subcircuits: there are no Gates_block instances (containing subcircuits) in the resulting circuit. If the original circuit contains subcircuits, the gates in the subcircuits are directly incorporated in the resulting flat circuit." 3281 "Method to get the list of parent gate indices. Then the parent gates can be obtained from the list of gates involved in the circuit." 3284 "Method to get the list of child gate indices. Then the children gates can be obtained from the list of gates involved in the circuit." 3287 "Method to extract the stored quantum circuit in a human-readable data serialized and pickle-able format." 3290 "Call to set the state of a quantum circuit from a human-readable data serialized and pickle-able format." 3302 PyVarObject_HEAD_INIT(NULL, 0)
3303 "qgd_Circuit_Wrapper.qgd_Circuit_Wrapper",
3307 #if PY_VERSION_HEX < 0x030800b4 3310 #if PY_VERSION_HEX >= 0x030800b4 3315 #if PY_MAJOR_VERSION < 3 3318 #if PY_MAJOR_VERSION >= 3 3331 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
3332 "Object to represent a qgd_Circuit_Wrapper class of the QGD package.",
3359 #
if PY_VERSION_HEX >= 0x030400a1
3362 #
if PY_VERSION_HEX >= 0x030800b1
3365 #
if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000
3374 PyModuleDef_HEAD_INIT,
3375 "qgd_Circuit_Wrapper",
3376 "Python binding for QGD Circuit class",
3391 if (PyType_Ready(&qgd_Circuit_Wrapper_Type) < 0)
3394 m = PyModule_Create(&qgd_Circuit_Wrapper_Module);
3398 Py_INCREF(&qgd_Circuit_Wrapper_Type);
3399 if (PyModule_AddObject(m,
"qgd_Circuit_Wrapper", (PyObject *) &qgd_Circuit_Wrapper_Type) < 0) {
3400 Py_DECREF(&qgd_Circuit_Wrapper_Type);
static PyObject * qgd_Circuit_Wrapper_set_Min_Fusion(qgd_Circuit_Wrapper *self, PyObject *args)
static PyObject * qgd_Circuit_Wrapper_get_Parameter_Num(qgd_Circuit_Wrapper *self)
Get the number of free parameters in the gate structure used for the decomposition.
Gates_block * get_flat_circuit()
Method to generate a flat circuit.
Copyright (C) Miklos Maroti, 2021 SPDX-License-Identifier: Apache-2.0.
PyMODINIT_FUNC PyInit_qgd_Circuit_Wrapper(void)
Method called when the Python module is initialized.
static PyObject * qgd_Circuit_Wrapper_apply_derivate_to(qgd_Circuit_Wrapper *self, PyObject *args, PyObject *kwds)
Evaluate the derivative of the circuit on an input matrix with respect to all free parameters (float6...
Header file for a class representing a CSWAP (Controlled SWAP) operation.
static PyObject * qgd_Circuit_Wrapper_get_Parameter_Start_Index(qgd_Circuit_Wrapper *self)
Call to get the starting index of the parameters in the parameter array corresponding to the circuit ...
Header file for a class representing a CP gate.
parameter_num
[set adaptive gate structure]
Class to store single-precision real arrays and properties.
PyObject_HEAD Gate * gate
Pointer to the C++ class of the base Gate gate.
static PyObject * qgd_Circuit_Wrapper_get_parents(qgd_Circuit_Wrapper *self, PyObject *args)
Wrapper function to get the indices of parent gates.
Header file for a class representing a controlled Z rotation gate.
A class representing a controlled RX gate.
A class representing a CP gate.
#define qgd_Circuit_Wrapper_add_two_qubit_gate(gate_name, GATE_NAME)
static PyObject * qgd_Circuit_Wrapper_get_Qbits(qgd_Circuit_Wrapper *self)
Call to retrieve the list of qubits involved in the circuit.
static PyObject * qgd_Circuit_Wrapper_get_gates(qgd_Circuit_Wrapper *self)
Call to get the incorporated gates in a Python list.
#define qgd_Circuit_Wrapper_add_one_qubit_gate(gate_name, GATE_NAME)
#define get_gate_template_one_qubit(GATE_NAME)
virtual Gate * clone()
Call to create a clone of the present class.
void add_gate(Gate *gate)
Append a general gate to the list of gates.
Matrix to_float64() const
Convert to double precision.
Header file for a class representing a controlled rotation gate around the Y axis.
return Py_BuildValue("i", 0)
static PyObject * get_gate(Gates_block *circuit, int &idx)
Call to get the metadata organized into Python dictionary of the idx-th gate.
Matrix_real numpy2matrix_real(PyArrayObject *arr)
Call to create a PIC matrix_real representation of a numpy array.
static int qgd_Circuit_Wrapper_init(qgd_Circuit_Wrapper *self, PyObject *args, PyObject *kwds)
Method called when a python instance of the class qgd_Circuit_Wrapper is initialized.
static PyObject * qgd_Circuit_Wrapper_get_Gate_Nums(qgd_Circuit_Wrapper *self)
Call to get the counts of individual gates in the circuit.
static PyObject * qgd_Circuit_Wrapper_get_Qbit_Num(qgd_Circuit_Wrapper *self)
Call to retrieve the number of qubits in the circuit.
static PyObject * qgd_Circuit_Wrapper_get_children(qgd_Circuit_Wrapper *self, PyObject *args)
Wrapper function to get the indices of children gates.
Structure type representing single-precision complex numbers.
Header file for a class representing a controlled rotation gate around the Y axis.
scalar * data
pointer to the stored data
Gates_block * create_remapped_circuit(const std::map< int, int > &qbit_map)
Call to create a new circuit with remapped qubits.
Header file for a class representing a CH operation.
Header file for a class representing a controlled X rotation gate.
Header file for a class representing a SWAP operation.
Type definition of the qgd_Gate Python class of the qgd_Gate module.
Header file for a class responsible for grouping gates into subcircuits. (Subcircuits can be nested) ...
PyObject * matrix_real_to_numpy(Matrix_real &mtx)
Call to make a numpy array from an instance of matrix class.
virtual Gates_block * clone() override
Create a clone of the present class.
static PyObject * qgd_Circuit_Wrapper_Remap_Qbits(qgd_Circuit_Wrapper *self, PyObject *args)
Call to remap the qubits in the circuit.
U3 RX RZ H Y SX S T CNOT CH SYC CRZ PyObject PyObject * kwds
Matrix_real_float numpy2matrix_real_float(PyArrayObject *arr)
Call to create a PIC matrix_real_float representation of a numpy array.
void release_Circuit(Gates_block *instance)
Call to deallocate an instance of Gates_block class.
Header file for a class representing a CCX (Toffoli) operation.
scalar * get_data() const
Call to get the pointer to the stored data.
static PyTypeObject qgd_Circuit_Wrapper_Type
A structure describing the type of the class Circuit.
static PyObject * qgd_Circuit_Wrapper_add_CSWAP(qgd_Circuit_Wrapper *self, PyObject *args, PyObject *kwds)
Wrapper function to add a CSWAP gate to the front of the gate structure.
Class representing a RZZ gate.
static PyMemberDef qgd_Circuit_Wrapper_Members[]
Structure containing metadata about the members of class qgd_Circuit_Wrapper.
A class representing a CROT gate.
static PyObject * qgd_Circuit_Wrapper_apply_to(qgd_Circuit_Wrapper *self, PyObject *args, PyObject *kwds)
Apply the gate circuit operation on the input matrix.
A class representing a CZ operation.
Header file for a class representing a CNOT operation.
A class representing a CRY gate.
static void circuit_matrix_owner_capsule_destruct(PyObject *cap)
Capsule destructor: calls delete on a heap-allocated Matrix, which correctly decrements the reference...
U3 RX RZ H Y SX S T CNOT CH SYC CRZ PyObject * args
std::vector< int > get_control_qbits() const
Call to get the vector of control qubits.
int rows
The number of rows.
A class representing a CH operation.
int cols
The number of columns.
static PyObject * qgd_Circuit_Wrapper_setstate(qgd_Circuit_Wrapper *self, PyObject *args)
Call to set the state of a quantum circuit from a human-readable data serialized and pickle-able form...
PyObject_HEAD Gates_block * gate
static PyObject * qgd_Circuit_Wrapper_add_Circuit(qgd_Circuit_Wrapper *self, PyObject *args)
Wrapper function to add a block of operations to the front of the gate structure. ...
static PyObject * qgd_Circuit_Wrapper_add_GENERAL(qgd_Circuit_Wrapper *self, PyObject *args, PyObject *kwds)
Wrapper function to add a GENERAL_OPERATION gate from an explicit matrix.
gate_type get_type()
Call to get the type of the operation.
static PyObject * qgd_Circuit_Wrapper_set_Qbit_Num(qgd_Circuit_Wrapper *self, PyObject *args)
Call to set the number of qubits in the circuit.
static PyObject * qgd_Circuit_Wrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Method called when a python instance of the class qgd_Circuit_Wrapper is allocated.
static PyObject * qgd_Circuit_Wrapper_get_Second_Renyi_Entropy(qgd_Circuit_Wrapper *self, PyObject *args)
Wrapper function to evaluate the second Rényi entropy of a quantum circuit at a specific parameter s...
std::vector< Gate * > get_parents()
Call to get the parents of the current gate.
static PyObject * qgd_Circuit_Wrapper_get_Flat_Circuit(qgd_Circuit_Wrapper *self)
Method to generate a flat circuit.
static PyObject * qgd_Circuit_Wrapper_get_gate(qgd_Circuit_Wrapper *self, PyObject *args)
Wrapper function to get a gate from the circuit.
Header file for a class representing a CZ operation.
static void circuit_matrix_float_owner_capsule_destruct(PyObject *cap)
Capsule destructor: calls delete on a heap-allocated Matrix_float, which correctly decrements the ref...
void set_owner(bool owner_in)
Call to set the current class instance to be (or not to be) the owner of the stored data array...
Structure type representing complex numbers in the SQUANDER package.
A class representing a CNOT operation.
static void qgd_Circuit_Wrapper_dealloc(qgd_Circuit_Wrapper *self)
Method called when a python instance of the class qgd_Circuit_Wrapper is destroyed.
static PyObject * qgd_Circuit_Wrapper_apply_to_list(qgd_Circuit_Wrapper *self, PyObject *args, PyObject *kwds)
Apply the circuit to a list of input matrices with float32/float64 dispatch.
static PyMethodDef qgd_Circuit_Wrapper_Methods[]
std::vector< Gate * > get_children()
Call to get the children of the current gate.
std::vector< int > get_target_qbits() const
Call to get the vector of target qubits.
Double-precision complex matrix (float64).
Header file for a class representing a gate used in adaptive decomposition.
int size() const
Call to get the number of the allocated elements.
Matrix_float numpy2matrix_float(PyArrayObject *arr)
Call to create a PIC matrix_float representation of a numpy array.
A class representing a controlled RZ gate.
A class representing a CRY gate.
A class responsible for grouping two-qubit (CNOT,CZ,CH) and one-qubit gates into layers.
static PyObject * qgd_Circuit_Wrapper_Extract_Parameters(qgd_Circuit_Wrapper *self, PyObject *args)
Call to extract the parameters corresponding to the gate from a parameter array associated with the c...
Single-precision complex matrix (float32).
Fixed point data related to a gate operation.
int get_target_qbit()
Call to get the index of the target qubit.
Base class for the representation of general gate operations.
static PyModuleDef qgd_Circuit_Wrapper_Module
Structure containing metadata about the module.
PyObject * matrix_float_to_numpy(Matrix_float &mtx)
Call to make a numpy array from an instance of matrix_float class.
Header file for a class representing a controlled rotation gate around the Y axis.
Matrix numpy2matrix(PyArrayObject *arr)
Call to create a PIC matrix representation of a numpy array.
static PyObject * qgd_Circuit_Wrapper_getstate(qgd_Circuit_Wrapper *self)
Method to extract the stored quantum circuit in a human-readable data serialized and pickle-able form...
PyObject_HEAD Gates_block * circuit
Pointer to the C++ class of the base Gate_block module.
static PyObject * qgd_Circuit_Wrapper_add_RXX(qgd_Circuit_Wrapper *self, PyObject *args, PyObject *kwds)
static PyObject * qgd_Circuit_Wrapper_add_RZZ(qgd_Circuit_Wrapper *self, PyObject *args, PyObject *kwds)
A class representing a SYC operation.
int get_qbit_num()
Call to get the number of qubits composing the unitary.
gate_type
Type definition of operation types (also generalized for decomposition classes derived from the class...
Type definition for qgd_Circuit_Wrapper.
Gate * get_gate(int idx)
Call to get the gates stored in the class.
Gates_block * create_Circuit(int qbit_num)
Creates an instance of class Gates_block (Circuit) and returns a pointer to the class instance...
#define get_gate_template_two_qubit(GATE_NAME)
static PyObject * qgd_Circuit_Wrapper_apply_from_right(qgd_Circuit_Wrapper *self, PyObject *args, PyObject *kwds)
Apply the gate circuit from the right on the input matrix with float32/float64 dispatch.
static PyObject * qgd_Circuit_Wrapper_add_RYY(qgd_Circuit_Wrapper *self, PyObject *args, PyObject *kwds)
PyObject * matrix_to_numpy(Matrix &mtx)
Call to make a numpy array from an instance of matrix class.
static PyObject * qgd_Circuit_Wrapper_get_Matrix(qgd_Circuit_Wrapper *self, PyObject *args, PyObject *kwds)
Extract the optimized parameters and return the matrix representation of the gate circuit...
static PyObject * qgd_Circuit_Wrapper_apply_to_combined(qgd_Circuit_Wrapper *self, PyObject *args, PyObject *kwds)
Evaluate forward circuit action and all derivatives in one call.
int get_control_qbit()
Call to get the index of the control qubit.
PyObject * target_qbits_py
Class to store data of complex arrays and its properties.
Class representing a RYY gate.
CR static adaptive PyObject * qgd_Circuit_Wrapper_add_CCX(qgd_Circuit_Wrapper *self, PyObject *args, PyObject *kwds)
Wrapper function to add a CCX gate to the front of the gate structure.
Header file for a class representing a Sycamore gate.