47 std::string err(
"Optimization_Interface::solve_layer_optimization_problem_COSINE: Only cost functions FROBENIUS_NORM and VQE are implemented for this strategy");
58 tbb::tick_count t0_CPU = tbb::tick_count::now();
60 if (
gates.size() == 0 ) {
65 double M_PI_eight =
M_PI/8;
66 double M_PI_quarter =
M_PI/4;
67 double M_PI_half =
M_PI/2;
68 double M_PI_double =
M_PI*2;
70 if (solution_guess.
size() == 0 ) {
72 std::uniform_real_distribution<> distrib_real(0, M_PI_double);
74 solution_guess[idx] = distrib_real(
gen);
89 std::stringstream sstream;
90 double optimization_time = 0.0;
91 tbb::tick_count optimization_start = tbb::tick_count::now();
103 if (
config.count(
"batch_size_cosine") > 0 ) {
105 config[
"batch_size_cosine"].get_property( value );
106 batch_size = (
int) value;
108 else if (
config.count(
"batch_size") > 0 ) {
110 config[
"batch_size"].get_property( value );
111 batch_size = (
int) value;
118 if( batch_size > num_of_parameters ) {
119 std::string err(
"Optimization_Interface::solve_layer_optimization_problem_COSINE: batch size should be lower or equal to the number of free parameters");
125 unsigned long long max_inner_iterations_loc;
126 if (
config.count(
"max_inner_iterations_cosine") > 0 ) {
127 long long max_inner_iterations_loc_tmp;
128 config[
"max_inner_iterations_cosine"].get_property( max_inner_iterations_loc_tmp );
129 max_inner_iterations_loc = (
unsigned long long)max_inner_iterations_loc_tmp;
131 else if (
config.count(
"max_inner_iterations") > 0 ) {
132 long long max_inner_iterations_loc_tmp;
133 config[
"max_inner_iterations"].get_property( max_inner_iterations_loc_tmp );
134 max_inner_iterations_loc = (
unsigned long long)max_inner_iterations_loc_tmp;
141 long long export_circuit_2_binary_loc;
142 if (
config.count(
"export_circuit_2_binary_cosine") > 0 ) {
143 config[
"export_circuit_2_binary_cosine"].get_property( export_circuit_2_binary_loc );
145 else if (
config.count(
"export_circuit_2_binary") > 0 ) {
146 config[
"export_circuit_2_binary"].get_property( export_circuit_2_binary_loc );
149 export_circuit_2_binary_loc = 0;
152 long long check_for_convergence;
153 if (
config.count(
"check_for_convergence") > 0 ) {
154 config[
"check_for_convergence"].get_property( check_for_convergence );
156 else if (
config.count(
"check_for_convergence_cosine") > 0 ) {
157 config[
"check_for_convergence_cosine"].get_property( check_for_convergence );
160 check_for_convergence = 1;
164 double optimization_tolerance_loc;
165 if (
config.count(
"optimization_tolerance_cosine") > 0 ) {
166 config[
"optimization_tolerance_cosine"].get_property( optimization_tolerance_loc );
168 else if (
config.count(
"optimization_tolerance") > 0 ) {
169 config[
"optimization_tolerance"].get_property( optimization_tolerance_loc );
177 int output_periodicity;
178 if (
config.count(
"output_periodicity_cosine") > 0 ) {
180 config[
"output_periodicity_cosine"].get_property( value );
181 output_periodicity = (
int) value;
183 if (
config.count(
"output_periodicity") > 0 ) {
185 config[
"output_periodicity"].get_property( value );
186 output_periodicity = (
int) value;
189 output_periodicity = 0;
194 if ( output_periodicity>0 ) {
200 memset( f0_vec.
get_data(), 0, f0_vec.
size()*
sizeof(double) );
201 double f0_mean = 0.0;
210 std::vector<Matrix_real> parameters_mtx_vec(batch_size);
211 parameters_mtx_vec.reserve(batch_size);
216 bool three_point_line_search_double_period =
cost_fnc ==
VQE;
217 bool five_point_line_search_double_period =
cost_fnc ==
GQML;
220 for (
unsigned long long iter_idx=0; iter_idx<max_inner_iterations_loc; iter_idx++) {
223 std::vector<int> indices(num_of_parameters);
224 indices.reserve(num_of_parameters);
229 for(
int idx=0; idx<batch_size; idx++ ) {
230 parameters_mtx_vec[idx] = solution_guess_tmp_mtx.
copy();
233 std::uniform_int_distribution<> distrib_int(0, static_cast<int>(indices.size()-1));
236 int chosen_idx = distrib_int(
gen);
237 param_idx_agents[ idx ] = indices[ chosen_idx ];
238 indices.erase( indices.begin()+chosen_idx );
243 MPI_Bcast( (
void*)param_idx_agents.
get_data(), batch_size, MPI_INT, 0, MPI_COMM_WORLD);
248 if ( three_point_line_search ) {
250 for(
int idx=0; idx<batch_size; idx++) {
251 Matrix_real& solution_guess_mtx_idx = parameters_mtx_vec[ idx ];
252 solution_guess_mtx_idx[ param_idx_agents[idx] ] += M_PI_half;
258 for(
int idx=0; idx<batch_size; idx++) {
259 Matrix_real& solution_guess_mtx_idx = parameters_mtx_vec[ idx ];
260 solution_guess_mtx_idx[ param_idx_agents[idx] ] += M_PI_half;
265 for(
int idx=0; idx<batch_size; idx++ ) {
267 double f0_shifted_pi = f0_shifted_pi_agents[idx];
268 double f0_shifted_pi2 = f0_shifted_pi2_agents[idx];
274 double A_times_sin = offset - f0_shifted_pi2;
276 double phi0 = atan2( A_times_sin, A_times_cos);
279 double parameter_shift = phi0 > 0 ?
M_PI-phi0 : -phi0-
M_PI;
282 param_update_mtx[ idx ] = parameter_shift;
285 Matrix_real& solution_guess_mtx_idx = parameters_mtx_vec[idx];
286 solution_guess_mtx_idx[ param_idx_agents[idx] ] = solution_guess_tmp_mtx[ param_idx_agents[idx] ];
291 else if ( three_point_line_search_double_period ) {
293 for(
int idx=0; idx<batch_size; idx++) {
294 Matrix_real& solution_guess_mtx_idx = parameters_mtx_vec[ idx ];
295 solution_guess_mtx_idx[ param_idx_agents[idx] ] += M_PI_quarter;
301 for(
int idx=0; idx<batch_size; idx++) {
302 Matrix_real& solution_guess_mtx_idx = parameters_mtx_vec[ idx ];
303 solution_guess_mtx_idx[ param_idx_agents[idx] ] += M_PI_quarter;
308 for(
int idx=0; idx<batch_size; idx++ ) {
310 double f0_shifted_pi = f0_shifted_pi2_agents[idx];
311 double f0_shifted_pi2 = f0_shifted_pi4_agents[idx];
317 double A_times_sin = offset - f0_shifted_pi2;
319 double phi0 = atan2( A_times_sin, A_times_cos);
322 double parameter_shift = phi0 > 0 ? M_PI_half-phi0/2 : -phi0/2-M_PI_half;
325 param_update_mtx[ idx ] = parameter_shift;
328 Matrix_real& solution_guess_mtx_idx = parameters_mtx_vec[idx];
329 solution_guess_mtx_idx[ param_idx_agents[idx] ] = solution_guess_tmp_mtx[ param_idx_agents[idx] ];
333 else if (five_point_line_search_double_period) {
334 for (
int idx=0; idx<batch_size; idx++) {
335 Matrix_real& solution_guess_mtx_idx = parameters_mtx_vec[idx];
336 solution_guess_mtx_idx[param_idx_agents[idx]] += M_PI_eight;
341 for (
int idx=0; idx<batch_size; idx++) {
342 Matrix_real& solution_guess_mtx_idx = parameters_mtx_vec[idx];
343 solution_guess_mtx_idx[param_idx_agents[idx]] += M_PI_eight;
348 for (
int idx=0; idx<batch_size; idx++) {
349 Matrix_real& solution_guess_mtx_idx = parameters_mtx_vec[idx];
350 solution_guess_mtx_idx[param_idx_agents[idx]] += M_PI_quarter;
355 for (
int idx=0; idx<batch_size; idx++) {
356 Matrix_real& solution_guess_mtx_idx = parameters_mtx_vec[idx];
357 solution_guess_mtx_idx[param_idx_agents[idx]] += M_PI_quarter;
361 for (
int idx=0; idx<batch_size; idx++) {
362 double f0_shifted_pi8 = f0_shifted_pi8_agents[idx];
363 double f0_shifted_pi4 = f0_shifted_pi4_agents[idx];
364 double f0_shifted_pi2 = f0_shifted_pi2_agents[idx];
365 double f0_shifted_3pi4 = f0_shifted_3pi4_agents[idx];
368 double f2 = -f0_shifted_pi4 + f0_shifted_3pi4;
370 double B = 0.5*sqrt(f1*f1+f2*f2);
372 double delta = atan2(f1, f2) - 2*solution_guess_tmp_mtx[param_idx_agents[idx]];
374 double C = 0.25*(
current_minimum + f0_shifted_pi2 + f0_shifted_pi4 + f0_shifted_3pi4);
377 double f4 = f0_shifted_pi8 - C - B*cos(2*solution_guess_tmp_mtx[param_idx_agents[idx]] + M_PI_quarter +delta);
379 double A = sqrt(f3*f3 + f4*f4);
381 double phi = atan2(f3, f4) - 4*solution_guess_tmp_mtx[param_idx_agents[idx]];
385 params[1] = phi + 4*solution_guess_tmp_mtx[param_idx_agents[idx]];
387 params[3] = delta + 2*solution_guess_tmp_mtx[param_idx_agents[idx]];
391 if (abs(B) > abs(A)) {
392 parameter_shift[0] = M_PI_half - delta/2 -solution_guess_tmp_mtx[param_idx_agents[idx]]/2 ;
395 parameter_shift[0] = M_PI_quarter - phi/4 -solution_guess_tmp_mtx[param_idx_agents[idx]]/4;
397 parameter_shift[0] = std::fmod(parameter_shift[0], M_PI_double);
402 param_update_mtx[ idx ] = parameter_shift[0];
405 Matrix_real& solution_guess_mtx_idx = parameters_mtx_vec[idx];
406 solution_guess_mtx_idx[ param_idx_agents[idx] ] = solution_guess_tmp_mtx[ param_idx_agents[idx] ];
412 std::string err(
"solve_layer_optimization_problem_COSINE: Not implemented method.");
419 double interval_coeff = 2.0/(sqrt(5.0) + 1);
423 double point_a = 0.0;
424 double point_b = 1.0;
425 double epsilon = 1e-2;
427 double interval_length = point_b - point_a;
429 double x1 = point_a + interval_length*interval_coeff*interval_coeff;
434 for(
int idx=0; idx<batch_size; idx++ ) {
435 parameters_x1[ param_idx_agents[idx] ] += param_update_mtx[ idx ]*x1;
447 double current_best_point = point_a;
453 interval_length = point_b - point_a;
455 if ( interval_length < epsilon) {
459 if ( (x1-point_a) < (point_b-x1) ) {
461 x2 = point_a + interval_length*interval_coeff;
463 parameters_x2 = solution_guess_tmp_mtx.
copy();
465 for(
int idx=0; idx<batch_size; idx++ ) {
466 parameters_x2[ param_idx_agents[idx] ] += param_update_mtx[ idx ]*x2;
476 x1 = point_a + interval_length*interval_coeff*interval_coeff;
478 parameters_x1 = solution_guess_tmp_mtx.
copy();
480 for(
int idx=0; idx<batch_size; idx++ ) {
481 parameters_x1[ param_idx_agents[idx] ] += param_update_mtx[ idx ]*x1;
492 if ( val_x1 < val_x2 ) {
494 if ( current_best_value > val_x1 ) {
495 current_best_point = x1;
496 current_best_value = val_x1;
501 if ( current_best_value > val_x2 ) {
502 current_best_point = x2;
503 current_best_value = val_x2;
513 if ( iter > iter_max) {
514 std::stringstream sstream;
515 sstream <<
"line search not converged: interval length: " << interval_length <<
" " << interval_coeff << std::endl;
526 for (
int param_idx=0; param_idx<batch_size; param_idx++) {
527 solution_guess_tmp_mtx[ param_idx_agents[param_idx] ] += param_update_mtx[ param_idx ]*current_best_point;
581 if ( output_periodicity>0 && iter_idx % output_periodicity == 0 ) {
582 std::stringstream sstream;
583 sstream <<
"COSINE: processed iterations " << (double)iter_idx/max_inner_iterations_loc*100 <<
"%, current minimum:" <<
current_minimum;
586 if ( export_circuit_2_binary_loc > 0 ) {
587 std::string
filename(
"initial_circuit_iteration.binary");
596 if ( output_periodicity>0 && iter_idx % output_periodicity == 0 ) {
611 f0_idx = (f0_idx + 1) % f0_vec.
size();
614 for (
int idx=0; idx<f0_vec.
size(); idx++) {
615 var_f0 = var_f0 + (f0_vec[idx]-f0_mean)*(f0_vec[idx]-f0_mean);
617 var_f0 = std::sqrt(var_f0)/f0_vec.
size();
621 if ( std::abs( (f0_mean -
current_minimum)/f0_mean) < 1e-7 && std::abs(var_f0/f0_mean) < 1e-7 && check_for_convergence > 0 ) {
622 std::stringstream sstream;
623 sstream <<
"COSINE: converged to minimum at iterations " << (double)iter_idx/max_inner_iterations_loc*100 <<
"%, current minimum:" <<
current_minimum;
626 if ( export_circuit_2_binary_loc > 0 ) {
627 std::string
filename(
"initial_circuit_iteration.binary");
643 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
649 tbb::tick_count optimization_end = tbb::tick_count::now();
650 optimization_time = optimization_time + (optimization_end-optimization_start).seconds();
void export_current_cost_fnc(double current_minimum)
Call to print out into a file the current cost function and the second Rényi entropy on the subsyste...
void print(const std::stringstream &sstream, int verbose_level=1) const
Call to print output messages in the function of the verbosity level.
Matrix_real copy() const
Call to create a copy of the matrix.
void HS_partial_optimization_problem_cos_combined(Matrix_real parameters, void *void_params, double *f0, Matrix_real &grad)
???????????????
cost_function_type cost_fnc
The chosen variant of the cost function.
int get_accelerator_num()
Get the number of accelerators to be reserved on DFEs on users demand.
double optimization_problem(double *parameters)
Evaluate the optimization problem of the optimization.
scalar * get_data() const
Call to get the pointer to the stored data.
std::vector< Gate * > gates
The list of stored gates.
A class implementing the BFGS optimizer based on conjugate gradient direction method of M...
std::string project_name
the name of the project
double optimization_tolerance
The maximal allowed error of the optimization problem (The error of the decomposition would scale wit...
double Start_Optimization(Matrix_real &x, long maximal_iterations_in=5001)
Call this method to start the optimization.
double CPU_time
time spent on optimization
int verbose
Set the verbosity level of the output messages.
double circuit_simulation_time
Time spent on circuit simulation/cost function evaluation.
int size() const
Call to get the number of the allocated elements.
std::map< std::string, Config_Element > config
config metadata utilized during the optimization
Header file for the paralleized calculation of the cost function of the final optimization problem (s...
volatile double current_minimum
The current minimum of the optimization problem.
void solve_layer_optimization_problem_COSINE(int num_of_parameters, Matrix_real &solution_guess)
Call to solve layer by layer the optimization problem via the COSINE algorithm.
void export_gate_list_to_binary(Matrix_real ¶meters, Gates_block *gates_block, const std::string &filename, int verbosity)
Use to export a quantum circuit into binary format.
int qbit_num
number of qubits spanning the matrix of the operation
Header file for DFE support in unitary simulation.
int max_inner_iterations
the maximal number of iterations for which an optimization engine tries to solve the optimization pro...
Matrix_real optimized_parameters_mtx
The optimized parameters for the gates.
Matrix_real optimization_problem_batched(std::vector< Matrix_real > ¶meters_vec)
The cost function of the optimization with batched input (implemented only for the Frobenius norm cos...
Class to store data of complex arrays and its properties.
std::mt19937 gen
Standard mersenne_twister_engine seeded with rd()