27 #define PY_SSIZE_T_CLEAN 31 #include "structmember.h" 83 template<
typename GateT>
85 GateT* gate =
new GateT( qbit_num, target_qbit );
86 return static_cast<Gate*
>( gate );
89 template<
typename GateT>
91 GateT* gate =
new GateT( qbit_num );
92 return static_cast<Gate*
>( gate );
96 template<
typename GateT>
99 GateT* gate =
new GateT( qbit_num, target_qbit, control_qbit );
100 return static_cast<Gate*
>( gate );
104 template<
typename GateT>
107 GateT* gate =
new GateT( qbit_num, target_qbits );
108 return static_cast<Gate*
>( gate );
112 template<
typename GateT>
115 GateT* gate =
new GateT( qbit_num, target_qbit, control_qbits );
116 return static_cast<Gate*
>( gate );
120 template<
typename GateT>
123 GateT* gate =
new GateT( qbit_num, target_qbits, control_qbits );
124 return static_cast<Gate*
>( gate );
137 if( self->gate != NULL ) {
138 delete(
self->gate );
142 Py_TYPE(
self)->tp_free((PyObject *)
self);
154 static char *kwlist[] = {(
char*)
"qbit_num", NULL};
158 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|i", kwlist, &qbit_num)) {
159 std::string err(
"Unable to parse arguments");
160 PyErr_SetString(PyExc_Exception, err.c_str());
165 PyErr_SetString(PyExc_ValueError,
"Qubit_num must be set!");
173 self->gate =
new Gate( qbit_num );
177 return (PyObject *)
self;
188 template<
typename GateT>
193 static char *kwlist[] = {(
char*)
"qbit_num", (
char*)
"target_qbit", NULL};
197 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|ii", kwlist, &qbit_num, &target_qbit)) {
198 std::string err(
"Unable to parse arguments");
199 PyErr_SetString(PyExc_Exception, err.c_str());
203 if (qbit_num == -1 || target_qbit == -1){
204 PyErr_SetString(PyExc_ValueError,
"Qubit_num and target_qubit all must be set!");
208 if (qbit_num <= target_qbit ){
209 PyErr_SetString(PyExc_ValueError,
"Target_qubit cannot be larger or equal than qubit_num!");
219 return (PyObject *)
self;
228 template<
typename GateT>
232 static char *kwlist[] = {(
char*)
"qbit_num", NULL};
235 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|i", kwlist, &qbit_num)) {
236 std::string err(
"Unable to parse arguments");
237 PyErr_SetString(PyExc_Exception, err.c_str());
242 PyErr_SetString(PyExc_ValueError,
"Qubit_num must be set!");
249 self->gate = create_qbit_gate<GateT>(
qbit_num );
252 return (PyObject *)
self;
262 template<
typename GateT>
266 static char *kwlist[] = {(
char*)
"qbit_num", (
char*)
"target_qbit", (
char*)
"control_qbit", NULL};
272 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|iii", kwlist, &qbit_num, &target_qbit, &control_qbit)) {
273 std::string err(
"Unable to parse arguments");
274 PyErr_SetString(PyExc_Exception, err.c_str());
278 if ((qbit_num == -1 || target_qbit == -1) || control_qbit == -1){
279 PyErr_SetString(PyExc_ValueError,
"Qubit_num, target_qubit and control_qubit all must be set!");
283 if (qbit_num <= target_qbit || qbit_num <= control_qbit ){
284 PyErr_SetString(PyExc_ValueError,
"Target_qubit or control_qbit cannot be larger or equal than qubit_num!");
294 return (PyObject *)
self;
304 template<
typename GateT>
308 static char *kwlist[] = {(
char*)
"qbit_num", (
char*)
"target_qbit", (
char*)
"control_qbits", NULL};
311 PyObject* control_qbits_py = NULL;
313 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|iiO", kwlist, &qbit_num, &target_qbit, &control_qbits_py)) {
314 std::string err(
"Unable to parse arguments");
315 PyErr_SetString(PyExc_Exception, err.c_str());
319 if (qbit_num == -1 || target_qbit == -1 || control_qbits_py == NULL) {
320 PyErr_SetString(PyExc_ValueError,
"qbit_num, target_qbit, and control_qbits must be provided!");
324 if (target_qbit >= qbit_num) {
325 PyErr_SetString(PyExc_ValueError,
"Target qubit index out of range!");
330 if (!PyList_Check(control_qbits_py)) {
331 PyErr_SetString(PyExc_TypeError,
"control_qbits must be a list!");
335 std::vector<int> control_qbits;
336 Py_ssize_t list_size = PyList_Size(control_qbits_py);
337 for (Py_ssize_t i = 0; i < list_size; i++) {
338 PyObject* item = PyList_GetItem(control_qbits_py, i);
339 if (!PyLong_Check(item)) {
340 PyErr_SetString(PyExc_TypeError,
"control_qbits must contain integers!");
343 int qbit = PyLong_AsLong(item);
344 if (qbit >= qbit_num) {
345 PyErr_SetString(PyExc_ValueError,
"Control qubit index out of range!");
348 control_qbits.push_back(qbit);
357 return (PyObject *)
self;
366 template<
typename GateT>
370 static char *kwlist[] = {(
char*)
"qbit_num", (
char*)
"target_qbits", NULL};
374 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|iO", kwlist, &qbit_num, &target_qbits_py)) {
375 std::string err(
"Unable to parse arguments");
376 PyErr_SetString(PyExc_Exception, err.c_str());
380 if (qbit_num == -1 || target_qbits_py == NULL) {
381 PyErr_SetString(PyExc_ValueError,
"qbit_num and target_qbits must be provided!");
386 if (!PyList_Check(target_qbits_py)) {
387 PyErr_SetString(PyExc_TypeError,
"target_qbits must be a list!");
391 std::vector<int> target_qbits;
392 Py_ssize_t target_size = PyList_Size(target_qbits_py);
393 for (Py_ssize_t i = 0; i < target_size; i++) {
394 PyObject* item = PyList_GetItem(target_qbits_py, i);
395 if (!PyLong_Check(item)) {
396 PyErr_SetString(PyExc_TypeError,
"target_qbits must contain integers!");
399 int qbit = PyLong_AsLong(item);
400 if (qbit >= qbit_num) {
401 PyErr_SetString(PyExc_ValueError,
"Target qubit index out of range!");
404 target_qbits.push_back(qbit);
410 self->gate = create_multi_target_gate<GateT>(
qbit_num, target_qbits);
413 return (PyObject *)
self;
422 template<
typename GateT>
426 static char *kwlist[] = {(
char*)
"qbit_num", (
char*)
"target_qbits", (
char*)
"control_qbits", NULL};
429 PyObject* control_qbits_py = NULL;
431 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|iOO", kwlist, &qbit_num, &target_qbits_py, &control_qbits_py)) {
432 std::string err(
"Unable to parse arguments");
433 PyErr_SetString(PyExc_Exception, err.c_str());
437 if (qbit_num == -1 || target_qbits_py == NULL || control_qbits_py == NULL) {
438 PyErr_SetString(PyExc_ValueError,
"qbit_num, target_qbits, and control_qbits must be provided!");
443 if (!PyList_Check(target_qbits_py) || !PyList_Check(control_qbits_py)) {
444 PyErr_SetString(PyExc_TypeError,
"target_qbits and control_qbits must be lists!");
448 std::vector<int> target_qbits;
449 Py_ssize_t target_size = PyList_Size(target_qbits_py);
450 for (Py_ssize_t i = 0; i < target_size; i++) {
451 PyObject* item = PyList_GetItem(target_qbits_py, i);
452 if (!PyLong_Check(item)) {
453 PyErr_SetString(PyExc_TypeError,
"target_qbits must contain integers!");
456 int qbit = PyLong_AsLong(item);
457 if (qbit >= qbit_num) {
458 PyErr_SetString(PyExc_ValueError,
"Target qubit index out of range!");
461 target_qbits.push_back(qbit);
464 std::vector<int> control_qbits;
465 Py_ssize_t control_size = PyList_Size(control_qbits_py);
466 for (Py_ssize_t i = 0; i < control_size; i++) {
467 PyObject* item = PyList_GetItem(control_qbits_py, i);
468 if (!PyLong_Check(item)) {
469 PyErr_SetString(PyExc_TypeError,
"control_qbits must contain integers!");
472 int qbit = PyLong_AsLong(item);
473 if (qbit >= qbit_num) {
474 PyErr_SetString(PyExc_ValueError,
"Control qubit index out of range!");
477 control_qbits.push_back(qbit);
483 self->gate = create_multi_target_controlled_gate<GateT>(
qbit_num, target_qbits, control_qbits);
486 return (PyObject *)
self;
518 static char *kwlist[] = {(
char*)
"parameters", (
char*)
"is_f32", NULL};
520 PyObject* parameters_obj = NULL;
521 PyArrayObject * parameters_arr = NULL;
526 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|Op", kwlist, ¶meters_obj, &is_f32 )) {
527 std::string err(
"Unable to parse keyword arguments");
528 PyErr_SetString(PyExc_Exception, err.c_str());
533 Gate* gate =
self->gate;
538 if (parameters_obj != NULL) {
539 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF(parameters_obj, NPY_FLOAT32, NPY_ARRAY_IN_ARRAY);
540 if (parameters_arr == NULL) {
541 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be float32 when is_f32=True");
548 if (parameters_arr != NULL) {
549 PyErr_SetString(PyExc_Exception,
"The gate contains no parameters to set, but parameter array was given as input");
550 Py_DECREF(parameters_arr);
557 for (
int idx = 0; idx < gate_mtx.
size(); idx++) {
558 gate_mtx[idx].real = 0.0f;
559 gate_mtx[idx].imag = 0.0f;
562 gate_mtx[idx * gate_mtx.
stride + idx].real = 1.0f;
569 if (parameters_arr == NULL) {
570 PyErr_SetString(PyExc_Exception,
"The gate has free parameters to set, but no parameter array was given as input");
576 gate_mtx = gate->
get_matrix(parameters_mtx, 1);
578 Py_DECREF(parameters_arr);
582 std::string err(
"The number of parameters in a gate is set to a negative value");
583 PyErr_SetString(PyExc_Exception, err.c_str());
584 if (parameters_arr != NULL) {
585 Py_DECREF(parameters_arr);
598 if (parameters_obj != NULL) {
599 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF(parameters_obj, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
600 if (parameters_arr == NULL) {
601 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be real typed and array-like");
608 if( parameters_arr != NULL ) {
609 PyErr_SetString(PyExc_Exception,
"The gate contains no parameters to set, but parameter array was given as input");
610 Py_DECREF(parameters_arr);
620 if( parameters_arr == NULL ) {
621 PyErr_SetString(PyExc_Exception,
"The gate has free parameters to set, but no parameter array was given as input");
628 gate_mtx =
self->gate->get_matrix( parameters_mtx, parallel );
630 Py_DECREF(parameters_arr);
635 std::string err(
"The number of parameters in a gate is set to a negative value");
636 PyErr_SetString(PyExc_Exception, err.c_str());
637 if (parameters_arr != NULL) {
638 Py_DECREF(parameters_arr);
652 catch (
const std::string& err) {
653 if (parameters_arr != NULL) {
654 Py_DECREF(parameters_arr);
656 PyErr_SetString(PyExc_RuntimeError, err.c_str());
659 catch (
const std::exception& err) {
660 if (parameters_arr != NULL) {
661 Py_DECREF(parameters_arr);
663 PyErr_SetString(PyExc_RuntimeError, err.what());
667 if (parameters_arr != NULL) {
668 Py_DECREF(parameters_arr);
670 PyErr_SetString(PyExc_RuntimeError,
"Unknown error in Gate_Wrapper_get_Matrix");
682 static char *kwlist[] = {(
char*)
"unitary", (
char*)
"parameters", (
char*)
"is_f32", NULL};
684 PyArrayObject * input = NULL;
685 PyArrayObject * parameters_arr = NULL;
688 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"O|Op", kwlist, &input, ¶meters_arr, &is_f32 )) {
689 std::string err(
"Unable to parse keyword arguments");
690 PyErr_SetString(PyExc_Exception, err.c_str());
694 Gate* gate =
self->gate;
696 bool release_parameters_arr =
false;
698 if ( input == NULL ) {
699 PyErr_SetString(PyExc_Exception,
"Input matrix was not given");
703 if (param_count == 0 && parameters_arr != NULL) {
704 PyErr_SetString(PyExc_Exception,
"The gate contains no parameters to set, but parameter array was given as input");
709 if ( PyArray_TYPE(input) != NPY_COMPLEX64 ) {
710 PyErr_SetString(PyExc_TypeError,
"input matrix or state should be complex64 when is_f32=True");
715 if ( PyArray_TYPE(input) != NPY_COMPLEX128 ) {
716 PyErr_SetString(PyExc_TypeError,
"input matrix or state should be complex128 when is_f32=False");
721 if ( !PyArray_IS_C_CONTIGUOUS(input) ) {
722 PyErr_SetString(PyExc_Exception,
"input state/matrix is not memory contiguous");
731 if (param_count == 0) {
734 else if (param_count > 0) {
735 if( parameters_arr == NULL ) {
736 std::string err(
"The gate has free parameters to set, but no parameter array was given as input");
737 PyErr_SetString(PyExc_Exception, err.c_str());
741 if ( PyArray_TYPE(parameters_arr) != NPY_FLOAT32 ) {
742 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be float32 when is_f32=True");
746 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
747 Py_INCREF(parameters_arr);
750 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_FLOAT32, NPY_ARRAY_IN_ARRAY);
753 if (parameters_arr == NULL) {
754 PyErr_SetString(PyExc_TypeError,
"Failed to cast parameters to a contiguous float32 numpy array");
757 release_parameters_arr =
true;
762 Py_DECREF(parameters_arr);
765 PyErr_SetString(PyExc_ValueError,
"The number of parameters in a gate is set to a negative value");
769 catch (
const std::string& err) {
770 if (release_parameters_arr) {
771 Py_DECREF(parameters_arr);
773 PyErr_SetString(PyExc_RuntimeError, err.c_str());
777 if (release_parameters_arr) {
778 Py_DECREF(parameters_arr);
780 PyErr_SetString(PyExc_RuntimeError,
"Unknown error in gate operation");
784 if (input_mtx.
data != PyArray_DATA(input)) {
794 if (param_count == 0) {
797 else if (param_count > 0) {
798 if( parameters_arr == NULL ) {
799 std::string err(
"The gate has free parameters to set, but no parameter array was given as input");
800 PyErr_SetString(PyExc_Exception, err.c_str());
804 if ( PyArray_TYPE(parameters_arr) != NPY_DOUBLE ) {
805 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be float64 when is_f32=False");
809 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
810 Py_INCREF(parameters_arr);
813 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
816 if (parameters_arr == NULL) {
817 PyErr_SetString(PyExc_TypeError,
"Failed to cast parameters to a contiguous double numpy array");
820 release_parameters_arr =
true;
825 Py_DECREF(parameters_arr);
828 PyErr_SetString(PyExc_ValueError,
"The number of parameters in a gate is set to a negative value");
832 catch (
const std::string& err) {
833 if (release_parameters_arr) {
834 Py_DECREF(parameters_arr);
836 PyErr_SetString(PyExc_RuntimeError, err.c_str());
840 if (release_parameters_arr) {
841 Py_DECREF(parameters_arr);
843 PyErr_SetString(PyExc_RuntimeError,
"Unknown error in gate operation");
847 if (input_mtx.
data != PyArray_DATA(input)) {
861 static char *kwlist[] = {(
char*)
"inputs", (
char*)
"parameters", (
char*)
"parallel", (
char*)
"is_f32", NULL};
863 PyObject * inputs_obj = NULL;
864 PyArrayObject * parameters_arr = NULL;
868 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"O|Oip", kwlist, &inputs_obj, ¶meters_arr, ¶llel, &is_f32 )) {
869 std::string err(
"Unable to parse keyword arguments");
870 PyErr_SetString(PyExc_Exception, err.c_str());
874 if ( inputs_obj == NULL ) {
875 PyErr_SetString(PyExc_Exception,
"Input list was not given");
879 PyObject* seq = PySequence_Fast(inputs_obj,
"inputs must be a sequence of numpy arrays");
884 Gate* gate =
self->gate;
886 bool release_parameters_arr =
false;
892 if (param_count > 0) {
893 if( parameters_arr == NULL ) {
894 std::string err(
"The gate has free parameters to set, but no parameter array was given as input");
896 PyErr_SetString(PyExc_Exception, err.c_str());
900 if ( PyArray_TYPE(parameters_arr) != NPY_FLOAT32 ) {
902 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be float32 when is_f32=True");
906 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
907 Py_INCREF(parameters_arr);
910 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_FLOAT32, NPY_ARRAY_IN_ARRAY);
913 if (parameters_arr == NULL) {
915 PyErr_SetString(PyExc_TypeError,
"Failed to cast parameters to a contiguous float32 numpy array");
918 release_parameters_arr =
true;
922 const Py_ssize_t
n = PySequence_Fast_GET_SIZE(seq);
923 PyObject** items = PySequence_Fast_ITEMS(seq);
924 for (Py_ssize_t idx = 0; idx <
n; idx++) {
925 PyObject* item = items[idx];
926 if (!PyArray_Check(item)) {
928 if (release_parameters_arr) {
929 Py_DECREF(parameters_arr);
931 PyErr_SetString(PyExc_TypeError,
"All inputs should be numpy arrays");
935 PyArrayObject* input = (PyArrayObject*)item;
936 if ( PyArray_TYPE(input) != NPY_COMPLEX64 ) {
938 if (release_parameters_arr) {
939 Py_DECREF(parameters_arr);
941 PyErr_SetString(PyExc_TypeError,
"All inputs should be complex64 when is_f32=True");
945 if ( !PyArray_IS_C_CONTIGUOUS(input) ) {
947 if (release_parameters_arr) {
948 Py_DECREF(parameters_arr);
950 PyErr_SetString(PyExc_TypeError,
"All inputs should be C-contiguous");
955 if (param_count == 0) {
956 gate->
apply_to(input_mtx, parallel);
958 else if (param_count > 0) {
959 gate->
apply_to(parameters_mtx, input_mtx, parallel);
963 if (release_parameters_arr) {
964 Py_DECREF(parameters_arr);
966 PyErr_SetString(PyExc_ValueError,
"The number of parameters in a gate is set to a negative value");
970 if (input_mtx.
data != PyArray_DATA(input)) {
978 if (param_count > 0) {
979 if( parameters_arr == NULL ) {
980 std::string err(
"The gate has free parameters to set, but no parameter array was given as input");
982 PyErr_SetString(PyExc_Exception, err.c_str());
986 if ( PyArray_TYPE(parameters_arr) != NPY_DOUBLE ) {
988 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be float64 when is_f32=False");
992 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
993 Py_INCREF(parameters_arr);
996 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
999 if (parameters_arr == NULL) {
1001 PyErr_SetString(PyExc_TypeError,
"Failed to cast parameters to a contiguous double numpy array");
1004 release_parameters_arr =
true;
1008 const Py_ssize_t
n = PySequence_Fast_GET_SIZE(seq);
1009 PyObject** items = PySequence_Fast_ITEMS(seq);
1010 for (Py_ssize_t idx = 0; idx <
n; idx++) {
1011 PyObject* item = items[idx];
1012 if (!PyArray_Check(item)) {
1014 if (release_parameters_arr) {
1015 Py_DECREF(parameters_arr);
1017 PyErr_SetString(PyExc_TypeError,
"All inputs should be numpy arrays");
1021 PyArrayObject* input = (PyArrayObject*)item;
1022 if ( PyArray_TYPE(input) != NPY_COMPLEX128 ) {
1024 if (release_parameters_arr) {
1025 Py_DECREF(parameters_arr);
1027 PyErr_SetString(PyExc_TypeError,
"All inputs should be complex128 when is_f32=False");
1031 if ( !PyArray_IS_C_CONTIGUOUS(input) ) {
1033 if (release_parameters_arr) {
1034 Py_DECREF(parameters_arr);
1036 PyErr_SetString(PyExc_TypeError,
"All inputs should be C-contiguous");
1041 if (param_count == 0) {
1042 gate->
apply_to(input_mtx, parallel);
1044 else if (param_count > 0) {
1045 gate->
apply_to(parameters_mtx, input_mtx, parallel);
1049 if (release_parameters_arr) {
1050 Py_DECREF(parameters_arr);
1052 PyErr_SetString(PyExc_ValueError,
"The number of parameters in a gate is set to a negative value");
1056 if (input_mtx.
data != PyArray_DATA(input)) {
1063 if (release_parameters_arr) {
1064 Py_DECREF(parameters_arr);
1068 catch (
const std::string& err) {
1070 if (release_parameters_arr) {
1071 Py_DECREF(parameters_arr);
1073 PyErr_SetString(PyExc_RuntimeError, err.c_str());
1078 if (release_parameters_arr) {
1079 Py_DECREF(parameters_arr);
1081 PyErr_SetString(PyExc_RuntimeError,
"Unknown error in gate operation");
1094 static char *kwlist[] = {(
char*)
"unitary", (
char*)
"parameters", (
char*)
"parallel", (
char*)
"is_f32", NULL};
1096 PyArrayObject * input = NULL;
1097 PyArrayObject * parameters_arr = NULL;
1102 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"O|Oip", kwlist, &input, ¶meters_arr, ¶llel, &is_f32 )) {
1103 std::string err(
"Unable to parse keyword arguments");
1104 PyErr_SetString(PyExc_Exception, err.c_str());
1109 if ( input == NULL ) {
1110 PyErr_SetString(PyExc_Exception,
"Input matrix was not given");
1115 if ( PyArray_TYPE(input) != NPY_COMPLEX64 ) {
1116 PyErr_SetString(PyExc_TypeError,
"input matrix or state should be complex64 when is_f32=True");
1121 if ( PyArray_TYPE(input) != NPY_COMPLEX128 ) {
1122 PyErr_SetString(PyExc_TypeError,
"input matrix or state should be complex128 when is_f32=False");
1128 if ( !PyArray_IS_C_CONTIGUOUS(input) ) {
1129 PyErr_SetString(PyExc_Exception,
"input state/matrix is not memory contiguous");
1133 Gate* gate =
self->gate;
1136 bool release_parameters_arr =
false;
1143 if (param_count == 0) {
1144 gate->
apply_to(input_mtx, parallel);
1146 else if (param_count > 0) {
1147 if( parameters_arr == NULL ) {
1148 std::string err(
"The gate has free parameters to set, but no parameter array was given as input");
1149 PyErr_SetString(PyExc_Exception, err.c_str());
1153 if ( PyArray_TYPE(parameters_arr) != NPY_FLOAT32 ) {
1154 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be float32 when is_f32=True");
1158 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
1159 Py_INCREF(parameters_arr);
1162 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_FLOAT32, NPY_ARRAY_IN_ARRAY);
1165 if (parameters_arr == NULL) {
1166 PyErr_SetString(PyExc_TypeError,
"Failed to cast parameters to a contiguous float32 numpy array");
1169 release_parameters_arr =
true;
1172 gate->
apply_to(parameters_mtx, input_mtx, parallel);
1174 Py_DECREF(parameters_arr);
1177 PyErr_SetString(PyExc_ValueError,
"The number of parameters in a gate is set to a negative value");
1181 catch (
const std::string& err) {
1182 if (release_parameters_arr) {
1183 Py_DECREF(parameters_arr);
1185 PyErr_SetString(PyExc_RuntimeError, err.c_str());
1189 if (release_parameters_arr) {
1190 Py_DECREF(parameters_arr);
1192 PyErr_SetString(PyExc_RuntimeError,
"Unknown error in gate operation");
1196 if (input_mtx.
data != PyArray_DATA(input)) {
1206 if (param_count == 0) {
1207 gate->
apply_to(input_mtx, parallel);
1209 else if (param_count > 0) {
1210 if( parameters_arr == NULL ) {
1211 std::string err(
"The gate has free parameters to set, but no parameter array was given as input");
1212 PyErr_SetString(PyExc_Exception, err.c_str());
1216 if ( PyArray_TYPE(parameters_arr) != NPY_DOUBLE ) {
1217 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be float64 when is_f32=False");
1221 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
1222 Py_INCREF(parameters_arr);
1225 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
1228 if (parameters_arr == NULL) {
1229 PyErr_SetString(PyExc_TypeError,
"Failed to cast parameters to a contiguous double numpy array");
1232 release_parameters_arr =
true;
1236 gate->
apply_to(parameters_mtx, input_mtx, parallel);
1238 Py_DECREF(parameters_arr);
1241 PyErr_SetString(PyExc_ValueError,
"The number of parameters in a gate is set to a negative value");
1245 catch (
const std::string& err) {
1246 if (release_parameters_arr) {
1247 Py_DECREF(parameters_arr);
1249 PyErr_SetString(PyExc_RuntimeError, err.c_str());
1253 if (release_parameters_arr) {
1254 Py_DECREF(parameters_arr);
1256 PyErr_SetString(PyExc_RuntimeError,
"Unknown error in gate operation");
1260 if (input_mtx.
data != PyArray_DATA(input)) {
1274 Matrix* m =
static_cast<Matrix*
>( PyCapsule_GetPointer(cap,
"squander.matrix_owner") );
1293 static char *kwlist[] = {(
char*)
"unitary", (
char*)
"parameters", (
char*)
"parallel", (
char*)
"is_f32", NULL};
1295 PyArrayObject * input = NULL;
1296 PyArrayObject * parameters_arr = NULL;
1300 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"O|Oip", kwlist, &input, ¶meters_arr, ¶llel, &is_f32 )) {
1301 std::string err(
"Unable to parse keyword arguments");
1302 PyErr_SetString(PyExc_Exception, err.c_str());
1306 if ( input == NULL ) {
1307 PyErr_SetString(PyExc_Exception,
"Input matrix was not given");
1312 if ( PyArray_TYPE(input) != NPY_COMPLEX64 ) {
1313 PyErr_SetString(PyExc_TypeError,
"input matrix or state should be complex64 when is_f32=True");
1318 if ( PyArray_TYPE(input) != NPY_COMPLEX128 ) {
1319 PyErr_SetString(PyExc_TypeError,
"input matrix or state should be complex128 when is_f32=False");
1324 if ( !PyArray_IS_C_CONTIGUOUS(input) ) {
1325 PyErr_SetString(PyExc_Exception,
"input state/matrix is not memory contiguous");
1329 Gate* gate =
self->gate;
1331 bool release_parameters_arr =
false;
1338 if (param_count > 0) {
1339 if( parameters_arr == NULL ) {
1340 std::string err(
"The gate has free parameters to set, but no parameter array was given as input");
1341 PyErr_SetString(PyExc_Exception, err.c_str());
1345 if ( PyArray_TYPE(parameters_arr) != NPY_FLOAT32 ) {
1346 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be float32 when is_f32=True");
1350 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
1351 Py_INCREF(parameters_arr);
1354 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_FLOAT32, NPY_ARRAY_IN_ARRAY);
1357 if (parameters_arr == NULL) {
1358 PyErr_SetString(PyExc_TypeError,
"Failed to cast parameters to a contiguous float32 numpy array");
1361 release_parameters_arr =
true;
1366 std::vector<Matrix_float> derivs;
1369 PyObject* deriv_list = PyList_New((Py_ssize_t)derivs.size());
1370 if (deriv_list == NULL) {
1371 if (release_parameters_arr) {
1372 Py_DECREF(parameters_arr);
1377 for (Py_ssize_t idx = 0; idx < (Py_ssize_t)derivs.size(); ++idx) {
1383 PyObject* cap = PyCapsule_New(
1384 owned,
"squander.matrix_float_owner",
1388 Py_DECREF(deriv_list);
1389 if (release_parameters_arr) {
1390 Py_DECREF(parameters_arr);
1394 npy_intp shape[2] = { (npy_intp)owned->
rows, (npy_intp)owned->
cols };
1396 PyObject* deriv_py = PyArray_SimpleNewFromData(
1397 2, shape, NPY_COMPLEX64, owned->
get_data());
1398 if (deriv_py == NULL) {
1400 Py_DECREF(deriv_list);
1401 if (release_parameters_arr) {
1402 Py_DECREF(parameters_arr);
1407 PyArray_SetBaseObject((PyArrayObject*)deriv_py, cap);
1408 PyList_SET_ITEM(deriv_list, idx, deriv_py);
1411 if (release_parameters_arr) {
1412 Py_DECREF(parameters_arr);
1416 catch (
const std::string& err) {
1417 if (release_parameters_arr) {
1418 Py_DECREF(parameters_arr);
1420 PyErr_SetString(PyExc_RuntimeError, err.c_str());
1424 if (release_parameters_arr) {
1425 Py_DECREF(parameters_arr);
1427 PyErr_SetString(PyExc_RuntimeError,
"Unknown error in gate derivative operation");
1435 if (param_count > 0) {
1436 if( parameters_arr == NULL ) {
1437 std::string err(
"The gate has free parameters to set, but no parameter array was given as input");
1438 PyErr_SetString(PyExc_Exception, err.c_str());
1442 if ( PyArray_TYPE(parameters_arr) != NPY_DOUBLE ) {
1443 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be float64 when is_f32=False");
1447 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
1448 Py_INCREF(parameters_arr);
1451 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
1454 if (parameters_arr == NULL) {
1455 PyErr_SetString(PyExc_TypeError,
"Failed to cast parameters to a contiguous double numpy array");
1458 release_parameters_arr =
true;
1463 std::vector<Matrix> derivs;
1466 PyObject* deriv_list = PyList_New((Py_ssize_t)derivs.size());
1467 if (deriv_list == NULL) {
1468 if (release_parameters_arr) {
1469 Py_DECREF(parameters_arr);
1474 for (Py_ssize_t idx = 0; idx < (Py_ssize_t)derivs.size(); ++idx) {
1480 PyObject* cap = PyCapsule_New(
1481 owned,
"squander.matrix_owner",
1485 Py_DECREF(deriv_list);
1486 if (release_parameters_arr) {
1487 Py_DECREF(parameters_arr);
1491 npy_intp shape[2] = { (npy_intp)owned->
rows, (npy_intp)owned->
cols };
1493 PyObject* deriv_py = PyArray_SimpleNewFromData(
1494 2, shape, NPY_COMPLEX128, owned->
get_data());
1495 if (deriv_py == NULL) {
1497 Py_DECREF(deriv_list);
1498 if (release_parameters_arr) {
1499 Py_DECREF(parameters_arr);
1504 PyArray_SetBaseObject((PyArrayObject*)deriv_py, cap);
1505 PyList_SET_ITEM(deriv_list, idx, deriv_py);
1508 if (release_parameters_arr) {
1509 Py_DECREF(parameters_arr);
1513 catch (
const std::string& err) {
1514 if (release_parameters_arr) {
1515 Py_DECREF(parameters_arr);
1517 PyErr_SetString(PyExc_RuntimeError, err.c_str());
1521 if (release_parameters_arr) {
1522 Py_DECREF(parameters_arr);
1524 PyErr_SetString(PyExc_RuntimeError,
"Unknown error in gate derivative operation");
1537 static char *kwlist[] = {(
char*)
"unitary", (
char*)
"parameters", (
char*)
"parallel", (
char*)
"is_f32", NULL};
1539 PyArrayObject * input = NULL;
1540 PyArrayObject * parameters_arr = NULL;
1544 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"O|Oip", kwlist, &input, ¶meters_arr, ¶llel, &is_f32 )) {
1545 std::string err(
"Unable to parse keyword arguments");
1546 PyErr_SetString(PyExc_Exception, err.c_str());
1550 if ( input == NULL ) {
1551 PyErr_SetString(PyExc_Exception,
"Input matrix was not given");
1556 if ( PyArray_TYPE(input) != NPY_COMPLEX64 ) {
1557 PyErr_SetString(PyExc_TypeError,
"input matrix or state should be complex64 when is_f32=True");
1562 if ( PyArray_TYPE(input) != NPY_COMPLEX128 ) {
1563 PyErr_SetString(PyExc_TypeError,
"input matrix or state should be complex128 when is_f32=False");
1568 if ( !PyArray_IS_C_CONTIGUOUS(input) ) {
1569 PyErr_SetString(PyExc_Exception,
"input state/matrix is not memory contiguous");
1573 Gate* gate =
self->gate;
1575 bool release_parameters_arr =
false;
1584 if (param_count > 0) {
1585 if( parameters_arr == NULL ) {
1586 std::string err(
"The gate has free parameters to set, but no parameter array was given as input");
1587 PyErr_SetString(PyExc_Exception, err.c_str());
1591 if ( PyArray_TYPE(parameters_arr) != NPY_FLOAT32 ) {
1592 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be float32 when is_f32=True");
1596 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
1597 Py_INCREF(parameters_arr);
1600 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_FLOAT32, NPY_ARRAY_IN_ARRAY);
1603 if (parameters_arr == NULL) {
1604 PyErr_SetString(PyExc_TypeError,
"Failed to cast parameters to a contiguous float32 numpy array");
1607 release_parameters_arr =
true;
1611 std::vector<Matrix_float> combined = gate->
apply_to_combined(parameters_mtx, input_mtx, parallel);
1613 PyObject* combined_list = PyList_New((Py_ssize_t)combined.size());
1614 if (combined_list == NULL) {
1615 if (release_parameters_arr) {
1616 Py_DECREF(parameters_arr);
1621 for (Py_ssize_t idx = 0; idx < (Py_ssize_t)combined.size(); ++idx) {
1623 PyObject* cap = PyCapsule_New(
1624 owned,
"squander.matrix_float_owner",
1628 Py_DECREF(combined_list);
1629 if (release_parameters_arr) {
1630 Py_DECREF(parameters_arr);
1634 npy_intp shape[2] = { (npy_intp)owned->
rows, (npy_intp)owned->
cols };
1635 PyObject* out_py = PyArray_SimpleNewFromData(
1636 2, shape, NPY_COMPLEX64, owned->
get_data());
1637 if (out_py == NULL) {
1639 Py_DECREF(combined_list);
1640 if (release_parameters_arr) {
1641 Py_DECREF(parameters_arr);
1645 PyArray_SetBaseObject((PyArrayObject*)out_py, cap);
1646 PyList_SET_ITEM(combined_list, idx, out_py);
1649 if (release_parameters_arr) {
1650 Py_DECREF(parameters_arr);
1652 return combined_list;
1654 catch (
const std::string& err) {
1655 if (release_parameters_arr) {
1656 Py_DECREF(parameters_arr);
1658 PyErr_SetString(PyExc_RuntimeError, err.c_str());
1662 if (release_parameters_arr) {
1663 Py_DECREF(parameters_arr);
1665 PyErr_SetString(PyExc_RuntimeError,
"Unknown error in gate combined operation");
1675 if (param_count > 0) {
1676 if( parameters_arr == NULL ) {
1677 std::string err(
"The gate has free parameters to set, but no parameter array was given as input");
1678 PyErr_SetString(PyExc_Exception, err.c_str());
1682 if ( PyArray_TYPE(parameters_arr) != NPY_DOUBLE ) {
1683 PyErr_SetString(PyExc_TypeError,
"Parameter vector should be float64 when is_f32=False");
1687 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
1688 Py_INCREF(parameters_arr);
1691 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
1694 if (parameters_arr == NULL) {
1695 PyErr_SetString(PyExc_TypeError,
"Failed to cast parameters to a contiguous double numpy array");
1698 release_parameters_arr =
true;
1702 std::vector<Matrix> combined = gate->
apply_to_combined(parameters_mtx, input_mtx, parallel);
1704 PyObject* combined_list = PyList_New((Py_ssize_t)combined.size());
1705 if (combined_list == NULL) {
1706 if (release_parameters_arr) {
1707 Py_DECREF(parameters_arr);
1712 for (Py_ssize_t idx = 0; idx < (Py_ssize_t)combined.size(); ++idx) {
1714 PyObject* cap = PyCapsule_New(
1715 owned,
"squander.matrix_owner",
1719 Py_DECREF(combined_list);
1720 if (release_parameters_arr) {
1721 Py_DECREF(parameters_arr);
1725 npy_intp shape[2] = { (npy_intp)owned->
rows, (npy_intp)owned->
cols };
1726 PyObject* out_py = PyArray_SimpleNewFromData(
1727 2, shape, NPY_COMPLEX128, owned->
get_data());
1728 if (out_py == NULL) {
1730 Py_DECREF(combined_list);
1731 if (release_parameters_arr) {
1732 Py_DECREF(parameters_arr);
1736 PyArray_SetBaseObject((PyArrayObject*)out_py, cap);
1737 PyList_SET_ITEM(combined_list, idx, out_py);
1740 if (release_parameters_arr) {
1741 Py_DECREF(parameters_arr);
1743 return combined_list;
1745 catch (
const std::string& err) {
1746 if (release_parameters_arr) {
1747 Py_DECREF(parameters_arr);
1749 PyErr_SetString(PyExc_RuntimeError, err.c_str());
1753 if (release_parameters_arr) {
1754 Py_DECREF(parameters_arr);
1756 PyErr_SetString(PyExc_RuntimeError,
"Unknown error in gate combined operation");
1775 static char *kwlist[] = {(
char*)
"ThetaOver2", (
char*)
"Phi", (
char*)
"Lambda", NULL};
1787 catch (std::string err) {
1788 PyErr_SetString(PyExc_Exception, err.c_str());
1792 std::string err(
"Invalid pointer to gate class");
1793 PyErr_SetString(PyExc_Exception, err.c_str());
1798 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|ddd", kwlist, &ThetaOver2, &Phi, &Lambda )) {
1799 std::string err(
"Unable to parse keyword arguments");
1800 PyErr_SetString(PyExc_Exception, err.c_str());
1808 Gate* gate =
self->gate;
1818 std::string err(
"The number of parameters in a gate is set to a negative value");
1819 PyErr_SetString(PyExc_Exception, err.c_str());
1844 parameter_num =
self->gate->get_parameter_num();
1846 catch (std::string err) {
1847 PyErr_SetString(PyExc_Exception, err.c_str());
1851 std::string err(
"Invalid pointer to gate class");
1852 PyErr_SetString(PyExc_Exception, err.c_str());
1873 start_index =
self->gate->get_parameter_start_idx();
1875 catch (std::string err) {
1876 PyErr_SetString(PyExc_Exception, err.c_str());
1880 std::string err(
"Invalid pointer to gate class");
1881 PyErr_SetString(PyExc_Exception, err.c_str());
1902 target_qbit =
self->gate->get_target_qbit();
1904 catch (std::string err) {
1905 PyErr_SetString(PyExc_Exception, err.c_str());
1909 std::string err(
"Invalid pointer to gate class");
1910 PyErr_SetString(PyExc_Exception, err.c_str());
1928 control_qbit =
self->gate->get_control_qbit();
1930 catch (std::string err) {
1931 PyErr_SetString(PyExc_Exception, err.c_str());
1935 std::string err(
"Invalid pointer to gate class");
1936 PyErr_SetString(PyExc_Exception, err.c_str());
1950 int target_qbit_in = -1;
1951 if (!PyArg_ParseTuple(args,
"|i", &target_qbit_in )) {
1952 std::string err(
"Unable to parse arguments");
1957 self->gate->set_target_qbit(target_qbit_in);
1959 catch (std::string err) {
1960 PyErr_SetString(PyExc_Exception, err.c_str());
1964 std::string err(
"Invalid pointer to circuit class");
1965 PyErr_SetString(PyExc_Exception, err.c_str());
1980 int control_qbit_in = -1;
1981 if (!PyArg_ParseTuple(args,
"|i", &control_qbit_in )) {
1982 std::string err(
"Unable to parse arguments");
1987 self->gate->set_control_qbit(control_qbit_in);
1989 catch (std::string err) {
1990 PyErr_SetString(PyExc_Exception, err.c_str());
1994 std::string err(
"Invalid pointer to circuit class");
1995 PyErr_SetString(PyExc_Exception, err.c_str());
2013 std::vector<int> target_qbits;
2016 target_qbits =
self->gate->get_target_qbits();
2018 catch (std::string err) {
2019 PyErr_SetString(PyExc_Exception, err.c_str());
2023 std::string err(
"Invalid pointer to gate class");
2024 PyErr_SetString(PyExc_Exception, err.c_str());
2028 PyObject*
target_qbits_py = PyList_New((Py_ssize_t)target_qbits.size());
2029 for (
size_t i = 0; i < target_qbits.size(); i++) {
2030 PyList_SetItem(target_qbits_py, (Py_ssize_t)i,
Py_BuildValue(
"i", target_qbits[i]));
2044 std::vector<int> control_qbits;
2047 control_qbits =
self->gate->get_control_qbits();
2049 catch (std::string err) {
2050 PyErr_SetString(PyExc_Exception, err.c_str());
2054 std::string err(
"Invalid pointer to gate class");
2055 PyErr_SetString(PyExc_Exception, err.c_str());
2059 PyObject* control_qbits_py = PyList_New((Py_ssize_t)control_qbits.size());
2060 for (
size_t i = 0; i < control_qbits.size(); i++) {
2061 PyList_SetItem(control_qbits_py, (Py_ssize_t)i,
Py_BuildValue(
"i", control_qbits[i]));
2064 return control_qbits_py;
2075 if (!PyArg_ParseTuple(args,
"O", &target_qbits_py)) {
2076 std::string err(
"Unable to parse arguments");
2077 PyErr_SetString(PyExc_Exception, err.c_str());
2081 if (!PyList_Check(target_qbits_py)) {
2082 PyErr_SetString(PyExc_TypeError,
"target_qbits must be a list!");
2086 std::vector<int> target_qbits;
2087 Py_ssize_t list_size = PyList_Size(target_qbits_py);
2088 for (Py_ssize_t i = 0; i < list_size; i++) {
2089 PyObject* item = PyList_GetItem(target_qbits_py, i);
2090 if (!PyLong_Check(item)) {
2091 PyErr_SetString(PyExc_TypeError,
"target_qbits must contain integers!");
2094 target_qbits.push_back(PyLong_AsLong(item));
2098 self->gate->set_target_qbits(target_qbits);
2100 catch (std::string err) {
2101 PyErr_SetString(PyExc_Exception, err.c_str());
2105 std::string err(
"Invalid pointer to gate class");
2106 PyErr_SetString(PyExc_Exception, err.c_str());
2120 PyObject* control_qbits_py = NULL;
2121 if (!PyArg_ParseTuple(args,
"O", &control_qbits_py)) {
2122 std::string err(
"Unable to parse arguments");
2123 PyErr_SetString(PyExc_Exception, err.c_str());
2127 if (!PyList_Check(control_qbits_py)) {
2128 PyErr_SetString(PyExc_TypeError,
"control_qbits must be a list!");
2132 std::vector<int> control_qbits;
2133 Py_ssize_t list_size = PyList_Size(control_qbits_py);
2134 for (Py_ssize_t i = 0; i < list_size; i++) {
2135 PyObject* item = PyList_GetItem(control_qbits_py, i);
2136 if (!PyLong_Check(item)) {
2137 PyErr_SetString(PyExc_TypeError,
"control_qbits must contain integers!");
2140 control_qbits.push_back(PyLong_AsLong(item));
2144 self->gate->set_control_qbits(control_qbits);
2146 catch (std::string err) {
2147 PyErr_SetString(PyExc_Exception, err.c_str());
2151 std::string err(
"Invalid pointer to gate class");
2152 PyErr_SetString(PyExc_Exception, err.c_str());
2167 std::vector<int> involved_qbits;
2170 involved_qbits =
self->gate->get_involved_qubits();
2172 catch (std::string err) {
2173 PyErr_SetString(PyExc_Exception, err.c_str());
2177 std::string err(
"Invalid pointer to gate class");
2178 PyErr_SetString(PyExc_Exception, err.c_str());
2182 PyObject* involved_qbits_py = PyList_New((Py_ssize_t)involved_qbits.size());
2183 for (
size_t i = 0; i < involved_qbits.size(); i++) {
2184 PyList_SetItem(involved_qbits_py, (Py_ssize_t)i,
Py_BuildValue(
"i", involved_qbits[i]));
2187 return involved_qbits_py;
2199 PyArrayObject * parameters_arr = NULL;
2203 if (!PyArg_ParseTuple(args,
"O", ¶meters_arr )) {
2204 PyErr_SetString(PyExc_ValueError,
"Unable to parse arguments");
2208 if( parameters_arr == NULL ) {
2209 PyErr_SetString(PyExc_ValueError,
"Missing input parameter array");
2213 if (PyArray_TYPE(parameters_arr) != NPY_DOUBLE) {
2214 PyErr_SetString(PyExc_TypeError,
"Parameter array must contain double values");
2218 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
2219 Py_INCREF(parameters_arr);
2222 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
2225 if (parameters_arr == NULL) {
2226 PyErr_SetString(PyExc_TypeError,
"Failed to cast parameter array to contiguous double format");
2236 extracted_parameters =
self->gate->extract_parameters( parameters_mtx );
2238 catch (std::string err) {
2239 Py_DECREF(parameters_arr);
2240 PyErr_SetString(PyExc_Exception, err.c_str());
2244 Py_DECREF(parameters_arr);
2245 std::string err(
"Invalid pointer to circuit class");
2246 PyErr_SetString(PyExc_Exception, err.c_str());
2254 if (extracted_parameters_py == NULL) {
2255 Py_DECREF(parameters_arr);
2261 PyArray_Dims new_shape;
2265 PyObject *extracted_parameters_py_flatten = PyArray_Newshape( (PyArrayObject*)extracted_parameters_py, &new_shape, NPY_CORDER);
2266 Py_DECREF(extracted_parameters_py);
2267 if (extracted_parameters_py_flatten == NULL) {
2268 Py_DECREF(parameters_arr);
2272 Py_DECREF(parameters_arr);
2273 return extracted_parameters_py_flatten;
2288 name =
self->gate->get_name();
2290 catch (std::string err) {
2291 PyErr_SetString(PyExc_Exception, err.c_str());
2295 std::string err(
"Invalid pointer to circuit class");
2296 PyErr_SetString(PyExc_Exception, err.c_str());
2300 return PyUnicode_FromString(name.c_str());
2311 PyObject* gate_state = PyDict_New();
2313 if( gate_state == NULL ) {
2314 std::string err(
"Failed to create dictionary");
2315 PyErr_SetString(PyExc_Exception, err.c_str());
2320 PyObject* val =
Py_BuildValue(
"i", self->gate->get_type() );
2321 if (val == NULL || PyDict_SetItemString(gate_state,
"type", val) != 0) {
2323 Py_DECREF(gate_state);
2329 if (val == NULL || PyDict_SetItemString(gate_state,
"qbit_num", val) != 0) {
2331 Py_DECREF(gate_state);
2337 if (val == NULL || PyDict_SetItemString(gate_state,
"target_qbit", val) != 0) {
2339 Py_DECREF(gate_state);
2345 if (val == NULL || PyDict_SetItemString(gate_state,
"control_qbit", val) != 0) {
2347 Py_DECREF(gate_state);
2353 std::vector<int> target_qbits =
self->gate->get_target_qbits();
2354 PyObject*
target_qbits_py = PyList_New((Py_ssize_t)target_qbits.size());
2355 if (target_qbits_py == NULL) {
2356 Py_DECREF(gate_state);
2359 for (
size_t i = 0; i < target_qbits.size(); i++) {
2361 if (item == NULL || PyList_SetItem(target_qbits_py, (Py_ssize_t)i, item) != 0) {
2363 Py_DECREF(target_qbits_py);
2364 Py_DECREF(gate_state);
2368 if (PyDict_SetItemString(gate_state,
"target_qbits", target_qbits_py) != 0) {
2369 Py_DECREF(target_qbits_py);
2370 Py_DECREF(gate_state);
2373 Py_DECREF(target_qbits_py);
2376 std::vector<int> control_qbits =
self->gate->get_control_qbits();
2377 PyObject* control_qbits_py = PyList_New((Py_ssize_t)control_qbits.size());
2378 if (control_qbits_py == NULL) {
2379 Py_DECREF(gate_state);
2382 for (
size_t i = 0; i < control_qbits.size(); i++) {
2384 if (item == NULL || PyList_SetItem(control_qbits_py, (Py_ssize_t)i, item) != 0) {
2386 Py_DECREF(control_qbits_py);
2387 Py_DECREF(gate_state);
2391 if (PyDict_SetItemString(gate_state,
"control_qbits", control_qbits_py) != 0) {
2392 Py_DECREF(control_qbits_py);
2393 Py_DECREF(gate_state);
2396 Py_DECREF(control_qbits_py);
2400 Matrix gate_mtx =
self->gate->get_matrix();
2403 if (gate_mtx_py == NULL) {
2404 Py_DECREF(gate_state);
2407 if (PyDict_SetItemString(gate_state,
"matrix", gate_mtx_py) != 0) {
2408 Py_DECREF(gate_mtx_py);
2409 Py_DECREF(gate_state);
2412 Py_DECREF(gate_mtx_py);
2414 catch (std::string err) {
2415 PyErr_SetString(PyExc_Exception, err.c_str());
2416 Py_DECREF(gate_state);
2420 PyErr_SetString(PyExc_Exception,
"Failed to serialize GENERAL_OPERATION matrix");
2421 Py_DECREF(gate_state);
2441 PyObject* gate_state = NULL;
2445 if (!PyArg_ParseTuple(args,
"O", &gate_state )) {
2446 PyErr_SetString(PyExc_ValueError,
"Unable to parse arguments");
2450 if( !PyDict_Check( gate_state ) ) {
2451 std::string err(
"Gate state should be given by a dictionary");
2452 PyErr_SetString(PyExc_Exception, err.c_str());
2457 if ( PyDict_Contains(gate_state, qbit_num_key) == 0 ) {
2458 std::string err(
"Gate state should contain the number of qubits");
2459 PyErr_SetString(PyExc_Exception, err.c_str());
2461 Py_DECREF( qbit_num_key );
2464 PyObject* qbit_num_py = PyDict_GetItem(gate_state, qbit_num_key);
2465 Py_DECREF( qbit_num_key );
2468 PyObject* target_qbit_key =
Py_BuildValue(
"s",
"target_qbit" );
2469 if ( PyDict_Contains(gate_state, target_qbit_key) == 0 ) {
2470 std::string err(
"Gate state should contain a target qubit");
2471 PyErr_SetString(PyExc_Exception, err.c_str());
2473 Py_DECREF( target_qbit_key );
2476 PyObject* target_qbit_py = PyDict_GetItem(gate_state, target_qbit_key);
2477 Py_DECREF( target_qbit_key );
2480 PyObject* control_qbit_key =
Py_BuildValue(
"s",
"control_qbit" );
2481 if ( PyDict_Contains(gate_state, control_qbit_key) == 0 ) {
2482 std::string err(
"Gate state should contain a control qubit (-1 for gates with no control qubits)");
2483 PyErr_SetString(PyExc_Exception, err.c_str());
2485 Py_DECREF( control_qbit_key );
2488 PyObject* control_qbit_py = PyDict_GetItem(gate_state, control_qbit_key);
2489 Py_DECREF( control_qbit_key );
2496 if ( PyDict_Contains(gate_state, type_key) == 0 ) {
2497 std::string err(
"Gate state should contain a type ID (see gate.h for the gate type IDs)");
2498 PyErr_SetString(PyExc_Exception, err.c_str());
2500 Py_DECREF( type_key );
2503 PyObject* type_py = PyDict_GetItem(gate_state, type_key);
2504 Py_DECREF( type_key );
2514 std::vector<int> target_qbits;
2515 PyObject* target_qbits_key =
Py_BuildValue(
"s",
"target_qbits" );
2516 if ( PyDict_Contains(gate_state, target_qbits_key) == 1 ) {
2517 PyObject*
target_qbits_py = PyDict_GetItem(gate_state, target_qbits_key);
2518 if (PyList_Check(target_qbits_py)) {
2519 Py_ssize_t list_size = PyList_Size(target_qbits_py);
2520 for (Py_ssize_t i = 0; i < list_size; i++) {
2521 PyObject* item = PyList_GetItem(target_qbits_py, i);
2522 if (PyLong_Check(item)) {
2523 target_qbits.push_back(PyLong_AsLong(item));
2528 Py_DECREF( target_qbits_key );
2531 std::vector<int> control_qbits;
2532 PyObject* control_qbits_key =
Py_BuildValue(
"s",
"control_qbits" );
2533 if ( PyDict_Contains(gate_state, control_qbits_key) == 1 ) {
2534 PyObject* control_qbits_py = PyDict_GetItem(gate_state, control_qbits_key);
2535 if (PyList_Check(control_qbits_py)) {
2536 Py_ssize_t list_size = PyList_Size(control_qbits_py);
2537 for (Py_ssize_t i = 0; i < list_size; i++) {
2538 PyObject* item = PyList_GetItem(control_qbits_py, i);
2539 if (PyLong_Check(item)) {
2540 control_qbits.push_back(PyLong_AsLong(item));
2545 Py_DECREF( control_qbits_key );
2549 switch (gate_type) {
2660 if (!target_qbits.empty()) {
2662 gate = create_multi_target_gate<RXX>(
qbit_num, target_qbits );
2665 std::vector<int> swap_targets = {
target_qbit, control_qbit};
2666 gate = create_multi_target_gate<RXX>(
qbit_num, swap_targets );
2671 if (!target_qbits.empty()) {
2673 gate = create_multi_target_gate<RYY>(
qbit_num, target_qbits );
2676 std::vector<int> swap_targets = {
target_qbit, control_qbit};
2677 gate = create_multi_target_gate<RYY>(
qbit_num, swap_targets );
2682 if (!target_qbits.empty()) {
2684 gate = create_multi_target_gate<RZZ>(
qbit_num, target_qbits );
2687 std::vector<int> swap_targets = {
target_qbit, control_qbit};
2688 gate = create_multi_target_gate<RZZ>(
qbit_num, swap_targets );
2693 if (!target_qbits.empty()) {
2695 gate = create_multi_target_gate<SWAP>(
qbit_num, target_qbits );
2698 std::vector<int> swap_targets = {
target_qbit, control_qbit};
2699 gate = create_multi_target_gate<SWAP>(
qbit_num, swap_targets );
2704 if (!control_qbits.empty()) {
2708 std::string err(
"CCX gate requires control_qbits vector");
2709 PyErr_SetString(PyExc_Exception, err.c_str());
2715 if (!target_qbits.empty() && !control_qbits.empty()) {
2717 gate = create_multi_target_controlled_gate<CSWAP>(
qbit_num, target_qbits, control_qbits );
2719 std::string err(
"CSWAP gate requires both target_qbits and control_qbits vectors");
2720 PyErr_SetString(PyExc_Exception, err.c_str());
2730 std::string err(
"Unsupported gate type: block operation");
2731 PyErr_SetString(PyExc_Exception, err.c_str());
2735 gate =
new Gate(qbit_num);
2738 if (PyDict_Contains(gate_state, matrix_key) == 0) {
2739 Py_DECREF(matrix_key);
2740 std::string err(
"GENERAL_OPERATION gate state should contain a matrix");
2741 PyErr_SetString(PyExc_Exception, err.c_str());
2746 PyObject* matrix_obj = PyDict_GetItem(gate_state, matrix_key);
2747 Py_DECREF(matrix_key);
2749 PyArrayObject* matrix_arr = (PyArrayObject*)PyArray_FROM_OTF(matrix_obj, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
2750 if (matrix_arr == NULL) {
2757 Py_DECREF(matrix_arr);
2759 if (!target_qbits.empty()) {
2761 }
else if (target_qbit >= 0) {
2765 if (!control_qbits.empty()) {
2767 }
else if (control_qbit >= 0) {
2774 std::string err(
"Unsupported gate type");
2775 PyErr_SetString(PyExc_Exception, err.c_str());
2779 delete(
self->gate );
2782 catch (std::string err) {
2783 PyErr_SetString(PyExc_Exception, err.c_str());
2787 std::string err(
"Invalid pointer to circuit class");
2788 PyErr_SetString(PyExc_Exception, err.c_str());
2803 #define GATE_WRAPPER_BASE_METHODS \ 2804 {"get_Matrix", (PyCFunction) Gate_Wrapper_get_Matrix, METH_VARARGS | METH_KEYWORDS, \ 2805 "Method to get the matrix representation of the gate." \ 2807 {"apply_to", (PyCFunction) Gate_Wrapper_Wrapper_apply_to, METH_VARARGS | METH_KEYWORDS, \ 2808 "Call to apply the gate on an input state/matrix." \ 2810 {"apply_derivate_to", (PyCFunction) Gate_Wrapper_Wrapper_apply_derivate_to, METH_VARARGS | METH_KEYWORDS, \ 2811 "Call to evaluate derivatives of the gate action on an input state/matrix." \ 2813 {"apply_to_combined", (PyCFunction) Gate_Wrapper_Wrapper_apply_to_combined, METH_VARARGS | METH_KEYWORDS, \ 2814 "Call to evaluate forward gate action and all derivatives in one call." \ 2816 {"apply_from_right", (PyCFunction) Gate_Wrapper_Wrapper_apply_from_right, METH_VARARGS | METH_KEYWORDS, \ 2817 "Call to apply the gate from right side on an input state/matrix." \ 2819 {"apply_to_list", (PyCFunction) Gate_Wrapper_Wrapper_apply_to_list, METH_VARARGS | METH_KEYWORDS, \ 2820 "Call to apply the gate on a list of input states/matrices." \ 2822 {"get_Gate_Kernel", (PyCFunction) Gate_Wrapper_get_Gate_Kernel, METH_VARARGS | METH_KEYWORDS, \ 2823 "Call to calculate the gate matrix acting on a single qbit space." \ 2825 {"get_Parameter_Num", (PyCFunction) Gate_Wrapper_get_Parameter_Num, METH_NOARGS, \ 2826 "Call to get the number of free parameters in the gate." \ 2828 {"get_Parameter_Start_Index", (PyCFunction) Gate_Wrapper_get_Parameter_Start_Index, METH_NOARGS, \ 2829 "Call to get the starting index of the parameters in the parameter array corresponding to the circuit in which the current gate is incorporated." \ 2831 {"get_Target_Qbit", (PyCFunction) Gate_Wrapper_get_Target_Qbit, METH_NOARGS, \ 2832 "Call to get the target qbit." \ 2834 {"get_Control_Qbit", (PyCFunction) Gate_Wrapper_get_Control_Qbit, METH_NOARGS, \ 2835 "Call to get the control qbit (returns with -1 if no control qbit is used in the gate)." \ 2837 {"get_Target_Qbits", (PyCFunction) Gate_Wrapper_get_Target_Qbits, METH_NOARGS, \ 2838 "Call to get the target qubits as a list." \ 2840 {"get_Control_Qbits", (PyCFunction) Gate_Wrapper_get_Control_Qbits, METH_NOARGS, \ 2841 "Call to get the control qubits as a list." \ 2843 {"set_Target_Qbit", (PyCFunction) Gate_Wrapper_set_Target_Qbit, METH_VARARGS, \ 2844 "Call to set the target qubits from a list." \ 2846 {"set_Control_Qbit", (PyCFunction) Gate_Wrapper_set_Control_Qbit, METH_VARARGS, \ 2847 "Call to set the control qubits from a list." \ 2849 {"set_Target_Qbits", (PyCFunction) Gate_Wrapper_set_Target_Qbits, METH_VARARGS, \ 2850 "Call to set the target qubits from a list." \ 2852 {"set_Control_Qbits", (PyCFunction) Gate_Wrapper_set_Control_Qbits, METH_VARARGS, \ 2853 "Call to set the control qubits from a list." \ 2855 {"get_Involved_Qbits", (PyCFunction) Gate_Wrapper_get_Involved_Qbits, METH_NOARGS, \ 2856 "Call to get the target qubits as a list." \ 2858 {"Extract_Parameters", (PyCFunction) Gate_Wrapper_Extract_Parameters, METH_VARARGS, \ 2859 "Call to extract the paramaters corresponding to the gate, from a parameter array associated to the circuit in which the gate is embedded." \ 2861 {"get_Name", (PyCFunction) Gate_Wrapper_get_Name, METH_NOARGS, \ 2862 "Method to get the name label of the gate" \ 2869 "Method to extract the stored quantum gate in a human-readable data serialized and pickle-able format" 2872 "Call to set the state of quantum gate from a human-readable data serialized and pickle-able format" 2893 ob_base.ob_size = 0;
2897 tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
2898 tp_doc =
"Object to represent python binding for a generic base gate of the Squander package.";
2911 #define gate_wrapper_type_template(gate_name, wrapper_new) \ 2912 struct gate_name##_Wrapper_Type : Gate_Wrapper_Type_tmp { \ 2913 gate_name##_Wrapper_Type() { \ 2914 tp_name = #gate_name; \ 2915 tp_doc = "Object to represent python binding for a " #gate_name " gate of the Squander package."; \ 2916 tp_new = (newfunc) wrapper_new< gate_name>; \ 2917 tp_base = &Gate_Wrapper_Type; \ 2920 static gate_name##_Wrapper_Type gate_name##_Wrapper_Type_ins; 2927 tp_doc =
"Object to represent python binding for a SWAP gate of the Squander package.";
2928 tp_new = (newfunc) multi_target_gate_Wrapper_new<SWAP>;
2938 tp_doc =
"Object to represent python binding for a RXX gate of the Squander package.";
2939 tp_new = (newfunc) multi_target_gate_Wrapper_new<RXX>;
2949 tp_doc =
"Object to represent python binding for a RYY gate of the Squander package.";
2950 tp_new = (newfunc) multi_target_gate_Wrapper_new<RYY>;
2960 tp_doc =
"Object to represent python binding for a RZZ gate of the Squander package.";
2961 tp_new = (newfunc) multi_target_gate_Wrapper_new<RZZ>;
2972 tp_doc =
"Object to represent python binding for a CCX gate of the Squander package.";
2973 tp_new = (newfunc) multi_control_gate_Wrapper_new<CCX>;
2983 tp_doc =
"Object to represent python binding for a CSWAP gate of the Squander package.";
2984 tp_new = (newfunc) multi_target_controlled_gate_Wrapper_new<CSWAP>;
3059 PyModuleDef_HEAD_INIT,
3061 "Python binding for gates implemented in Squander C++",
3065 #define Py_INCREF_template(gate_name) \ 3066 Py_INCREF(&gate_name##_Wrapper_Type_ins); \ 3067 if (PyModule_AddObject(m, #gate_name, (PyObject *) &gate_name##_Wrapper_Type_ins) < 0) { \ 3068 Py_DECREF(&gate_name##_Wrapper_Type_ins); \ 3084 PyObject * m= PyModule_Create(& gates_Wrapper_Module);
3089 if (PyType_Ready(&Gate_Wrapper_Type) < 0 ||
3090 PyType_Ready(&CH_Wrapper_Type_ins) < 0 ||
3091 PyType_Ready(&CNOT_Wrapper_Type_ins) < 0 ||
3092 PyType_Ready(&CZ_Wrapper_Type_ins) < 0 ||
3093 PyType_Ready(&CRY_Wrapper_Type_ins) < 0 ||
3094 PyType_Ready(&CRX_Wrapper_Type_ins) < 0 ||
3095 PyType_Ready(&CRZ_Wrapper_Type_ins) < 0 ||
3096 PyType_Ready(&CP_Wrapper_Type_ins) < 0 ||
3097 PyType_Ready(&H_Wrapper_Type_ins) < 0 ||
3098 PyType_Ready(&RX_Wrapper_Type_ins) < 0 ||
3099 PyType_Ready(&RXX_Wrapper_Type_ins) < 0 ||
3100 PyType_Ready(&RYY_Wrapper_Type_ins) < 0 ||
3101 PyType_Ready(&RZZ_Wrapper_Type_ins) < 0 ||
3102 PyType_Ready(&RY_Wrapper_Type_ins) < 0 ||
3103 PyType_Ready(&RZ_Wrapper_Type_ins) < 0 ||
3104 PyType_Ready(&SX_Wrapper_Type_ins) < 0 ||
3105 PyType_Ready(&SXdg_Wrapper_Type_ins) < 0 ||
3106 PyType_Ready(&SYC_Wrapper_Type_ins) < 0 ||
3107 PyType_Ready(&U1_Wrapper_Type_ins) < 0 ||
3108 PyType_Ready(&U2_Wrapper_Type_ins) < 0 ||
3109 PyType_Ready(&U3_Wrapper_Type_ins) < 0 ||
3110 PyType_Ready(&CU_Wrapper_Type_ins) < 0 ||
3111 PyType_Ready(&X_Wrapper_Type_ins) < 0 ||
3112 PyType_Ready(&Y_Wrapper_Type_ins) < 0 ||
3113 PyType_Ready(&Z_Wrapper_Type_ins) < 0 ||
3114 PyType_Ready(&S_Wrapper_Type_ins) < 0 ||
3115 PyType_Ready(&SDG_Wrapper_Type_ins) < 0 ||
3116 PyType_Ready(&T_Wrapper_Type_ins) < 0 ||
3117 PyType_Ready(&Tdg_Wrapper_Type_ins) < 0 ||
3118 PyType_Ready(&CR_Wrapper_Type_ins) < 0 ||
3119 PyType_Ready(&CROT_Wrapper_Type_ins) < 0 ||
3120 PyType_Ready(&CCX_Wrapper_Type_ins) < 0 ||
3121 PyType_Ready(&SWAP_Wrapper_Type_ins) < 0 ||
3122 PyType_Ready(&CSWAP_Wrapper_Type_ins) < 0 ||
3123 PyType_Ready(&R_Wrapper_Type_ins) < 0 ) {
3130 Py_INCREF(&Gate_Wrapper_Type);
3131 if (PyModule_AddObject(m,
"Gate", (PyObject *) & Gate_Wrapper_Type) < 0) {
3132 Py_DECREF(& Gate_Wrapper_Type);
3186 Py_INCREF(&SDG_Wrapper_Type_ins);
3187 if (PyModule_AddObject(m,
"Sdg", (PyObject *) & SDG_Wrapper_Type_ins) < 0) {
3188 Py_DECREF(& SDG_Wrapper_Type_ins);
3193 Py_INCREF(&SXdg_Wrapper_Type_ins);
3194 if (PyModule_AddObject(m,
"SXdg", (PyObject *) & SXdg_Wrapper_Type_ins) < 0) {
3195 Py_DECREF(& SXdg_Wrapper_Type_ins);
3202 Py_INCREF(&Tdg_Wrapper_Type_ins);
3203 if (PyModule_AddObject(m,
"Tdg", (PyObject *) & Tdg_Wrapper_Type_ins) < 0) {
3204 Py_DECREF(& Tdg_Wrapper_Type_ins);
static PyObject * Gate_Wrapper_set_Control_Qbit(Gate_Wrapper *self, PyObject *args)
Call to set the target qbit.
Copyright (C) Miklos Maroti, 2021 SPDX-License-Identifier: Apache-2.0.
static PyObject * Gate_Wrapper_getstate(Gate_Wrapper *self)
Method to extract the stored quantum gate in a human-readable data serialized and pickle-able format...
Gate * create_multi_target_controlled_gate(int qbit_num, const std::vector< int > &target_qbits, const std::vector< int > &control_qbits)
Header file for a class representing a CSWAP (Controlled SWAP) operation.
static PyObject * Gate_Wrapper_set_Target_Qbits(Gate_Wrapper *self, PyObject *args)
Call to set the target qubits from a Python list.
A class representing a RXX gate.
Header file for a class representing a CP gate.
Gate * create_controlled_gate(int qbit_num, int target_qbit, int control_qbit)
parameter_num
[set adaptive gate structure]
static PyObject * multi_target_controlled_gate_Wrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Generic wrapper for multi-target controlled gates (e.g., CSWAP)
Header file for a class for the representation of general gate operations.
void set_control_qbits(const std::vector< int > &control_qbits_in)
Call to set the control qubits for the gate operation.
Class to store single-precision real arrays and properties.
A class representing a CCX (Toffoli) operation.
Header file for a class representing a controlled Z rotation gate.
#define GATE_WRAPPER_BASE_METHODS
Structure containing metadata about the methods of class qgd_U3.
PyMODINIT_FUNC PyInit_gates_Wrapper(void)
Method called when the Python module is initialized.
static PyObject * generic_Gate_Wrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Method called when a python instance of the class qgd_CH_Wrapper is allocated.
Gate * create_multi_target_gate(int qbit_num, const std::vector< int > &target_qbits)
static PyObject * Gate_Wrapper_Wrapper_apply_to_combined(Gate_Wrapper *self, PyObject *args, PyObject *kwds)
Call to evaluate forward gate action and all derivatives in one call.
A class representing a controlled RX gate.
A class representing a CP gate.
static PyObject * Gate_Wrapper_Wrapper_apply_to_list(Gate_Wrapper *self, PyObject *args, PyObject *kwds)
Call to apply the gate operation on a list of input states or matrices.
static PyObject * Gate_Wrapper_get_Involved_Qbits(Gate_Wrapper *self)
Call to get the target qubits vector.
static PyObject * Gate_Wrapper_get_Matrix(Gate_Wrapper *self, PyObject *args, PyObject *kwds)
Call te extract t he matric representation of the gate.
virtual std::vector< Matrix > apply_derivate_to(Matrix_real ¶meters_mtx_in, Matrix &input, int parallel)
Call to evaluate the derivate of the circuit on an inout with respect to all of the free parameters...
static PyObject * Gate_Wrapper_Extract_Parameters(Gate_Wrapper *self, PyObject *args)
Call to extract the paramaters corresponding to the gate, from a parameter array associated to the ci...
int stride
The column stride of the array. (The array elements in one row are a_0, a_1, ... a_{cols-1}, 0, 0, 0, 0. The number of zeros is stride-cols)
Header file for a class representing a controlled rotation gate around the Y axis.
PyObject_HEAD Gate * gate
Pointer to the C++ class of the CH gate.
return Py_BuildValue("i", 0)
static PyModuleDef gates_Wrapper_Module
Structure containing metadata about the module.
Matrix_real numpy2matrix_real(PyArrayObject *arr)
Call to create a PIC matrix_real representation of a numpy array.
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
static PyObject * Gate_Wrapper_get_Gate_Kernel(Gate_Wrapper *self, PyObject *args, PyObject *kwds)
Calculate the matrix of a U3 gate gate corresponding to the given parameters acting on a single qbit ...
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.
static SWAP_Wrapper_Type SWAP_Wrapper_Type_ins
#define Py_INCREF_template(gate_name)
static PyObject * Gate_Wrapper_get_Parameter_Num(Gate_Wrapper *self)
Call to get the number of free parameters in the gate.
PyObject * matrix_real_to_numpy(Matrix_real &mtx)
Call to make a numpy array from an instance of matrix class.
A class representing a SWAP operation.
U3 RX RZ H Y SX S T CNOT CH SYC CRZ PyObject PyObject * kwds
static PyObject * Gate_Wrapper_Wrapper_apply_derivate_to(Gate_Wrapper *self, PyObject *args, PyObject *kwds)
Call to evaluate derivatives of the gate action on an input state or matrix.
static PyObject * Gate_Wrapper_get_Parameter_Start_Index(Gate_Wrapper *self)
Call to get the starting index of the parameters in the parameter array corresponding to the circuit ...
Matrix_real_float numpy2matrix_real_float(PyArrayObject *arr)
Call to create a PIC matrix_real_float representation of a numpy array.
Header file for a class representing a CCX (Toffoli) operation.
scalar * get_data() const
Call to get the pointer to the stored data.
static Matrix calc_one_qubit_u3(double ThetaOver2=0.0, double Phi=0.0, double Lambda=0.0)
Build a 2x2 U3 kernel from angles (theta/2, phi, lambda).
static PyObject * Gate_Wrapper_set_Control_Qbits(Gate_Wrapper *self, PyObject *args)
Call to set the control qubits from a Python list.
static PyObject * controlled_gate_Wrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Method called when a python instance of a controlled gate class is initialized.
Class representing a RZZ gate.
static void matrix_owner_capsule_destruct(PyObject *cap)
Capsule destructor: calls delete on a heap-allocated Matrix, which correctly decrements the reference...
static void matrix_float_owner_capsule_destruct(PyObject *cap)
Capsule destructor for heap-allocated Matrix_float.
A class representing a RYY gate.
virtual Matrix get_matrix(Matrix_real ¶meters, int parallel)
Call to retrieve the gate matrix.
static void Gate_Wrapper_dealloc(Gate_Wrapper *self)
Method called when a python instance of the class Gate_Wrapper is destroyed.
A class representing a CROT gate.
static PyObject * Gate_Wrapper_get_Target_Qbits(Gate_Wrapper *self)
Call to get the target qubits vector.
A class representing a CZ operation.
Header file for a class representing a CNOT operation.
static PyObject * Gate_Wrapper_get_Target_Qbit(Gate_Wrapper *self)
Call to get the target qbit.
static PyObject * Gate_Wrapper_set_Target_Qbit(Gate_Wrapper *self, PyObject *args)
Call to set the target qbit.
A class representing a CRY gate.
virtual void apply_from_right(Matrix &input)
Call to apply the gate on the input array/matrix by input*Gate.
U3 RX RZ H Y SX S T CNOT CH SYC CRZ PyObject * args
int rows
The number of rows.
A class representing a CH operation.
int cols
The number of columns.
static PyObject * Gate_Wrapper_setstate(Gate_Wrapper *self, PyObject *args)
Call to set the state of quantum gate from a human-readable data serialized and pickle-able format...
static RZZ_Wrapper_Type RZZ_Wrapper_Type_ins
static PyObject * multi_control_gate_Wrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Generic wrapper for single-target multi-control gates (e.g., CCX)
static int Gate_Wrapper_init(Gate_Wrapper *self, PyObject *args, PyObject *kwds)
Method called when a python instance of a non-controlled gate class is initialized.
static Gate_Wrapper_Type_tmp Gate_Wrapper_Type
void set_control_qbit(int control_qbit_in)
Call to set the control qubit for the gate operation.
Header file for a class representing a CZ operation.
static PyObject * qbit_gate_Wrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Method called when a python instance of a qbit-only gate class is initialized.
void set_target_qbit(int target_qbit_in)
Call to set the target qubit for the gate operation.
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...
A class representing a RZZ gate.
Structure type representing complex numbers in the SQUANDER package.
A class representing a CNOT operation.
void set_matrix(Matrix input)
Call to set the stored matrix in the operation.
static PyObject * Gate_Wrapper_Wrapper_apply_to(Gate_Wrapper *self, PyObject *args, PyObject *kwds)
Call to apply the gate operation on an input state or matrix.
Double-precision complex matrix (float64).
int size() const
Call to get the number of the allocated elements.
#define gate_wrapper_type_template(gate_name, wrapper_new)
Gate * create_qbit_gate(int qbit_num)
Matrix_float numpy2matrix_float(PyArrayObject *arr)
Call to create a PIC matrix_float representation of a numpy array.
static PyObject * Gate_Wrapper_get_Name(Gate_Wrapper *self)
Extract the optimized parameters.
A class representing a controlled RZ gate.
A class representing a CRY gate.
virtual int get_parameter_num()
Call to get the number of free parameters.
static PyObject * Gate_Wrapper_get_Control_Qbit(Gate_Wrapper *self)
Call to get the control qbit (returns with -1 if no control qbit is used in the gate) ...
Gate * create_gate(int qbit_num, int target_qbit)
virtual Matrix gate_kernel(const Matrix_real &precomputed_sincos)
Compute the gate kernel matrix from precomputed trigonometric values.
Single-precision complex matrix (float32).
virtual std::vector< Matrix > apply_to_combined(Matrix_real ¶meters_mtx_in, Matrix &input, int parallel)
Combined forward + derivative application with shared precomputed trig cache.
static RYY_Wrapper_Type RYY_Wrapper_Type_ins
Type definition of the Gate_Wrapper Python class of the gates module.
Base class for the representation of general gate operations.
PyObject * matrix_float_to_numpy(Matrix_float &mtx)
Call to make a numpy array from an instance of matrix_float class.
void set_target_qbits(const std::vector< int > &target_qbits_in)
Call to set the target qubits for the gate operation.
static PyMethodDef Gate_Wrapper_methods[]
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.
A class representing a SYC operation.
static PyObject * multi_target_gate_Wrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Generic wrapper for multi-target gates without control (e.g., SWAP)
static PyMemberDef Gate_Wrapper_members[]
Structure containing metadata about the members of class qgd_CH_Wrapper.
static PyObject * Gate_Wrapper_Wrapper_apply_from_right(Gate_Wrapper *self, PyObject *args, PyObject *kwds)
Call to apply the gate operation from the right side on an input state or matrix. ...
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...
Gate * create_multi_qubit_gate(int qbit_num, int target_qbit, const std::vector< int > &control_qbits)
virtual void apply_to(Matrix &input, int parallel)
Call to apply the gate on the input array/matrix.
static CCX_Wrapper_Type CCX_Wrapper_Type_ins
static CSWAP_Wrapper_Type CSWAP_Wrapper_Type_ins
PyObject * matrix_to_numpy(Matrix &mtx)
Call to make a numpy array from an instance of matrix class.
static PyObject * Gate_Wrapper_get_Control_Qbits(Gate_Wrapper *self)
Call to get the control qubits vector.
static RXX_Wrapper_Type RXX_Wrapper_Type_ins
PyObject * target_qbits_py
Class to store data of complex arrays and its properties.
static PyObject * Gate_Wrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Method called when a python instance of a non-controlled gate class is initialized.
A class representing a CSWAP (Controlled SWAP) operation.
Class representing a RYY gate.
Header file for a class representing a Sycamore gate.