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++) {
647 PyObject*
gate =
Py_BuildValue(
"iiibbbb", DFEgates[i].ThetaOver2, DFEgates[i].Phi,
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" );
2133 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2135 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"CNOT");
2137 PyObject* gate_input =
Py_BuildValue(
"(OOO)", qbit_num, target_qbit, control_qbit);
2138 py_gate = PyObject_CallObject(py_gate_class, gate_input);
2142 delete( py_gate_C->
gate );
2145 Py_DECREF( qgd_gate );
2146 Py_DECREF( gate_input );
2161 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2162 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"CRY");
2163 PyObject* gate_input =
Py_BuildValue(
"(OOO)", qbit_num, target_qbit, control_qbit);
2164 py_gate = PyObject_CallObject(py_gate_class, gate_input);
2166 delete( py_gate_C->
gate );
2172 PyObject* target_qbits_list = PyList_New((Py_ssize_t)target_qbits_vec.size());
2173 for (
size_t i = 0; i < target_qbits_vec.size(); i++) {
2174 PyList_SetItem(target_qbits_list, (Py_ssize_t)i,
Py_BuildValue(
"i", target_qbits_vec[i]));
2177 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2178 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"SWAP");
2180 PyObject* gate_input =
Py_BuildValue(
"(OO)", qbit_num, target_qbits_list);
2181 py_gate = PyObject_CallObject(py_gate_class, gate_input);
2185 delete( py_gate_C->
gate );
2188 Py_DECREF( qgd_gate );
2189 Py_DECREF( gate_input );
2190 Py_DECREF( target_qbits_list );
2196 PyObject* target_qbits_list = PyList_New((Py_ssize_t)target_qbits_vec.size());
2197 for (
size_t i = 0; i < target_qbits_vec.size(); i++) {
2198 PyList_SetItem(target_qbits_list, (Py_ssize_t)i,
Py_BuildValue(
"i", target_qbits_vec[i]));
2201 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2202 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"RXX");
2204 PyObject* gate_input =
Py_BuildValue(
"(OO)", qbit_num, target_qbits_list);
2205 py_gate = PyObject_CallObject(py_gate_class, gate_input);
2209 delete( py_gate_C->
gate );
2212 Py_DECREF( qgd_gate );
2213 Py_DECREF( gate_input );
2214 Py_DECREF( target_qbits_list );
2220 PyObject* target_qbits_list = PyList_New((Py_ssize_t)target_qbits_vec.size());
2221 for (
size_t i = 0; i < target_qbits_vec.size(); i++) {
2222 PyList_SetItem(target_qbits_list, (Py_ssize_t)i,
Py_BuildValue(
"i", target_qbits_vec[i]));
2225 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2226 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"RYY");
2228 PyObject* gate_input =
Py_BuildValue(
"(OO)", qbit_num, target_qbits_list);
2229 py_gate = PyObject_CallObject(py_gate_class, gate_input);
2233 delete( py_gate_C->
gate );
2236 Py_DECREF( qgd_gate );
2237 Py_DECREF( gate_input );
2238 Py_DECREF( target_qbits_list );
2244 PyObject* target_qbits_list = PyList_New((Py_ssize_t)target_qbits_vec.size());
2245 for (
size_t i = 0; i < target_qbits_vec.size(); i++) {
2246 PyList_SetItem(target_qbits_list, (Py_ssize_t)i,
Py_BuildValue(
"i", target_qbits_vec[i]));
2249 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2250 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"RZZ");
2252 PyObject* gate_input =
Py_BuildValue(
"(OO)", qbit_num, target_qbits_list);
2253 py_gate = PyObject_CallObject(py_gate_class, gate_input);
2257 delete( py_gate_C->
gate );
2260 Py_DECREF( qgd_gate );
2261 Py_DECREF( gate_input );
2262 Py_DECREF( target_qbits_list );
2282 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2284 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"Sdg");
2286 PyObject* gate_input =
Py_BuildValue(
"(OO)", qbit_num, target_qbit);
2287 py_gate = PyObject_CallObject(py_gate_class, gate_input);
2291 delete( py_gate_C->
gate );
2294 Py_DECREF( qgd_gate );
2295 Py_DECREF( gate_input );
2302 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2304 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"SXdg");
2306 PyObject* gate_input =
Py_BuildValue(
"(OO)", qbit_num, target_qbit);
2307 py_gate = PyObject_CallObject(py_gate_class, gate_input);
2311 delete( py_gate_C->
gate );
2314 Py_DECREF( qgd_gate );
2315 Py_DECREF( gate_input );
2322 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2324 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"Tdg");
2326 PyObject* gate_input =
Py_BuildValue(
"(OO)", qbit_num, target_qbit);
2327 py_gate = PyObject_CallObject(py_gate_class, gate_input);
2331 delete( py_gate_C->
gate );
2334 Py_DECREF( qgd_gate );
2335 Py_DECREF( gate_input );
2342 PyObject* control_qbits_list = PyList_New((Py_ssize_t)control_qbits_vec.size());
2343 for (
size_t i = 0; i < control_qbits_vec.size(); i++) {
2344 PyList_SetItem(control_qbits_list, (Py_ssize_t)i,
Py_BuildValue(
"i", control_qbits_vec[i]));
2347 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2349 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"CCX");
2351 PyObject* gate_input =
Py_BuildValue(
"(OOO)", qbit_num, target_qbit, control_qbits_list);
2352 py_gate = PyObject_CallObject(py_gate_class, gate_input);
2356 delete( py_gate_C->
gate );
2359 Py_DECREF( qgd_gate );
2360 Py_DECREF( gate_input );
2361 Py_DECREF( control_qbits_list );
2363 Py_XDECREF(qbit_num);
2364 Py_XDECREF(target_qbit);
2365 Py_XDECREF(control_qbit);
2373 PyObject* target_qbits_list = PyList_New((Py_ssize_t)target_qbits_vec.size());
2374 for (
size_t i = 0; i < target_qbits_vec.size(); i++) {
2375 PyList_SetItem(target_qbits_list, (Py_ssize_t)i,
Py_BuildValue(
"i", target_qbits_vec[i]));
2379 PyObject* control_qbits_list = PyList_New((Py_ssize_t)control_qbits_vec.size());
2380 for (
size_t i = 0; i < control_qbits_vec.size(); i++) {
2381 PyList_SetItem(control_qbits_list, (Py_ssize_t)i,
Py_BuildValue(
"i", control_qbits_vec[i]));
2384 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
2386 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"CSWAP");
2388 PyObject* gate_input =
Py_BuildValue(
"(OOO)", qbit_num, target_qbits_list, control_qbits_list);
2389 py_gate = PyObject_CallObject(py_gate_class, gate_input);
2393 delete( py_gate_C->
gate );
2396 Py_DECREF( qgd_gate );
2397 Py_DECREF( gate_input );
2398 Py_DECREF( target_qbits_list );
2399 Py_DECREF( control_qbits_list );
2401 Py_XDECREF(qbit_num);
2402 Py_XDECREF(target_qbit);
2403 Py_XDECREF(control_qbit);
2411 PyObject* qgd_circuit = PyImport_ImportModule(
"squander.gates.qgd_Circuit");
2413 if ( qgd_circuit == NULL ) {
2414 PyErr_SetString(PyExc_Exception,
"Module import error: squander.gates.qgd_Circuit" );
2418 PyObject* qgd_circuit_Dict = PyModule_GetDict( qgd_circuit );
2421 PyObject* py_circuit_class = PyDict_GetItemString( qgd_circuit_Dict,
"qgd_Circuit");
2424 py_gate = PyObject_CallObject(py_circuit_class, circuit_input);
2433 Py_DECREF( qgd_circuit );
2434 Py_DECREF( circuit_input );
2439 Py_DECREF( qgd_gate );
2440 Py_XDECREF(qbit_num);
2441 Py_XDECREF(target_qbit);
2442 Py_XDECREF(control_qbit);
2443 PyErr_SetString(PyExc_Exception,
"qgd_Circuit_Wrapper::get_gate: unimplemented gate type" );
2447 Py_XDECREF(qbit_num);
2448 Py_XDECREF(target_qbit);
2449 Py_XDECREF(control_qbit);
2470 if (!PyArg_ParseTuple(args,
"|i", &idx ))
return Py_BuildValue(
"i", -1);
2473 return get_gate( self->circuit, idx );
2487 std::map< std::string, int > gate_nums;
2490 gate_nums =
self->circuit->get_gate_nums();
2492 catch (std::string err) {
2493 PyErr_SetString(PyExc_Exception, err.c_str());
2497 std::string err(
"Invalid pointer to circuit class");
2498 PyErr_SetString(PyExc_Exception, err.c_str());
2503 PyObject* gate_nums_py = PyDict_New();
2504 if( gate_nums_py == NULL ) {
2505 std::string err(
"Failed to create dictionary");
2506 PyErr_SetString(PyExc_Exception, err.c_str());
2510 for(
auto it = gate_nums.begin(); it != gate_nums.end(); it++ ) {
2515 if ( key == NULL || val == NULL ) {
2518 Py_DECREF(gate_nums_py);
2522 if ( PyDict_SetItem(gate_nums_py, key, val) != 0 ) {
2525 Py_DECREF(gate_nums_py);
2533 return gate_nums_py;
2552 int op_num =
self->circuit->get_gate_num();
2555 PyObject* ret = PyTuple_New( (Py_ssize_t) op_num );
2560 for (
int idx = 0; idx < op_num; idx++ ) {
2566 PyTuple_SetItem( ret, (Py_ssize_t) idx, gate );
2587 PyObject* py_gate = NULL;
2590 if (!PyArg_ParseTuple(args,
"|O", &py_gate ))
return Py_BuildValue(
"i", -1);
2593 if( py_gate == NULL ) {
2594 return PyTuple_New( 0 );
2601 PyObject* parent_tuple = PyTuple_New( (Py_ssize_t) parents.size() );
2603 std::vector<Gate*>&& gates =
self->circuit->get_gates();
2607 for(
size_t idx=0; idx<parents.size(); idx++) {
2609 Gate* parent_gate = parents[idx];
2612 int parent_idx = -1;
2613 for(
size_t jdx=0; jdx<gates.size(); jdx++ ) {
2617 if( parent_gate == gate ) {
2618 parent_idx =
static_cast<int>(jdx);
2622 if( jdx == static_cast<size_t>(gates.size()-1) ) {
2623 std::string err(
"Parent gate did not found in the circuit. May be the gate is not in the circuit");
2624 PyErr_SetString(PyExc_Exception, err.c_str());
2631 PyTuple_SetItem( parent_tuple, (Py_ssize_t) idx,
Py_BuildValue(
"i", parent_idx) );
2637 return parent_tuple;
2655 PyObject* py_gate = NULL;
2658 if (!PyArg_ParseTuple(args,
"|O", &py_gate ))
return Py_BuildValue(
"i", -1);
2661 if( py_gate == NULL ) {
2662 return PyTuple_New( 0 );
2669 PyObject* children_tuple = PyTuple_New( (Py_ssize_t) children.size() );
2671 std::vector<Gate*>&& gates =
self->circuit->get_gates();
2675 for(
size_t idx=0; idx<children.size(); idx++) {
2677 Gate* child_gate = children[idx];
2681 for(
size_t jdx=0; jdx<gates.size(); jdx++ ) {
2685 if( child_gate == gate ) {
2686 child_idx =
static_cast<int>(jdx);
2690 if( jdx == static_cast<size_t>(gates.size()-1) ) {
2691 std::string err(
"Child gate did not found in the circuit. May be the gate is not in the circuit");
2692 PyErr_SetString(PyExc_Exception, err.c_str());
2699 PyTuple_SetItem( children_tuple, (Py_ssize_t) idx,
Py_BuildValue(
"i", child_idx) );
2705 return children_tuple;
2721 PyArrayObject * parameters_arr = NULL;
2725 if (!PyArg_ParseTuple(args,
"|O", ¶meters_arr ))
2729 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
2730 Py_INCREF(parameters_arr);
2733 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
2744 extracted_parameters =
self->circuit->extract_parameters( parameters_mtx );
2746 catch (std::string err) {
2747 PyErr_SetString(PyExc_Exception, err.c_str());
2751 std::string err(
"Invalid pointer to circuit class");
2752 PyErr_SetString(PyExc_Exception, err.c_str());
2762 return extracted_parameters_py;
2776 PyObject* filename_py = NULL;
2777 PyObject* parameters_obj = NULL;
2779 if (!PyArg_ParseTuple(args,
"OO", &filename_py, ¶meters_obj)) {
2783 PyObject* filename_string = PyObject_Str(filename_py);
2784 if (filename_string == NULL) {
2787 PyObject* filename_unicode = PyUnicode_AsEncodedString(filename_string,
"utf-8",
"~E~");
2788 Py_DECREF(filename_string);
2789 if (filename_unicode == NULL) {
2792 const char* filename_C = PyBytes_AS_STRING(filename_unicode);
2793 std::string filename_str(filename_C);
2795 PyArrayObject* parameters_arr = NULL;
2796 if ( PyArray_Check(parameters_obj) && PyArray_IS_C_CONTIGUOUS((PyArrayObject*)parameters_obj) &&
2797 PyArray_TYPE((PyArrayObject*)parameters_obj) == NPY_DOUBLE ) {
2798 parameters_arr = (PyArrayObject*)parameters_obj;
2799 Py_INCREF(parameters_arr);
2802 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF(parameters_obj, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
2805 if (parameters_arr == NULL) {
2806 Py_DECREF(filename_unicode);
2807 PyErr_SetString(PyExc_TypeError,
"export_to_Binary: parameters must be a float64 numpy array");
2814 if (parameters_mtx.
size() !=
self->circuit->get_parameter_num()) {
2815 std::string err(
"export_to_Binary: number of parameters (" +
2816 std::to_string(parameters_mtx.
size()) +
2817 ") must equal the number of free parameters in the circuit (" +
2818 std::to_string(self->circuit->get_parameter_num()) +
").");
2823 catch (std::string err) {
2824 Py_DECREF(parameters_arr);
2825 Py_DECREF(filename_unicode);
2826 PyErr_SetString(PyExc_Exception, err.c_str());
2830 Py_DECREF(parameters_arr);
2831 Py_DECREF(filename_unicode);
2832 PyErr_SetString(PyExc_Exception,
"export_to_Binary: failed to export circuit");
2836 Py_DECREF(parameters_arr);
2837 Py_DECREF(filename_unicode);
2855 PyObject* qgd_circuit = PyImport_ImportModule(
"squander.gates.qgd_Circuit");
2857 if ( qgd_circuit == NULL ) {
2858 PyErr_SetString(PyExc_Exception,
"Module import error: squander.gates.qgd_Circuit" );
2862 PyObject* qgd_circuit_Dict = PyModule_GetDict( qgd_circuit );
2865 PyObject* py_circuit_class = PyDict_GetItemString( qgd_circuit_Dict,
"qgd_Circuit");
2868 if ( qbit_num_py == NULL ) {
2869 Py_DECREF( qgd_circuit );
2873 PyObject* circuit_input =
Py_BuildValue(
"(O)", qbit_num_py);
2874 Py_DECREF( qbit_num_py );
2875 if ( circuit_input == NULL ) {
2876 Py_DECREF( qgd_circuit );
2879 PyObject* py_circuit = PyObject_CallObject(py_circuit_class, circuit_input);
2883 delete( py_circuit_C->
circuit );
2884 py_circuit_C->
circuit = flat_circuit;
2887 Py_DECREF( qgd_circuit );
2888 Py_DECREF( circuit_input );
2906 int op_num =
self->circuit->get_gate_num();
2909 PyObject* ret = PyTuple_New( (Py_ssize_t) op_num+1 );
2915 PyObject* qbit_num_dict = PyDict_New();
2917 if( qbit_num_dict == NULL ) {
2918 std::string err(
"Failed to create dictionary");
2919 PyErr_SetString(PyExc_Exception, err.c_str());
2923 int qbit_num =
self->circuit->get_qbit_num();
2925 if (qbit_num_val == NULL || PyDict_SetItemString(qbit_num_dict,
"qbit_num", qbit_num_val) != 0) {
2926 Py_XDECREF(qbit_num_val);
2927 Py_DECREF(qbit_num_dict);
2932 PyTuple_SetItem( ret, 0, qbit_num_dict );
2934 Py_DECREF( qbit_num_val );
2937 PyObject* method_name = PyUnicode_FromString(
"__getstate__");
2938 if (method_name == NULL) {
2943 PyObject* qbit_num_key = PyUnicode_FromString(
"qbit_num");
2944 if (qbit_num_key == NULL) {
2945 Py_DECREF(method_name);
2951 for (
int idx = 0; idx < op_num; idx++ ) {
2956 Py_DECREF(qbit_num_key);
2957 Py_DECREF(method_name);
2962 PyObject* gate_state = PyObject_CallMethodObjArgs( gate, method_name, NULL );
2963 if (gate_state == NULL) {
2965 Py_DECREF(qbit_num_key);
2966 Py_DECREF(method_name);
2973 if ( PyDict_Contains(gate_state, qbit_num_key) == 1 ) {
2975 if ( PyDict_DelItem(gate_state, qbit_num_key) != 0 ) {
2976 std::string err(
"Failed to delete item qbit_num from gate state");
2977 PyErr_SetString(PyExc_Exception, err.c_str());
2978 Py_DECREF(gate_state);
2980 Py_DECREF(qbit_num_key);
2981 Py_DECREF(method_name);
2990 PyTuple_SetItem( ret, (Py_ssize_t) idx+1, gate_state );
2999 Py_DECREF( qbit_num_key );
3000 Py_DECREF( method_name );
3016 PyObject*
state = NULL;
3019 if (!PyArg_ParseTuple(args,
"|O", &state )) {
3020 std::string err(
"Unable to parse state argument");
3021 PyErr_SetString(PyExc_Exception, err.c_str());
3025 if ( PyTuple_Size(state) == 0 ) {
3026 std::string err(
"State should contain at least one element");
3027 PyErr_SetString(PyExc_Exception, err.c_str());
3031 PyObject* qbit_num_dict = PyTuple_GetItem( state, 0);
3036 if ( PyDict_Contains(qbit_num_dict, qbit_num_key) == 0 ) {
3037 std::string err(
"The first entry of the circuit state should be the number of qubits");
3038 PyErr_SetString(PyExc_Exception, err.c_str());
3040 Py_DECREF( qbit_num_key );
3044 PyObject* qbit_num_py = PyDict_GetItem(qbit_num_dict, qbit_num_key);
3046 if( !PyLong_Check(qbit_num_py) ) {
3047 std::string err(
"The number of qubits should be an integer value");
3048 PyErr_SetString(PyExc_Exception, err.c_str());
3050 Py_DECREF( qbit_num_key );
3059 PyObject* qgd_gate = PyImport_ImportModule(
"squander.gates.gates_Wrapper");
3061 if ( qgd_gate == NULL ) {
3062 PyErr_SetString(PyExc_Exception,
"Module import error: squander.gates.gates_Wrapper" );
3063 Py_DECREF( qbit_num_key );
3067 PyObject* qgd_gate_Dict = PyModule_GetDict( qgd_gate );
3068 PyObject* py_gate_class = PyDict_GetItemString( qgd_gate_Dict,
"Gate");
3069 PyObject* setstate_name =
Py_BuildValue(
"s",
"__setstate__" );
3075 self->circuit->release_gates();
3076 self->circuit->set_qbit_num( qbit_num );
3078 int gates_idx_max = (
int) PyTuple_Size(state);
3080 for(
int gate_idx=1; gate_idx < gates_idx_max; gate_idx++ ) {
3084 PyObject* gate_state_dict = PyTuple_GetItem( state, gate_idx);
3086 if( !PyDict_Check( gate_state_dict ) ) {
3087 std::string err(
"Gate state should be given by a dictionary");
3088 PyErr_SetString(PyExc_Exception, err.c_str());
3090 Py_DECREF( qgd_gate );
3091 Py_DECREF( qbit_num_key );
3092 Py_DECREF( setstate_name );
3093 Py_DECREF( dummy_target_qbit );
3097 PyDict_SetItem(gate_state_dict, qbit_num_key, qbit_num_py);
3100 PyObject* py_gate = PyObject_CallObject(py_gate_class, gate_input);
3101 if (py_gate == NULL) {
3102 Py_DECREF(gate_input);
3103 Py_DECREF( qgd_gate );
3104 Py_DECREF( qbit_num_key );
3105 Py_DECREF( setstate_name );
3106 Py_DECREF( dummy_target_qbit );
3111 PyObject* setstate_ret = PyObject_CallMethodObjArgs( py_gate, setstate_name, gate_state_dict, NULL );
3112 if (setstate_ret == NULL) {
3113 Py_DECREF( gate_input );
3114 Py_DECREF( py_gate );
3115 Py_DECREF( qgd_gate );
3116 Py_DECREF( qbit_num_key );
3117 Py_DECREF( setstate_name );
3118 Py_DECREF( dummy_target_qbit );
3121 Py_DECREF(setstate_ret);
3123 Gate* gate_loc =
static_cast<Gate*
>( ((
qgd_Gate*)py_gate)->gate->clone() );
3124 self->circuit->add_gate( gate_loc );
3127 Py_DECREF( gate_input );
3128 Py_DECREF( py_gate );
3136 catch (std::string err) {
3137 Py_DECREF( qgd_gate );
3138 Py_DECREF( qbit_num_key );
3139 Py_DECREF( setstate_name );
3140 Py_DECREF( dummy_target_qbit );
3141 PyErr_SetString(PyExc_Exception, err.c_str());
3145 Py_DECREF( qgd_gate );
3146 Py_DECREF( qbit_num_key );
3147 Py_DECREF( setstate_name );
3148 Py_DECREF( dummy_target_qbit );
3149 std::string err(
"Invalid pointer to circuit class");
3150 PyErr_SetString(PyExc_Exception, err.c_str());
3157 Py_DECREF( qgd_gate );
3159 Py_DECREF( qbit_num_key );
3160 Py_DECREF( setstate_name );
3161 Py_DECREF( dummy_target_qbit );
3177 int start_index =
self->circuit->get_parameter_start_idx();
3185 {
"add_U1", (PyCFunction) qgd_Circuit_Wrapper_add_U1, METH_VARARGS | METH_KEYWORDS,
3186 "Call to add a U1 gate to the front of the gate structure" 3188 {
"add_U2", (PyCFunction) qgd_Circuit_Wrapper_add_U2, METH_VARARGS | METH_KEYWORDS,
3189 "Call to add a U2 gate to the front of the gate structure" 3191 {
"add_U3", (PyCFunction) qgd_Circuit_Wrapper_add_U3, METH_VARARGS | METH_KEYWORDS,
3192 "Call to add a U3 gate to the front of the gate structure" 3194 {
"add_RX", (PyCFunction) qgd_Circuit_Wrapper_add_RX, METH_VARARGS | METH_KEYWORDS,
3195 "Call to add a RX gate to the front of the gate structure" 3198 "Call to add a RXX gate to the front of the gate structure" 3201 "Call to add a RYY gate to the front of the gate structure" 3204 "Call to add a RZZ gate to the front of the gate structure" 3206 {
"add_R", (PyCFunction) qgd_Circuit_Wrapper_add_R, METH_VARARGS | METH_KEYWORDS,
3207 "Call to add a R gate to the front of the gate structure" 3209 {
"add_RY", (PyCFunction) qgd_Circuit_Wrapper_add_RY, METH_VARARGS | METH_KEYWORDS,
3210 "Call to add a RY gate to the front of the gate structure" 3212 {
"add_RZ", (PyCFunction) qgd_Circuit_Wrapper_add_RZ, METH_VARARGS | METH_KEYWORDS,
3213 "Call to add a RZ gate to the front of the gate structure" 3215 {
"add_CNOT", (PyCFunction) qgd_Circuit_Wrapper_add_CNOT, METH_VARARGS | METH_KEYWORDS,
3216 "Call to add a CNOT gate to the front of the gate structure" 3218 {
"add_CZ", (PyCFunction) qgd_Circuit_Wrapper_add_CZ, METH_VARARGS | METH_KEYWORDS,
3219 "Call to add a CZ gate to the front of the gate structure" 3221 {
"add_CU", (PyCFunction) qgd_Circuit_Wrapper_add_CU, METH_VARARGS | METH_KEYWORDS,
3222 "Call to add a CU gate to the front of the gate structure" 3224 {
"add_CH", (PyCFunction) qgd_Circuit_Wrapper_add_CH, METH_VARARGS | METH_KEYWORDS,
3225 "Call to add a CH gate to the front of the gate structure" 3227 {
"add_SYC", (PyCFunction) qgd_Circuit_Wrapper_add_SYC, METH_VARARGS | METH_KEYWORDS,
3228 "Call to add a Sycamore gate to the front of the gate structure" 3230 {
"add_H", (PyCFunction) qgd_Circuit_Wrapper_add_H, METH_VARARGS | METH_KEYWORDS,
3231 "Call to add a Hadamard gate to the front of the gate structure" 3233 {
"add_X", (PyCFunction) qgd_Circuit_Wrapper_add_X, METH_VARARGS | METH_KEYWORDS,
3234 "Call to add a X gate to the front of the gate structure" 3236 {
"add_Y", (PyCFunction) qgd_Circuit_Wrapper_add_Y, METH_VARARGS | METH_KEYWORDS,
3237 "Call to add a Y gate to the front of the gate structure" 3239 {
"add_Z", (PyCFunction) qgd_Circuit_Wrapper_add_Z, METH_VARARGS | METH_KEYWORDS,
3240 "Call to add a Z gate to the front of the gate structure" 3242 {
"add_SX", (PyCFunction) qgd_Circuit_Wrapper_add_SX, METH_VARARGS | METH_KEYWORDS,
3243 "Call to add a SX gate to the front of the gate structure" 3245 {
"add_SXdg", (PyCFunction) qgd_Circuit_Wrapper_add_SXdg, METH_VARARGS | METH_KEYWORDS,
3246 "Call to add a SXdg gate to the front of the gate structure" 3248 {
"add_S", (PyCFunction) qgd_Circuit_Wrapper_add_S, METH_VARARGS | METH_KEYWORDS,
3249 "Call to add a S gate to the front of the gate structure" 3251 {
"add_Sdg", (PyCFunction) qgd_Circuit_Wrapper_add_Sdg, METH_VARARGS | METH_KEYWORDS,
3252 "Call to add a Sdg gate to the front of the gate structure" 3254 {
"add_T", (PyCFunction) qgd_Circuit_Wrapper_add_T, METH_VARARGS | METH_KEYWORDS,
3255 "Call to add a T gate to the front of the gate structure" 3257 {
"add_Tdg", (PyCFunction) qgd_Circuit_Wrapper_add_Tdg, METH_VARARGS | METH_KEYWORDS,
3258 "Call to add a Tdg gate to the front of the gate structure" 3260 {
"add_CRY", (PyCFunction) qgd_Circuit_Wrapper_add_CRY, METH_VARARGS | METH_KEYWORDS,
3261 "Call to add a CRY gate to the front of the gate structure" 3263 {
"add_CRX", (PyCFunction) qgd_Circuit_Wrapper_add_CRX, METH_VARARGS | METH_KEYWORDS,
3264 "Call to add a CRY gate to the front of the gate structure" 3266 {
"add_CRZ", (PyCFunction) qgd_Circuit_Wrapper_add_CRZ, METH_VARARGS | METH_KEYWORDS,
3267 "Call to add a CRY gate to the front of the gate structure" 3269 {
"add_CP", (PyCFunction) qgd_Circuit_Wrapper_add_CP, METH_VARARGS | METH_KEYWORDS,
3270 "Call to add a CRY gate to the front of the gate structure" 3273 "Call to add a CCX gate to the front of the gate structure" 3275 {
"add_SWAP", (PyCFunction) qgd_Circuit_Wrapper_add_SWAP, METH_VARARGS | METH_KEYWORDS,
3276 "Call to add a SWAP gate to the front of the gate structure" 3279 "Call to add a CSWAP gate to the front of the gate structure" 3281 {
"add_CROT", (PyCFunction) qgd_Circuit_Wrapper_add_CROT, METH_VARARGS | METH_KEYWORDS,
3282 "Call to add a CROT gate to the front of the gate structure" 3284 {
"add_CR", (PyCFunction) qgd_Circuit_Wrapper_add_CR, METH_VARARGS | METH_KEYWORDS,
3285 "Call to add a CR gate to the front of the gate structure" 3287 {
"add_adaptive", (PyCFunction) qgd_Circuit_Wrapper_add_adaptive, METH_VARARGS | METH_KEYWORDS,
3288 "Call to add an adaptive gate to the front of the gate structure" 3291 "Call to add a block of operations to the front of the gate structure." 3294 "Call to add a GENERAL_OPERATION gate from an explicit matrix." 3297 {
"convert_to_DFE_gates_with_derivates", (PyCFunction) qgd_Circuit_Wrapper_convert_to_DFE_gates_with_derivates, METH_VARARGS,
3298 "Call to convert to DFE gates with derivates." 3300 {
"adjust_parameters_for_derivation", (PyCFunction) qgd_Circuit_Wrapper_adjust_parameters_for_derivation, METH_VARARGS,
3301 "Call to adjust parameters for derivation." 3303 {
"convert_to_DFE_gates", (PyCFunction) qgd_Circuit_Wrapper_convert_to_DFE_gates, METH_VARARGS,
3304 "Call to convert to DFE gates." 3306 {
"convert_to_DFE_gates", (PyCFunction) qgd_Circuit_Wrapper_convert_to_DFE_gates, METH_VARARGS,
3307 "Call to convert to DFE gates." 3311 "Method to get the matrix of the operation." 3314 "Call to get the number of free parameters in the circuit" 3317 "Call to apply the gate on the input matrix (or state). Keyword is_f32=True selects float32/complex64 path." 3320 "Call to apply the gate from the right on the input matrix. Keyword is_f32=True selects float32/complex64 path." 3323 "Call to apply the circuit on a list of input matrices (float64/complex128 only)." 3326 "Call to evaluate the derivative of the circuit on an input matrix. Returns a list of derivative matrices." 3329 "Call to evaluate forward action and derivatives of the circuit on an input matrix. Returns [forward, derivatives...]." 3332 "Wrapper function to evaluate the second Rényi entropy of a quantum circuit at a specific parameter set." 3335 "Call to get the number of qubits in the circuit" 3338 "Call to set the number of qubits in the circuit" 3341 "Call to get the list of qubits involved in the circuit" 3344 "Call to set the min fusion in the circuit" 3347 "Call to remap the qubits in the circuit." 3350 "Method to get the i-th decomposing gates." 3353 "Method to get the tuple of decomposing gates." 3356 "Method to get statistics on the gate counts in the circuit." 3359 "Call to get the starting index of the parameters in the parameter array corresponding to the circuit in which the current gate is incorporated." 3362 "Call to extract the parameters corresponding to the gate from a parameter array associated with the circuit in which the gate is embedded." 3365 "Export the circuit and its parameters into Squander binary format. Arguments: filename (str), parameters (numpy array)." 3368 "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." 3371 "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." 3374 "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." 3377 "Method to extract the stored quantum circuit in a human-readable data serialized and pickle-able format." 3380 "Call to set the state of a quantum circuit from a human-readable data serialized and pickle-able format." 3392 PyVarObject_HEAD_INIT(NULL, 0)
3393 "qgd_Circuit_Wrapper.qgd_Circuit_Wrapper",
3397 #if PY_VERSION_HEX < 0x030800b4 3400 #if PY_VERSION_HEX >= 0x030800b4 3405 #if PY_MAJOR_VERSION < 3 3408 #if PY_MAJOR_VERSION >= 3 3421 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
3422 "Object to represent a qgd_Circuit_Wrapper class of the QGD package.",
3449 #
if PY_VERSION_HEX >= 0x030400a1
3452 #
if PY_VERSION_HEX >= 0x030800b1
3455 #
if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000
3464 PyModuleDef_HEAD_INIT,
3465 "qgd_Circuit_Wrapper",
3466 "Python binding for QGD Circuit class",
3481 if (PyType_Ready(&qgd_Circuit_Wrapper_Type) < 0)
3484 m = PyModule_Create(&qgd_Circuit_Wrapper_Module);
3488 Py_INCREF(&qgd_Circuit_Wrapper_Type);
3489 if (PyModule_AddObject(m,
"qgd_Circuit_Wrapper", (PyObject *) &qgd_Circuit_Wrapper_Type) < 0) {
3490 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 PyObject * qgd_Circuit_Wrapper_export_to_Binary(qgd_Circuit_Wrapper *self, PyObject *args)
Export the circuit and its parameters into Squander binary format.
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)
void export_gate_list_to_binary(Matrix_real ¶meters, Gates_block *gates_block, const std::string &filename, int verbosity)
Use to export a quantum circuit into binary format.
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.