Sequential Quantum Gate Decomposer  v1.9.3
Powerful decomposition of general unitarias into one- and two-qubit gates gates
Variational_Quantum_Eigensolver_Base.cpp
Go to the documentation of this file.
1 /*
2 Created on Fri Jun 26 14:13:26 2020
3 Copyright 2020 Peter Rakyta, Ph.D.
4 
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8 
9  http://www.apache.org/licenses/LICENSE-2.0
10 
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 
17 @author: Peter Rakyta, Ph.D.
18 */
23 
24 tbb::spin_mutex my_mutex;
25 
31 
32  // logical value describing whether the decomposition was finalized or not
34 
35 
36  // error of the unitarity of the final decomposition
37  decomposition_error = DBL_MAX;
38 
39 
40  // The current minimum of the optimization problem
41  current_minimum = DBL_MAX;
42 
43  global_target_minimum = -DBL_MAX;
44 
45  // logical value describing whether the optimization problem was solved or not
47 
48 
49  // The maximal allowed error of the optimization problem
50  optimization_tolerance = -DBL_MAX;
51 
52  // The convergence threshold in the optimization process
53  convergence_threshold = -DBL_MAX;
54 
55  alg = AGENTS;
56 
57 
59 
60  adaptive_eta = false;
61 
62  cost_fnc = VQE;
63 
64  ansatz = HEA;
65 }
66 
67 
68 
69 
77 Variational_Quantum_Eigensolver_Base::Variational_Quantum_Eigensolver_Base( Matrix_sparse Hamiltonian_in, int qbit_num_in, std::map<std::string, Config_Element>& config_in, int accelerator_num) : Optimization_Interface(Matrix(Power_of_2(qbit_num_in),1), qbit_num_in, false, config_in, RANDOM, accelerator_num) {
78 
79  Hamiltonian = Hamiltonian_in;
80  // config maps
81  config = config_in;
82  // logical value describing whether the decomposition was finalized or not
84 
85 
86  // error of the unitarity of the final decomposition
87  decomposition_error = DBL_MAX;
88 
89 
90  // The current minimum of the optimization problem
91  current_minimum = DBL_MAX;
92 
93 
94  // logical value describing whether the optimization problem was solved or not
96 
97  // override optimization parameters governing the convergence used in gate decomposition applications
98  global_target_minimum = -DBL_MAX;
99  optimization_tolerance = -DBL_MAX;
100  convergence_threshold = -DBL_MAX;
101 
102 
103 
105 
106  adaptive_eta = false;
107 
108  qbit_num = qbit_num_in;
109 
110 
111 
112  std::random_device rd;
113 
114  gen = std::mt19937(rd());
115 
116  alg = BAYES_OPT;
117 
118  cost_fnc = VQE;
119 
120  ansatz = HEA;
121 
122 }
123 
124 
125 
126 
131 
132 }
133 
134 
135 
136 
141 
142  // initialize the initial state if it was not given
143  if ( initial_state.size() == 0 ) {
145  }
146 
147 
148  if (gates.size() == 0 ) {
149  std::string error("Variational_Quantum_Eigensolver_Base::Get_ground_state: for VQE process the circuit needs to be initialized");
150  throw error;
151  }
152 
154  if ( num_of_parameters == 0 ) {
155  std::string error("Variational_Quantum_Eigensolver_Base::Get_ground_state: No intial parameters were given");
156  throw error;
157  }
158 
159 
160  if ( num_of_parameters != get_parameter_num() ) {
161  std::string error("Variational_Quantum_Eigensolver_Base::Get_ground_state: The number of initial parameters does not match with the number of parameters in the circuit");
162  throw error;
163  }
164 
165 
166  // start the VQE process
167  Matrix_real solution_guess = optimized_parameters_mtx.copy();
168  solve_layer_optimization_problem(num_of_parameters, solution_guess);
169 
170 
171  return;
172 }
173 
174 
175 
183 
184 
185  if ( State_left.rows != State_right.rows || Hamiltonian.rows != State_right.rows) {
186  std::string error("Variational_Quantum_Eigensolver_Base::Expectation_value_of_energy: States on the right and left should be of the same dimension as the Hamiltonian");
187  throw error;
188  }
189 
190  Matrix tmp = mult(Hamiltonian, State_right);
191  QGD_Complex16 Energy;
192  Energy.real = 0.0;
193  Energy.imag = 0.0;
194 
195 
196  tbb::combinable<double> priv_partial_energy_real{[](){return 0.0;}};
197  tbb::combinable<double> priv_partial_energy_imag{[](){return 0.0;}};
198 
199  tbb::parallel_for( tbb::blocked_range<int>(0, State_left.rows, 1024), [&](tbb::blocked_range<int> r) {
200 
201  double& energy_local_real = priv_partial_energy_real.local();
202  double& energy_local_imag = priv_partial_energy_imag.local();
203 
204  for (int idx=r.begin(); idx<r.end(); idx++){
205  energy_local_real += State_left[idx].real*tmp[idx].real + State_left[idx].imag*tmp[idx].imag;
206  energy_local_imag += State_left[idx].real*tmp[idx].imag - State_left[idx].imag*tmp[idx].real;
207  }
208 
209  });
210 
211  // calculate the final cost function
212  priv_partial_energy_real.combine_each([&Energy](double a) {
213  Energy.real = Energy.real + a;
214  });
215 
216  priv_partial_energy_imag.combine_each([&Energy](double a) {
217  Energy.imag = Energy.imag + a;
218  });
219 
220 
221  tmp.release_data(); // TODO: this is not necessary, beacause it is called with the destructor of the class Matrix
222 
223  {
224  tbb::spin_mutex::scoped_lock my_lock{my_mutex};
225 
226  number_of_iters++;
227 
228  }
229 
230  return Energy;
231 }
232 
233 
241 
242 
243  if ( State_left.rows != State_right.rows || Hamiltonian.rows != State_right.rows) {
244  std::string error("Variational_Quantum_Eigensolver_Base::Expectation_value_of_energy_real: States on the right and left should be of the same dimension as the Hamiltonian");
245  throw error;
246  }
247 
248  Matrix tmp = mult(Hamiltonian, State_right);
249  double Energy = 0.0;
250 
251 
252  tbb::combinable<double> priv_partial_energy{[](){return 0.0;}};
253 
254  tbb::parallel_for( tbb::blocked_range<int>(0, State_left.rows, 1024), [&](tbb::blocked_range<int> r) {
255 
256  double& energy_local = priv_partial_energy.local();
257 
258  for (int idx=r.begin(); idx<r.end(); idx++){
259  energy_local += State_left[idx].real*tmp[idx].real + State_left[idx].imag*tmp[idx].imag;
260  }
261 
262  });
263 
264  // calculate the final cost function
265  priv_partial_energy.combine_each([&Energy](double a) {
266  Energy = Energy + a;
267  });
268 
269 
270  tmp.release_data(); // TODO: this is not necessary, beacause it is called with the destructor of the class Matrix
271 
272  {
273  tbb::spin_mutex::scoped_lock my_lock{my_mutex};
274 
275  number_of_iters++;
276 
277  }
278 
279  return Energy;
280 }
281 
282 
283 
284 
292 
293  double Energy=0.0;
294 
295  Variational_Quantum_Eigensolver_Base* instance = reinterpret_cast<Variational_Quantum_Eigensolver_Base*>(void_instance);
296 
297  Matrix State = instance->initial_state.copy();
298 
299  instance->apply_to(parameters, State);
300  Energy = instance->Expectation_value_of_energy_real(State, State);
301 
302  return Energy;
303 }
304 
305 
306 #ifdef __GROQ__
307 
313 double Variational_Quantum_Eigensolver_Base::optimization_problem_Groq(Matrix_real& parameters, int chosen_device) {
314 
315 
316 
317  Matrix State;
318 
319 
320  //tbb::tick_count t0_DFE = tbb::tick_count::now();
321  std::vector<int> target_qbits;
322  std::vector<int> control_qbits;
323  std::vector<Matrix> u3_qbit;
324  extract_gate_kernels_target_and_control_qubits(u3_qbit, target_qbits, control_qbits, parameters);
325 
326 
327  // initialize the initial state on the chip if it was not given
328  if ( initial_state.size() == 0 ) {
329 
330  Matrix State_zero(0,0);
331  apply_to_groq_sv(accelerator_num, chosen_device, qbit_num, u3_qbit, target_qbits, control_qbits, State_zero, id);
332 
333  State = State_zero;
334 
335  }
336  else {
337 
338  State = initial_state.copy();
339  // apply state transformation via the Groq chip
340  apply_to_groq_sv(accelerator_num, chosen_device, qbit_num, u3_qbit, target_qbits, control_qbits, State, id);
341 
342  }
343 
344 
345 /*
347  Matrix State_copy = State.copy();
348 
349 
350  Decomposition_Base::apply_to(parameters, State_copy );
351 
352 
353  double diff = 0.0;
354  for( int64_t idx=0; idx<State_copy.size(); idx++ ) {
355 
356  QGD_Complex16 element = State[idx];
357  QGD_Complex16 element_copy = State_copy[idx];
358  QGD_Complex16 element_diff;
359  element_diff.real = element.real - element_copy.real;
360  element_diff.imag = element.imag - element_copy.imag;
361 
362  double diff_increment = element_diff.real*element_diff.real + element_diff.imag*element_diff.imag;
363  diff = diff + diff_increment;
364  }
365 
366  std::cout << "Variational_Quantum_Eigensolver_Base::apply_to checking diff: " << diff << std::endl;
367 
368 
369  if ( diff > 1e-4 ) {
370  std::string error("Groq and CPU results do not match");
371  throw(error);
372  }
373 
375 */
376 
377 
378 
379  double Energy = Expectation_value_of_energy_real(State, State);
380 
381  return Energy;
382 
383 }
384 
385 #endif
386 
387 
394 
395 
396  Matrix State;
397 
398 #ifdef __GROQ__
399  if ( accelerator_num > 0 ) {
400 
401 
402  return optimization_problem_Groq( parameters, 0 );
403 
404  }
405  else {
406 #endif
407  // initialize the initial state if it was not given
408  if ( initial_state.size() == 0 ) {
410  }
411 
412  State = initial_state.copy();
413  apply_to(parameters, State);
414 
415 #ifdef __GROQ__
416  }
417 #endif
418 
419 
420 
421 
422  double Energy = Expectation_value_of_energy_real(State, State);
423 
424  return Energy;
425 }
426 
427 
428 
437 
438  Variational_Quantum_Eigensolver_Base* instance = reinterpret_cast<Variational_Quantum_Eigensolver_Base*>(void_instance);
439 
440  // initialize the initial state if it was not given
441  if ( instance->initial_state.size() == 0 ) {
442  instance->initialize_zero_state();
443  }
444 
445  // the number of free parameters
446  int parameter_num_loc = parameters.size();
447 
448  Matrix_real cost_function_terms;
449 
450  // vector containing gradients of the transformed matrix
451  std::vector<Matrix> State_deriv;
452  Matrix State;
453 
454  int parallel = get_parallel_configuration();
455 
456  tbb::parallel_invoke(
457  [&]{
458  State = instance->initial_state.copy();
459  instance->apply_to(parameters, State);
460  *f0 = instance->Expectation_value_of_energy_real(State, State);
461 
462  },
463  [&]{
464  Matrix State_loc = instance->initial_state.copy();
465 
466  State_deriv = instance->apply_derivate_to( parameters, State_loc, parallel );
467  State_loc.release_data();
468  });
469 
470  tbb::parallel_for( tbb::blocked_range<int>(0,parameter_num_loc,2), [&](tbb::blocked_range<int> r) {
471  for (int idx=r.begin(); idx<r.end(); ++idx) {
472  grad[idx] = 2*instance->Expectation_value_of_energy_real(State_deriv[idx], State);
473  }
474  });
475 
476  /*
477  double delta = 0.0000001;
478 
479  tbb::parallel_for( tbb::blocked_range<int>(0,parameter_num_loc,1), [&](tbb::blocked_range<int> r) {
480  for (int idx=r.begin(); idx<r.end(); ++idx) {
481  Matrix_real param_tmp = parameters.copy();
482  param_tmp[idx] += delta;
483 
484  Matrix State = instance->initial_state.copy();
485  instance->apply_to(param_tmp, State);
486  double f_loc = instance->Expectation_value_of_energy_real(State, State);
487 
488 
489  grad[idx] = (f_loc-*f0)/delta;
490  }
491  });
492 
493 */
494  return;
495 }
496 
497 
498 
499 
500 
501 
509 
510  optimization_problem_combined_non_static( parameters, this, f0, grad );
511  return;
512 }
513 
514 
515 
516 
524 
525  double f0;
526  Variational_Quantum_Eigensolver_Base* instance = reinterpret_cast<Variational_Quantum_Eigensolver_Base*>(void_instance);
527  instance->optimization_problem_combined_non_static(parameters, void_instance, &f0, grad);
528  return;
529 
530 }
531 
532 
533 
534 
541 
542  // get the transformed matrix with the gates in the list
543  Matrix_real parameters_mtx(parameters, 1, parameter_num );
544 
545  return optimization_problem( parameters_mtx );
546 
547 
548 }
549 
550 
551 
552 
557 
558  int initialize_state;
559  if ( config.count("initialize_state") > 0 ) {
560  long long value;
561  config["initialize_state"].get_property( value );
562  initialize_state = (int) value;
563  }
564  else {
565  initialize_state = 1;
566 
567  }
568 
569  if( initialize_state == 0 ) {
570  initial_state = Matrix(0, 0);
571  return;
572  }
573 
574  initial_state = Matrix( 1 << qbit_num , 1);
575 
576 
577  initial_state[0].real = 1.0;
578  initial_state[0].imag = 0.0;
579  memset(initial_state.get_data()+2, 0.0, (initial_state.size()*2-2)*sizeof(double) );
580 
581  initial_state[1].real = 0.0;
582  initial_state[1].imag = 0.0;
583 
584 
585  return;
586 }
587 
588 
589 
590 
591 
597 
598  ansatz = ansatz_in;
599 
600  return;
601 }
602 
603 
604 
605 
606 
613 
614 
615  switch (ansatz){
616 
617  case HEA:
618  {
619 
620  release_gates();
621 
622  if ( qbit_num < 2 ) {
623  std::string error("Variational_Quantum_Eigensolver_Base::generate_initial_circuit: number of qubits should be at least 2");
624  throw error;
625  }
626 
627  for (int layer_idx=0; layer_idx<layers ;layer_idx++){
628 
629  for( int idx=0; idx<inner_blocks; idx++) {
630  add_u3(1);
631  add_u3(0);
632  add_cnot(1,0);
633  }
634 
635 
637  if (control_qbit+2<qbit_num){
638 
639  for( int idx=0; idx<inner_blocks; idx++) {
640  add_u3(control_qbit+1);
641  add_u3(control_qbit+2);
642 
644  }
645 
646  }
647 
648  for( int idx=0; idx<inner_blocks; idx++) {
649  add_u3(control_qbit+1);
651 
653 
654  }
655 
656  }
657  }
658 
659 
660  return;
661  }
662  case HEA_ZYZ:
663  {
664 
665  release_gates();
666 
667  if ( qbit_num < 2 ) {
668  std::string error("Variational_Quantum_Eigensolver_Base::generate_initial_circuit: number of qubits should be at least 2");
669  throw error;
670  }
671 
672  for (int layer_idx=0; layer_idx<layers ;layer_idx++){
673 
674  for( int idx=0; idx<inner_blocks; idx++) {
675  Gates_block* block_1 = new Gates_block( qbit_num );
676  Gates_block* block_2 = new Gates_block( qbit_num );
677 
678  // single qubit gates in a ablock are then merged into a single gate kernel.
679  block_1->add_rz(1);
680  block_1->add_ry(1);
681  block_1->add_rz(1);
682 
683  add_gate( block_1 );
684 
685  block_2->add_rz(0);
686  block_2->add_ry(0);
687  block_2->add_rz(0);
688 
689  add_gate( block_2 );
690 
691  add_cnot(1,0);
692  }
693 
695  if (control_qbit+2<qbit_num){
696 
697  for( int idx=0; idx<inner_blocks; idx++) {
698 
699  Gates_block* block_1 = new Gates_block( qbit_num );
700  Gates_block* block_2 = new Gates_block( qbit_num );
701 
702  block_1->add_rz(control_qbit+1);
703  block_1->add_ry(control_qbit+1);
704  block_1->add_rz(control_qbit+1);
705  add_gate( block_1 );
706 
707  block_2->add_rz(control_qbit+2);
708  block_2->add_ry(control_qbit+2);
709  block_2->add_rz(control_qbit+2);
710  add_gate( block_2 );
711 
713 
714  }
715 
716  }
717 
718  for( int idx=0; idx<inner_blocks; idx++) {
719 
720  Gates_block* block_1 = new Gates_block( qbit_num );
721  Gates_block* block_2 = new Gates_block( qbit_num );
722 
723  block_1->add_rz(control_qbit+1);
724  block_1->add_ry(control_qbit+1);
725  block_1->add_rz(control_qbit+1);
726  add_gate( block_1 );
727 
728  block_2->add_rz(control_qbit);
729  block_2->add_ry(control_qbit);
730  block_2->add_rz(control_qbit);
731  add_gate( block_2 );
732 
734  }
735 
736  }
737  }
738 
739 
740  return;
741  }
742  default:
743  std::string error("Variational_Quantum_Eigensolver_Base::generate_initial_circuit: ansatz not implemented");
744  throw error;
745  }
746 
747 }
748 
749 void
751 
752  release_gates();
753  Matrix_real optimized_parameters_mtx_tmp;
754  Gates_block* gate_structure_tmp = import_gate_list_from_binary(optimized_parameters_mtx_tmp, filename);
755 
756  if ( gates.size() > 0 ) {
757  gate_structure_tmp->combine( static_cast<Gates_block*>(this) );
758 
759  release_gates();
760  combine( gate_structure_tmp );
761 
762 
763  Matrix_real optimized_parameters_mtx_tmp2( 1, optimized_parameters_mtx_tmp.size() + optimized_parameters_mtx.size() );
764  memcpy( optimized_parameters_mtx_tmp2.get_data(), optimized_parameters_mtx_tmp.get_data(), optimized_parameters_mtx_tmp.size()*sizeof(double) );
765  memcpy( optimized_parameters_mtx_tmp2.get_data()+optimized_parameters_mtx_tmp.size(), optimized_parameters_mtx.get_data(), optimized_parameters_mtx.size()*sizeof(double) );
766  optimized_parameters_mtx = optimized_parameters_mtx_tmp2;
767  }
768  else {
769  combine( gate_structure_tmp );
770  optimized_parameters_mtx = optimized_parameters_mtx_tmp;
771 
772  std::stringstream sstream;
773  // get the number of gates used in the decomposition
774  std::map<std::string, int>&& gate_nums = get_gate_nums();
775 
776  for( auto it=gate_nums.begin(); it != gate_nums.end(); it++ ) {
777  sstream << it->second << " " << it->first << " gates" << std::endl;
778  }
779  print(sstream, 1);
780  }
781 
782 }
783 
784 
785 
786 
792 
793 
794 
795  // check the size of the input state
796  if ( initial_state_in.size() != 1 << qbit_num ) {
797  std::string error("Variational_Quantum_Eigensolver_Base::set_initial_state: teh number of elements in the input state does not match with the number of qubits.");
798  throw error;
799  }
800 
801  initial_state = Matrix( 1 << qbit_num, 1 );
802  memcpy( initial_state.get_data(), initial_state_in.get_data(), initial_state_in.size()*sizeof( QGD_Complex16 ) );
803 
804 }
805 
806 
807 
808 
optimization_aglorithms alg
The optimization algorithm to be used in the optimization.
bool adaptive_eta
logical variable indicating whether adaptive learning reate is used in the ADAM algorithm ...
void set_gate_structure(std::string filename)
Call to set custom layers to the gate structure that are intended to be used in the VQE process...
ansatz_type ansatz
Ansatz type (HEA stands for hardware efficient ansatz)
void print(const std::stringstream &sstream, int verbose_level=1) const
Call to print output messages in the function of the verbosity level.
Definition: logging.cpp:55
bool decomposition_finalized
The optimized parameters for the gates.
std::map< std::string, int > get_gate_nums()
Call to get the number of the individual gate types in the list of gates.
Class to solve VQE problems.
Matrix_real copy() const
Call to create a copy of the matrix.
int control_qbit
The index of the qubit which acts as a control qubit (control_qbit >= 0) in controlled operations...
Definition: Gate.h:87
double current_minimum
The current minimum of the optimization problem.
bool optimization_problem_solved
logical value describing whether the optimization problem was solved or not
void add_gate(Gate *gate)
Append a general gate to the list of gates.
cost_function_type cost_fnc
The chosen variant of the cost function.
Variational_Quantum_Eigensolver_Base()
Nullary constructor of the class.
void release_gates()
Call to release the stored gates.
tbb::spin_mutex my_mutex
void release_data()
Call to release the data stored by the matrix.
void add_cnot(int target_qbit, int control_qbit)
Append a CNOT gate gate to the list of gates.
QGD_Complex16 mult(QGD_Complex16 &a, QGD_Complex16 &b)
Call to calculate the product of two complex scalars.
Definition: common.cpp:259
Class to store data of complex arrays and its properties.
Definition: matrix_sparse.h:38
virtual void apply_to(Matrix_real &parameters_mtx, Matrix &input, int parallel=0)
Call to apply the gate on the input array/matrix Gates_block*input.
scalar * get_data() const
Call to get the pointer to the stored data.
virtual void optimization_problem_combined(Matrix_real parameters, double *f0, Matrix_real grad) override
Call to calculate both the cost function and the its gradient components.
Matrix initial_state
Quantum state used as an initial state in the VQE iterations.
Gates_block * import_gate_list_from_binary(Matrix_real &parameters, const std::string &filename, int verbosity)
?????????
virtual double optimization_problem_non_static(Matrix_real parameters, void *void_instance) override
The optimization problem of the final optimization.
std::vector< Gate * > gates
The list of stored gates.
Definition: Gates_block.h:46
void generate_circuit(int layers, int inner_blocks)
Call to generate the circuit ansatz.
double optimization_tolerance
The maximal allowed error of the optimization problem (The error of the decomposition would scale wit...
int get_parameter_num()
Call to get the number of free parameters.
static void optimization_problem_grad_vqe(Matrix_real parameters, void *void_instance, Matrix_real &grad)
Calculate the derivative of the cost function with respect to the free parameters.
int accelerator_num
number of utilized accelerators
int rows
The number of rows.
Definition: matrix_base.hpp:42
void start_optimization()
Call to start solving the VQE problem to get the approximation for the ground state.
double convergence_threshold
The convergence threshold in the optimization process.
int number_of_iters
number of iterations
ansatz_type
Type definition of the fifferent types of ansatz.
void add_u3(int target_qbit)
Append a U3 gate to the list of gates.
A base class to determine the decomposition of an N-qubit unitary into a sequence of CNOT and U3 gate...
void add_rz(int target_qbit)
Append a RZ gate to the list of gates.
QGD_Complex16 Expectation_value_of_energy(Matrix &State_left, Matrix &State_right)
Call to evaluate the expectation value of the energy <State_left| H | State_right>.
virtual void optimization_problem_combined_non_static(Matrix_real parameters, void *void_instance, double *f0, Matrix_real &grad) override
Call to calculate both the cost function and the its gradient components.
void combine(Gates_block *op_block)
Call to append the gates of an gate block to the current block.
void add_ry(int target_qbit)
Append a RY gate to the list of gates.
Structure type representing complex numbers in the SQUANDER package.
Definition: QGDTypes.h:38
void set_initial_state(Matrix initial_state_in)
Call to set the initial quantum state in the VQE iterations.
A base class to solve VQE problems This class can be used to approximate the ground state of the inpu...
virtual std::vector< Matrix > apply_derivate_to(Matrix_real &parameters_mtx, Matrix &input, int parallel)
Call to evaluate the derivate of the circuit on an inout with respect to all of the free parameters...
void set_ansatz(ansatz_type ansatz_in)
Call to set the ansatz type.
int Power_of_2(int n)
Calculates the n-th power of 2.
Definition: common.cpp:117
Class to store data of complex arrays and its properties.
Definition: matrix.h:38
int size() const
Call to get the number of the allocated elements.
Gates_block()
Default constructor of the class.
Definition: Gates_block.cpp:64
A class responsible for grouping two-qubit (CNOT,CZ,CH) and one-qubit gates into layers.
Definition: Gates_block.h:41
Matrix_sparse Hamiltonian
The Hamiltonian of the system.
std::map< std::string, Config_Element > config
config metadata utilized during the optimization
int parameter_num
the number of free parameters of the operation
Definition: Gate.h:91
void solve_layer_optimization_problem(int num_of_parameters, Matrix_real solution_guess)
Call to solve layer by layer the optimization problem via calling one of the implemented algorithms...
Matrix copy()
Call to create a copy of the matrix.
Definition: matrix.cpp:105
double Expectation_value_of_energy_real(Matrix &State_left, Matrix &State_right)
Call to evaluate the expectation value of the energy <State_left| H | State_right>.
double real
the real part of a complex number
Definition: QGDTypes.h:40
void initialize_zero_state()
Initialize the state used in the quantun circuit.
int qbit_num
number of qubits spanning the matrix of the operation
Definition: Gate.h:81
double decomposition_error
error of the final decomposition
int random_shift_count_max
the maximal number of parameter randomization tries to escape a local minimum.
Matrix_real optimized_parameters_mtx
The optimized parameters for the gates.
int get_parallel_configuration()
Get the parallel configuration from the config.
double global_target_minimum
The global target minimum of the optimization problem.
Class to store data of complex arrays and its properties.
Definition: matrix_real.h:39
std::mt19937 gen
Standard mersenne_twister_engine seeded with rd()
double imag
the imaginary part of a complex number
Definition: QGDTypes.h:42
virtual ~Variational_Quantum_Eigensolver_Base()
Destructor of the class.
virtual double optimization_problem(Matrix_real &parameters) override
The optimization problem of the final optimization.