23 #define PY_SSIZE_T_CLEAN 24 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION 27 #include <numpy/arrayobject.h> 28 #include "structmember.h" 83 if (instance != NULL ) {
103 if ( self->vqe != NULL ) {
109 if ( self->Hamiltonian != NULL ) {
111 Py_DECREF(self->Hamiltonian);
112 self->Hamiltonian = NULL;
115 Py_TYPE(
self)->tp_free((PyObject *)
self);
131 self->Hamiltonian = NULL;
133 return (PyObject *)
self;
147 static char *kwlist[] = {(
char*)
"Hamiltonian_data", (
char*)
"Hamiltonian_indices", (
char*)
"Hamiltonian_indptr", (
char*)
"qbit_num", (
char*)
"config", (
char*)
"accelerator_num", NULL};
150 PyArrayObject *Hamiltonian_data_arg = NULL;
151 PyArrayObject *Hamiltonian_indices_arg = NULL;
152 PyArrayObject *Hamiltonian_indptr_arg = NULL;
154 PyObject *config_arg = NULL;
155 int accelerator_num = 0;
158 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|OOOiOi", kwlist,
159 &Hamiltonian_data_arg, &Hamiltonian_indices_arg, &Hamiltonian_indptr_arg, &qbit_num, &config_arg, &accelerator_num))
164 if ( Hamiltonian_data_arg == NULL )
return -1;
166 Hamiltonian_data_arg = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)Hamiltonian_data_arg, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
168 int NNZ =
static_cast<int>(PyArray_DIMS(Hamiltonian_data_arg)[0]);
170 if ( Hamiltonian_indices_arg == NULL )
return -1;
172 Hamiltonian_indices_arg = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)Hamiltonian_indices_arg, NPY_INT32, NPY_ARRAY_IN_ARRAY);
173 int* Hamiltonian_indices = (
int*)PyArray_DATA(Hamiltonian_indices_arg);
175 if ( Hamiltonian_indptr_arg == NULL )
return -1;
177 Hamiltonian_indptr_arg = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)Hamiltonian_indptr_arg, NPY_INT32, NPY_ARRAY_IN_ARRAY);
178 int* Hamiltonian_indptr = (
int*)PyArray_DATA(Hamiltonian_indptr_arg);
183 std::map<std::string, Config_Element>
config;
187 PyObject *
key, *value;
190 while (PyDict_Next(config_arg, &pos, &key, &value)) {
193 PyObject* key_string = PyObject_Str(key);
194 PyObject* key_string_unicode = PyUnicode_AsEncodedString(key_string,
"utf-8",
"~E~");
195 const char* key_C = PyBytes_AS_STRING(key_string_unicode);
197 std::string key_Cpp( key_C );
200 if (PyBool_Check(value)) {
202 config[key_Cpp] = element;
204 else if ( PyLong_Check( value ) ) {
205 element.
set_property( key_Cpp, PyLong_AsLongLong( value ) );
206 config[ key_Cpp ] = element;
208 else if ( PyFloat_Check( value ) ) {
209 element.
set_property( key_Cpp, PyFloat_AsDouble( value ) );
210 config[ key_Cpp ] = element;
224 std::cout <<
"The number of qubits should be given as a positive integer, " << qbit_num <<
" was given" << std::endl;
245 self->vqe->get_optimized_parameters(parameters);
252 return parameter_arr;
262 self->vqe->start_optimization();
264 catch (std::string err) {
265 PyErr_SetString(PyExc_Exception, err.c_str());
266 std::cout << err << std::endl;
270 std::string err(
"Invalid pointer to decomposition class");
271 PyErr_SetString(PyExc_Exception, err.c_str());
291 qbit_num =
self->vqe->get_qbit_num();
293 catch (std::string err) {
294 PyErr_SetString(PyExc_Exception, err.c_str());
295 std::cout << err << std::endl;
299 std::string err(
"Invalid pointer to decomposition class");
300 PyErr_SetString(PyExc_Exception, err.c_str());
317 PyArrayObject * parameters_arr = NULL;
321 if (!PyArg_ParseTuple(args,
"|O", ¶meters_arr ))
325 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
326 Py_INCREF(parameters_arr);
329 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
338 self->vqe->set_optimized_parameters(parameters_mtx.
get_data(), parameters_mtx.
size());
340 catch (std::string err ) {
341 PyErr_SetString(PyExc_Exception, err.c_str());
345 std::string err(
"Invalid pointer to decomposition class");
346 PyErr_SetString(PyExc_Exception, err.c_str());
350 Py_DECREF(parameters_arr);
363 PyArrayObject * initial_state_arg = NULL;
366 if (!PyArg_ParseTuple(args,
"|O", &initial_state_arg )) {
367 PyErr_SetString(PyExc_Exception,
"error occured during input parsing");
371 if ( PyArray_IS_C_CONTIGUOUS(initial_state_arg) ) {
372 Py_INCREF(initial_state_arg);
375 initial_state_arg = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)initial_state_arg, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
384 self->vqe->set_initial_state( initial_state_mtx );
386 catch (std::string err ) {
387 PyErr_SetString(PyExc_Exception, err.c_str());
391 std::string err(
"Invalid pointer to decomposition class");
392 PyErr_SetString(PyExc_Exception, err.c_str());
399 Py_DECREF(initial_state_arg);
412 PyObject* density_noise_arg = NULL;
413 if (!PyArg_ParseTuple(args,
"|O", &density_noise_arg )) {
414 PyErr_SetString(PyExc_Exception,
"error occured during density-noise input parsing");
418 std::vector<DensityNoiseSpec> density_noise_specs;
419 if (density_noise_arg != NULL && density_noise_arg != Py_None) {
420 if (!PyList_Check(density_noise_arg)) {
421 PyErr_SetString(PyExc_Exception,
"density_noise should be given as a list of dictionaries");
425 for (Py_ssize_t idx = 0; idx < PyList_Size(density_noise_arg); ++idx) {
426 PyObject* noise_item = PyList_GetItem(density_noise_arg, idx);
427 if (!PyDict_Check(noise_item)) {
428 PyErr_SetString(PyExc_Exception,
"Each density_noise item should be a dictionary");
432 PyObject* channel_obj = PyDict_GetItemString(noise_item,
"channel");
433 PyObject* target_obj = PyDict_GetItemString(noise_item,
"target");
434 PyObject* after_gate_index_obj = PyDict_GetItemString(noise_item,
"after_gate_index");
435 PyObject* value_obj = PyDict_GetItemString(noise_item,
"value");
436 if (!channel_obj || !target_obj || !after_gate_index_obj || !value_obj) {
437 PyErr_SetString(PyExc_Exception,
"Each density_noise item should define channel, target, after_gate_index, and value");
441 PyObject* channel_unicode = PyUnicode_AsEncodedString(channel_obj,
"utf-8",
"~E~");
442 if (channel_unicode == NULL) {
443 PyErr_SetString(PyExc_Exception,
"density_noise channel should be a UTF-8 string");
447 const char* channel_C = PyBytes_AS_STRING(channel_unicode);
448 std::string channel(channel_C);
449 Py_DECREF(channel_unicode);
452 if (channel ==
"local_depolarizing") {
455 else if (channel ==
"amplitude_damping") {
458 else if (channel ==
"phase_damping") {
462 std::string err(
"Unsupported density_noise channel: " + channel);
463 PyErr_SetString(PyExc_Exception, err.c_str());
469 spec.
value = PyFloat_AsDouble(value_obj);
470 if (PyErr_Occurred()) {
471 PyErr_SetString(PyExc_Exception,
"Failed to parse density_noise numeric values");
475 density_noise_specs.push_back(spec);
480 self->vqe->set_density_noise_specs( density_noise_specs );
482 catch (std::string err ) {
483 PyErr_SetString(PyExc_Exception, err.c_str());
487 std::string err(
"Invalid pointer to decomposition class");
488 PyErr_SetString(PyExc_Exception, err.c_str());
503 auto set_dict_item = [](PyObject* dict,
const char*
key, PyObject* value) ->
int {
508 int status = PyDict_SetItemString(dict, key, value);
512 auto new_none = []() -> PyObject* {
518 PyObject* operations_list = NULL;
521 std::vector<DensityBridgeOperationInfo> operations =
522 self->vqe->inspect_density_bridge();
527 result = PyDict_New();
528 if (result == NULL) {
532 operations_list = PyList_New((Py_ssize_t)operations.size());
533 if (operations_list == NULL) {
538 for (
size_t idx = 0; idx < operations.size(); ++idx) {
539 const auto& operation = operations[idx];
540 if (operation.is_unitary) {
547 PyObject* op_dict = PyDict_New();
548 if (op_dict == NULL) {
549 Py_DECREF(operations_list);
554 if (set_dict_item(op_dict,
"index", PyLong_FromLong((
long)idx)) != 0 ||
558 PyUnicode_FromString(operation.is_unitary ?
"gate" :
"noise")
561 op_dict,
"name", PyUnicode_FromString(operation.name.c_str())
563 set_dict_item(op_dict,
"is_unitary", PyBool_FromLong(operation.is_unitary ? 1 : 0)) != 0 ||
567 PyLong_FromLong(operation.source_gate_index)
570 op_dict,
"target_qbit", PyLong_FromLong(operation.target_qbit)
575 operation.control_qbit >= 0
576 ? PyLong_FromLong(operation.control_qbit)
580 op_dict,
"param_count", PyLong_FromLong(operation.param_count)
583 op_dict,
"param_start", PyLong_FromLong(operation.param_start)
588 operation.has_fixed_value
589 ? PyFloat_FromDouble(operation.fixed_value)
593 Py_DECREF(operations_list);
598 PyList_SET_ITEM(operations_list, (Py_ssize_t)idx, op_dict);
601 if (set_dict_item(result,
"backend", PyUnicode_FromString(
"density_matrix")) != 0 ||
605 PyUnicode_FromString(
606 self->vqe->get_density_bridge_source_label().c_str()
610 result,
"qbit_num", PyLong_FromLong(self->vqe->get_qbit_num())
615 PyLong_FromLong(self->vqe->get_parameter_num())
620 PyLong_FromLong((
long)operations.size())
622 set_dict_item(result,
"gate_count", PyLong_FromLong(gate_count)) != 0 ||
623 set_dict_item(result,
"noise_count", PyLong_FromLong(noise_count)) != 0 ||
624 PyDict_SetItemString(result,
"operations", operations_list) != 0) {
625 Py_DECREF(operations_list);
630 Py_DECREF(operations_list);
633 catch (std::string err) {
634 Py_XDECREF(operations_list);
636 PyErr_SetString(PyExc_Exception, err.c_str());
640 Py_XDECREF(operations_list);
642 std::string err(
"Invalid pointer to decomposition class");
643 PyErr_SetString(PyExc_Exception, err.c_str());
658 PyObject* filename_py=NULL;
661 if (!PyArg_ParseTuple(args,
"|O", &filename_py ))
return Py_BuildValue(
"i", -1);
664 PyObject* filename_string = PyObject_Str(filename_py);
665 PyObject* filename_string_unicode = PyUnicode_AsEncodedString(filename_string,
"utf-8",
"~E~");
666 const char* filename_C = PyBytes_AS_STRING(filename_string_unicode);
667 std::string filename_str( filename_C );
671 self->vqe->set_gate_structure( filename_str );
673 catch (std::string err ) {
674 PyErr_SetString(PyExc_Exception, err.c_str());
678 std::string err(
"Invalid pointer to decomposition class");
679 PyErr_SetString(PyExc_Exception, err.c_str());
696 if (!PyArg_ParseTuple(args,
"|d", &tolerance ))
return Py_BuildValue(
"i", -1);
700 self->vqe->set_optimization_tolerance( tolerance );
711 PyArrayObject * parameters_arr = NULL;
712 PyArrayObject * unitary_arg = NULL;
716 if (!PyArg_ParseTuple(args,
"|OO", ¶meters_arr, &unitary_arg ))
720 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
721 Py_INCREF(parameters_arr);
724 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
732 if ( unitary_arg == NULL ) {
733 PyErr_SetString(PyExc_Exception,
"Input matrix was not given");
737 PyArrayObject*
unitary = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)unitary_arg, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
740 if ( !PyArray_IS_C_CONTIGUOUS(unitary) ) {
741 PyErr_SetString(PyExc_Exception,
"input mtrix is not memory contiguous");
750 self->vqe->apply_to( parameters_mtx, unitary_mtx );
752 if (unitary_mtx.
data != PyArray_DATA(unitary)) {
756 Py_DECREF(parameters_arr);
769 static char *kwlist[] = {(
char*)
"optimizer", NULL};
771 PyObject* optimizer_arg = NULL;
775 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|O", kwlist, &optimizer_arg)) {
777 std::string err(
"Unsuccessful argument parsing not ");
778 PyErr_SetString(PyExc_Exception, err.c_str());
783 if ( optimizer_arg == NULL ) {
784 std::string err(
"optimizer argument not set");
785 PyErr_SetString(PyExc_Exception, err.c_str());
790 PyObject* optimizer_string = PyObject_Str(optimizer_arg);
791 PyObject* optimizer_string_unicode = PyUnicode_AsEncodedString(optimizer_string,
"utf-8",
"~E~");
792 const char* optimizer_C = PyBytes_AS_STRING(optimizer_string_unicode);
795 if ( strcmp(
"agents", optimizer_C) == 0 || strcmp(
"AGENTS", optimizer_C) == 0) {
798 else if ( strcmp(
"agents_combined", optimizer_C)==0 || strcmp(
"AGENTS_COMBINED", optimizer_C)==0) {
801 else if ( strcmp(
"cosined", optimizer_C)==0 || strcmp(
"COSINE", optimizer_C)==0) {
804 else if ( strcmp(
"grad_descend_phase_shift_rule", optimizer_C)==0 || strcmp(
"GRAD_DESCEND_PARAMETER_SHIFT_RULE", optimizer_C)==0) {
807 else if ( strcmp(
"bfgs", optimizer_C)==0 || strcmp(
"BFGS", optimizer_C)==0) {
808 qgd_optimizer =
BFGS;
810 else if ( strcmp(
"adam", optimizer_C)==0 || strcmp(
"ADAM", optimizer_C)==0) {
811 qgd_optimizer =
ADAM;
813 else if ( strcmp(
"grad_descend", optimizer_C)==0 || strcmp(
"GRAD_DESCEND", optimizer_C)==0) {
816 else if ( strcmp(
"bayes_opt", optimizer_C)==0 || strcmp(
"BAYES_OPT", optimizer_C)==0) {
819 else if ( strcmp(
"bayes_agents", optimizer_C)==0 || strcmp(
"BAYES_AGENTS", optimizer_C)==0) {
823 std::string err(
"Unsupported optimizer: ");
825 PyErr_SetString(PyExc_Exception, err.c_str());
831 self->vqe->set_optimizer(qgd_optimizer);
833 catch (std::string err) {
834 PyErr_SetString(PyExc_Exception, err.c_str());
835 std::cout << err << std::endl;
839 std::string err(
"Invalid pointer to decomposition class");
840 PyErr_SetString(PyExc_Exception, err.c_str());
854 static char *kwlist[] = {(
char*)
"optimizer", NULL};
856 PyObject* ansatz_arg = NULL;
860 if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|O", kwlist, &ansatz_arg)) {
862 std::string err(
"Unsuccessful argument parsing not ");
863 PyErr_SetString(PyExc_Exception, err.c_str());
869 if ( ansatz_arg == NULL ) {
870 std::string err(
"optimizer argument not set");
871 PyErr_SetString(PyExc_Exception, err.c_str());
877 PyObject* ansatz_string = PyObject_Str(ansatz_arg);
878 PyObject* ansatz_string_unicode = PyUnicode_AsEncodedString(ansatz_string,
"utf-8",
"~E~");
879 const char* ansatz_C = PyBytes_AS_STRING(ansatz_string_unicode);
884 if ( strcmp(
"hea", ansatz_C) == 0 || strcmp(
"HEA", ansatz_C) == 0) {
887 else if ( strcmp(
"hea_zyz", ansatz_C) == 0 || strcmp(
"HEA_ZYZ", ansatz_C) == 0) {
891 std::string err(
"Unsupported ansatz: ");
893 PyErr_SetString(PyExc_Exception, err.c_str());
899 self->vqe->set_ansatz(qgd_ansatz);
901 catch (std::string err) {
902 PyErr_SetString(PyExc_Exception, err.c_str());
903 std::cout << err << std::endl;
907 std::string err(
"Invalid pointer to decomposition class");
908 PyErr_SetString(PyExc_Exception, err.c_str());
926 PyArrayObject * parameters_arr = NULL;
927 PyArrayObject * input_state_arg = NULL;
928 PyObject * qubit_list_arg = NULL;
932 if (!PyArg_ParseTuple(args,
"|OOO", ¶meters_arr, &input_state_arg, &qubit_list_arg ))
936 if ( PyArray_IS_C_CONTIGUOUS(parameters_arr) ) {
937 Py_INCREF(parameters_arr);
940 parameters_arr = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arr, NPY_DOUBLE, NPY_ARRAY_IN_ARRAY);
947 if ( input_state_arg == NULL ) {
948 PyErr_SetString(PyExc_Exception,
"Input matrix was not given");
952 PyArrayObject* input_state = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)input_state_arg, NPY_COMPLEX128, NPY_ARRAY_IN_ARRAY);
955 if ( !PyArray_IS_C_CONTIGUOUS(input_state) ) {
956 PyErr_SetString(PyExc_Exception,
"input mtrix is not memory contiguous");
966 if ( qubit_list_arg == NULL || (!PyList_Check( qubit_list_arg )) ) {
967 PyErr_SetString(PyExc_Exception,
"qubit_list should be a list");
971 Py_ssize_t reduced_qbit_num = PyList_Size( qubit_list_arg );
974 for (
int idx=0; idx<reduced_qbit_num; idx++ ) {
976 PyObject* item = PyList_GET_ITEM( qubit_list_arg, idx );
977 qbit_list_mtx[idx] = (
int) PyLong_AsLong( item );
986 entropy =
self->vqe->get_second_Renyi_entropy( parameters_mtx, input_state_mtx, qbit_list_mtx );
988 catch (std::string err) {
989 PyErr_SetString(PyExc_Exception, err.c_str());
990 std::cout << err << std::endl;
994 std::string err(
"Invalid pointer to decomposition class");
995 PyErr_SetString(PyExc_Exception, err.c_str());
1000 Py_DECREF(parameters_arr);
1001 Py_DECREF(input_state);
1019 if (!PyArg_ParseTuple(args,
"|ii", &layers, &inner_blocks ))
return Py_BuildValue(
"i", -1);
1023 self->vqe->generate_circuit( layers, inner_blocks );
1025 catch (std::string err) {
1026 PyErr_SetString(PyExc_Exception, err.c_str());
1027 std::cout << err << std::endl;
1031 std::string err(
"Invalid pointer to decomposition class");
1032 PyErr_SetString(PyExc_Exception, err.c_str());
1046 PyArrayObject* parameters_arg = NULL;
1050 if (!PyArg_ParseTuple(args,
"|O", ¶meters_arg )) {
1052 std::string err(
"Unsuccessful argument parsing not ");
1053 PyErr_SetString(PyExc_Exception, err.c_str());
1059 if ( PyArray_IS_C_CONTIGUOUS(parameters_arg) && PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ){
1060 Py_INCREF(parameters_arg);
1062 else if (PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ) {
1063 parameters_arg = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arg, NPY_FLOAT64, NPY_ARRAY_IN_ARRAY);
1066 std::string err(
"Parameters should be should be real (given in float64 format)");
1067 PyErr_SetString(PyExc_Exception, err.c_str());
1076 f0 =
self->vqe->optimization_problem(parameters_mtx );
1078 catch (std::string err ) {
1079 PyErr_SetString(PyExc_Exception, err.c_str());
1083 std::string err(
"Invalid pointer to decomposition class");
1084 PyErr_SetString(PyExc_Exception, err.c_str());
1088 Py_DECREF(parameters_arg);
1122 PyArrayObject *state_left_arg = NULL;
1123 PyArrayObject *state_right_arg = NULL;
1126 if (!PyArg_ParseTuple(args,
"|OO", &state_left_arg, &state_right_arg)) {
1127 PyErr_SetString(PyExc_Exception,
"Failed to parse input states");
1131 if (!state_left_arg || !state_right_arg) {
1132 PyErr_SetString(PyExc_Exception,
"Two state vectors are required");
1140 double energy = 0.0;
1142 energy =
self->vqe->Expectation_value_of_energy_real(state_left, state_right);
1143 }
catch (std::string &err) {
1144 PyErr_SetString(PyExc_Exception, err.c_str());
1147 PyErr_SetString(PyExc_Exception,
"Unexpected error in Expectation_value_of_energy_real");
1187 PyObject *dict_arg = NULL;
1188 if (!PyArg_ParseTuple(args,
"|O", &dict_arg)) {
1189 PyErr_SetString(PyExc_Exception,
"Failed to parse dictionary argument.");
1192 if (!PyDict_Check(dict_arg)) {
1193 PyErr_SetString(PyExc_Exception,
"Expected a Python dictionary as input.");
1198 PyObject* shots_obj = PyDict_GetItemString(dict_arg,
"shots");
1199 PyObject* p_readout_obj = PyDict_GetItemString(dict_arg,
"p_readout");
1200 if (!shots_obj || !p_readout_obj) {
1201 PyErr_SetString(PyExc_Exception,
"Missing 'shots' or 'p_readout' in dictionary.");
1204 const int shots = (
int)PyLong_AsLong(shots_obj);
1205 const double p_readout = PyFloat_AsDouble(p_readout_obj);
1209 PyObject *seed_obj = PyDict_GetItemString(dict_arg,
"seed");
1210 if (seed_obj && PyLong_Check(seed_obj)) {
1211 seed = (uint64_t)PyLong_AsUnsignedLongLong(seed_obj);
1215 PyObject *zz_list = PyDict_GetItemString(dict_arg,
"zz_terms");
1216 if (!zz_list || !PyList_Check(zz_list)) {
1217 PyErr_SetString(PyExc_Exception,
"Missing or invalid 'zz_terms' list.");
1220 self->vqe->zz_terms.clear();
1221 for (Py_ssize_t
k = 0;
k < PyList_Size(zz_list); ++
k) {
1222 PyObject *item = PyList_GetItem(zz_list,
k);
1223 int i_idx = (
int)PyLong_AsLong(PyDict_GetItemString(item,
"i"));
1224 int j_idx = (
int)PyLong_AsLong(PyDict_GetItemString(item,
"j"));
1225 double coeff = PyFloat_AsDouble(PyDict_GetItemString(item,
"coeff"));
1226 self->vqe->zz_terms.emplace_back(i_idx, j_idx, coeff);
1230 self->vqe->z_terms.clear();
1231 PyObject *z_list = PyDict_GetItemString(dict_arg,
"z_terms");
1232 if (z_list && PyList_Check(z_list)) {
1233 for (Py_ssize_t
k = 0;
k < PyList_Size(z_list); ++
k) {
1234 PyObject *item = PyList_GetItem(z_list,
k);
1235 int i_idx = (
int)PyLong_AsLong(PyDict_GetItemString(item,
"i"));
1236 double coeff = PyFloat_AsDouble(PyDict_GetItemString(item,
"coeff"));
1237 self->vqe->z_terms.emplace_back(i_idx, coeff);
1242 self->vqe->xx_terms.clear();
1243 PyObject *xx_list = PyDict_GetItemString(dict_arg,
"xx_terms");
1244 if (xx_list && PyList_Check(xx_list)) {
1245 for (Py_ssize_t
k = 0;
k < PyList_Size(xx_list); ++
k) {
1246 PyObject *item = PyList_GetItem(xx_list,
k);
1248 int i_idx = (
int)PyLong_AsLong(PyDict_GetItemString(item,
"i"));
1249 int j_idx = (
int)PyLong_AsLong(PyDict_GetItemString(item,
"j"));
1250 double coeff = PyFloat_AsDouble(PyDict_GetItemString(item,
"coeff"));
1252 self->vqe->xx_terms.emplace_back(i_idx, j_idx, coeff);
1257 Matrix state =
self->vqe->get_initial_state().copy();
1263 self->vqe->apply_to(parameters, state);
1267 res =
self->vqe->Expectation_value_with_shot_noise_real(state, shots, seed, p_readout);
1269 catch (
const std::string &err) {
1270 PyErr_SetString(PyExc_Exception, err.c_str());
1273 catch (
const char *err) {
1274 PyErr_SetString(PyExc_Exception, err);
1277 catch (
const std::exception &e) {
1278 PyErr_SetString(PyExc_Exception, e.what());
1282 PyErr_SetString(PyExc_Exception,
"Unknown C++ exception in Expectation_Value_Shot_Noise");
1309 PyObject* parameter_list = NULL;
1313 if (!PyArg_ParseTuple(args,
"|O", ¶meter_list )) {
1315 std::string err(
"Unsuccessful argument parsing not ");
1316 PyErr_SetString(PyExc_Exception, err.c_str());
1322 if ( parameter_list == NULL || (!PyList_Check( parameter_list )) ) {
1323 PyErr_SetString(PyExc_Exception,
"Parameters should be given as a list of parameter arrays");
1327 int tasks = (
int)PyList_Size( parameter_list );
1332 std::vector<Matrix_real> parameters_vec;
1333 parameters_vec.resize(tasks);
1335 for(
int idx=0; idx<tasks; idx++ ) {
1336 PyArrayObject* parameters_py = (PyArrayObject*)PyList_GET_ITEM( parameter_list, idx );
1339 if ( PyArray_IS_C_CONTIGUOUS(parameters_py) && PyArray_TYPE(parameters_py) == NPY_FLOAT64 ){
1340 Py_INCREF(parameters_py);
1342 else if (PyArray_TYPE(parameters_py) == NPY_FLOAT64 ) {
1343 parameters_py = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_py, NPY_FLOAT64, NPY_ARRAY_IN_ARRAY);
1346 Py_DECREF(parameters_py);
1347 std::string err(
"Parameters should be should be real (given in float64 format)");
1348 PyErr_SetString(PyExc_Exception, err.c_str());
1353 parameters_vec[idx] = parameters_mtx;
1355 Py_DECREF(parameters_py);
1360 result_mtx =
self->vqe->optimization_problem_batched( parameters_vec );
1362 catch (std::string err ) {
1363 PyErr_SetString(PyExc_Exception, err.c_str());
1367 std::string err(
"Invalid pointer to decomposition class");
1368 PyErr_SetString(PyExc_Exception, err.c_str());
1406 PyObject* qgd_Circuit = PyImport_ImportModule(
"squander.gates.qgd_Circuit");
1408 if ( qgd_Circuit == NULL ) {
1409 PyErr_SetString(PyExc_Exception,
"Module import error: squander.gates.qgd_Circuit" );
1419 PyObject* qgd_circuit_Dict = PyModule_GetDict( qgd_Circuit );
1422 PyObject* py_circuit_class = PyDict_GetItemString( qgd_circuit_Dict,
"qgd_Circuit");
1428 PyObject* py_circuit = PyObject_CallObject(py_circuit_class, circuit_input);
1434 delete( py_circuit_C->
gate );
1451 PyArrayObject* parameters_arg = NULL;
1455 if (!PyArg_ParseTuple(args,
"|O", ¶meters_arg )) {
1457 std::string err(
"Unsuccessful argument parsing not ");
1458 PyErr_SetString(PyExc_Exception, err.c_str());
1464 if ( PyArray_IS_C_CONTIGUOUS(parameters_arg) && PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ){
1465 Py_INCREF(parameters_arg);
1467 else if (PyArray_TYPE(parameters_arg) == NPY_FLOAT64 ) {
1468 parameters_arg = (PyArrayObject*)PyArray_FROM_OTF( (PyObject*)parameters_arg, NPY_FLOAT64, NPY_ARRAY_IN_ARRAY);
1471 std::string err(
"Parameters should be should be real (given in float64 format)");
1472 PyErr_SetString(PyExc_Exception, err.c_str());
1481 self->vqe->optimization_problem_grad(parameters_mtx, self->vqe, grad_mtx );
1483 catch (std::string err ) {
1484 PyErr_SetString(PyExc_Exception, err.c_str());
1488 std::string err(
"Invalid pointer to decomposition class");
1489 PyErr_SetString(PyExc_Exception, err.c_str());
1494 grad_mtx.set_owner(
false);
1497 Py_DECREF(parameters_arg);
1510 PyObject* project_name_new=NULL;
1513 if (!PyArg_ParseTuple(args,
"|O", &project_name_new))
return Py_BuildValue(
"i", -1);
1516 PyObject* project_name_new_string = PyObject_Str(project_name_new);
1517 PyObject* project_name_new_unicode = PyUnicode_AsEncodedString(project_name_new_string,
"utf-8",
"~E~");
1518 const char* project_name_new_C = PyBytes_AS_STRING(project_name_new_unicode);
1519 std::string project_name_new_str = ( project_name_new_C );
1522 self->vqe->set_project_name(project_name_new_str);
1537 PyObject* gate_structure_py;
1540 if (!PyArg_ParseTuple(args,
"|O", &gate_structure_py ))
return Py_BuildValue(
"i", -1);
1547 self->vqe->set_custom_gate_structure( qgd_op_block->
gate );
1549 catch (std::string err ) {
1550 PyErr_SetString(PyExc_Exception, err.c_str());
1554 std::string err(
"Invalid pointer to decomposition class");
1555 PyErr_SetString(PyExc_Exception, err.c_str());
1577 "Method to start the decomposition." 1580 "Method to get the array of optimized parameters." 1583 "Method to set the array of optimized parameters." 1586 "Method to set optimization tolerance" 1589 "Method to get the incorporated circuit." 1592 "method to set project name." 1595 "Method to set the gate structure from a file created in SQUANDER." 1598 "Call to apply the gate on the input matrix." 1601 "Method to set optimizer." 1604 "Method to set ansatz type." 1607 "Call to get the number of free parameters in the gate structure used for the decomposition" 1610 "Method to set the circuit based on the ansatz type." 1614 "Estimate â¨Hâ© via MonteâCarlo shot sampling; input is a dict with 'shots', 'p_readout', term lists, and optional 'seed'. Returns {'mean', 'variance', 'std_error'}." 1617 "Compute the real part of â¨Ï_left|H|Ï_rightâ©; inputs are two complex state vectors. "},
1621 "Method to get the expected energy of the circuit at parameters." 1624 "Wrapper function to evaluate the cost function for a batch of input parameters." 1627 "Wrapper function to evaluate the second Rényi entropy of a quantum circuit at a specific parameter set." 1630 "Call to get the number of qubits in the circuit" 1633 "Call to set the initial state used in the VQE process." 1636 "Configure ordered fixed local-noise insertions for the density-matrix backend." 1639 "Return machine-readable metadata describing the currently supported density-matrix bridge path." 1642 "Call to set custom gate structure for VQE experiments." 1645 "Method to get the expected energy of the circuit at parameters." 1654 PyVarObject_HEAD_INIT(NULL, 0)
1655 "qgd_N_Qubit_Decomposition_Wrapper.qgd_N_Qubit_Decomposition_Wrapper",
1659 #if PY_VERSION_HEX < 0x030800b4 1662 #if PY_VERSION_HEX >= 0x030800b4 1667 #if PY_MAJOR_VERSION < 3 1670 #if PY_MAJOR_VERSION >= 3 1683 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1684 "Object to represent a Gates_block class of the QGD package.",
1711 #
if PY_VERSION_HEX >= 0x030400a1
1714 #
if PY_VERSION_HEX >= 0x030800b1
1717 #
if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000
1726 PyModuleDef_HEAD_INIT,
1727 "qgd_N_Qubit_Decomposition_Wrapper",
1728 "Python binding for QGD N_Qubit_Decomposition class",
1743 if (PyType_Ready(&qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Type) < 0)
1746 m = PyModule_Create(&qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Module);
1750 Py_INCREF(&qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Type);
1751 if (PyModule_AddObject(m,
"qgd_Variational_Quantum_Eigensolver_Base_Wrapper", (PyObject *) &qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Type) < 0) {
1752 Py_DECREF(&qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Type);
void release_Variational_Quantum_Eigensolver_Base(Variational_Quantum_Eigensolver_Base *instance)
Call to deallocate an instance of N_Qubit_Decomposition class.
Gates_block * get_flat_circuit()
Method to generate a flat circuit.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Optimization_Problem(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Ansatz(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args, PyObject *kwds)
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Optimization_Tolerance(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
parameter_num
[set adaptive gate structure]
ansatz_type
Type definition of the fifferent types of ansatz.
PyMODINIT_FUNC PyInit_qgd_Variational_Quantum_Eigensolver_Base_Wrapper(void)
Method called when the Python module is initialized.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Optimized_Parameters(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Set parameters for the solver.
Type definition of the qgd_N_Qubit_Decomposition_Wrapper Python class of the qgd_N_Qubit_Decompositio...
Class to solve VQE problems.
Variational_Quantum_Eigensolver_Base * create_qgd_Variational_Quantum_Eigensolver_Base(Matrix_sparse Hamiltonian, int qbit_num, std::map< std::string, Config_Element > &config, int accelerator_num)
Creates an instance of class N_Qubit_Decomposition and return with a pointer pointing to the class in...
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_apply_to(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
return Py_BuildValue("i", 0)
Matrix_real numpy2matrix_real(PyArrayObject *arr)
Call to create a PIC matrix_real representation of a numpy array.
scalar * data
pointer to the stored data
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Expectation_Value_Shot_Noise(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Wrapper to compute an estimated expectation value using MonteâCarlo shot sampling with optional rea...
static void qgd_Variational_Quantum_Eigensolver_Base_Wrapper_dealloc(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self)
Method called when a python instance of the class qgd_N_Qubit_Decomposition_Wrapper is destroyed...
PyObject * matrix_real_to_numpy(Matrix_real &mtx)
Call to make a numpy array from an instance of matrix class.
U3 RX RZ H Y SX S T CNOT CH SYC CRZ PyObject PyObject * kwds
Class to store data of complex arrays and its properties.
A class describing a universal configuration element.
scalar * get_data() const
Call to get the pointer to the stored data.
PyObject_HEAD PyObject * Hamiltonian
pointer to the unitary to be decomposed to keep it alive
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Expectation_value_of_energy_real(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Wrapper function to evaluate the real part of the energy expectation value â¨Ï_left | H | Ï_rightâ...
optimization_aglorithms
implemented optimization strategies
static PyModuleDef qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Module
Structure containing metadata about the module.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_get_Optimized_Parameters(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self)
Extract the optimized parameters.
U3 RX RZ H Y SX S T CNOT CH SYC CRZ PyObject * args
PyObject_HEAD Gates_block * gate
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_get_circuit(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self)
Wrapper function to retrieve the circuit (Squander format) incorporated in the instance.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_get_Qbit_Num(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self)
Call to retrieve the number of qubits in the circuit.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Start_Optimization(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self)
Container for statistics returned by shot-noise simulations.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_get_Second_Renyi_Entropy(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Wrapper function to evaluate the second Rényi entropy of a quantum circuit at a specific parameter s...
void set_owner(bool owner_in)
Call to set the current class instance to be (or not to be) the owner of the stored data array...
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Gate_Structure_From_Binary(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Wrapper function to set custom layers to the gate structure that are intended to be used in the decom...
Structure type representing complex numbers in the SQUANDER package.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Gate_Structure(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Wrapper function to set custom gate structure for the decomposition.
A base class to solve VQE problems This class can be used to approximate the ground state of the inpu...
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Optimization_Problem_Grad(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Wrapper function to evaluate the cost function an dthe gradient components.
int Power_of_2(int n)
Calculates the n-th power of 2.
Double-precision complex matrix (float64).
int size() const
Call to get the number of the allocated elements.
A class responsible for grouping two-qubit (CNOT,CZ,CH) and one-qubit gates into layers.
Variational_Quantum_Eigensolver_Base * vqe
An object to decompose the unitary.
void set_property(std::string name_, double val_)
Call to set a double value.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Method called when a python instance of the class qgd_N_Qubit_Decomposition_Wrapper is allocated...
static PyTypeObject qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Type
A structure describing the type of the class qgd_N_Qubit_Decomposition_Wrapper.
Matrix numpy2matrix(PyArrayObject *arr)
Call to create a PIC matrix representation of a numpy array.
PyObject_HEAD Gates_block * circuit
Pointer to the C++ class of the base Gate_block module.
static PyMemberDef qgd_Variational_Quantum_Eigensolver_Base_Wrapper_members[]
Structure containing metadata about the members of class qgd_N_Qubit_Decomposition_Wrapper.
Ordered fixed-noise insertion metadata.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Optimizer(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args, PyObject *kwds)
int get_qbit_num()
Call to get the number of qubits composing the unitary.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Initial_State(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Set the initial state used in the VQE process.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Generate_Circuit(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Type definition for qgd_Circuit_Wrapper.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Density_Matrix_Noise(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Configure ordered fixed density-noise insertions for the density backend.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_get_Density_Matrix_Bridge_Metadata(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self)
Return a machine-readable description of the supported density bridge.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_Optimization_Problem_Batch(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Wrapper function to evaluate the cost function for many input paramaters at once. ...
static PyMethodDef qgd_Variational_Quantum_Eigensolver_Base_Wrapper_methods[]
Structure containing metadata about the methods of class qgd_N_Qubit_Decomposition_Wrapper.
Class to store data of complex arrays and its properties.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_set_Project_Name(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args)
Call to set a project name.
static PyObject * qgd_Variational_Quantum_Eigensolver_Base_Wrapper_get_Parameter_Num(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self)
Get the number of free parameters in the gate structure used for the decomposition.
static int qgd_Variational_Quantum_Eigensolver_Base_Wrapper_init(qgd_Variational_Quantum_Eigensolver_Base_Wrapper *self, PyObject *args, PyObject *kwds)
Method called when a python instance of the class qgd_N_Qubit_Decomposition_Wrapper is initialized...