47 std::string err(
"Optimization_Interface::solve_layer_optimization_problem_AGENTS: Only cost functions 0 and 3 are implemented");
58 if (
gates.size() == 0 ) {
63 double M_PI_quarter =
M_PI/4;
64 double M_PI_half =
M_PI/2;
65 double M_PI_double =
M_PI*2;
67 if (solution_guess.
size() == 0 ) {
69 std::uniform_real_distribution<> distrib_real(0, M_PI_double);
71 solution_guess[idx] = distrib_real(
gen);
92 tbb::tick_count optimization_start = tbb::tick_count::now();
93 double optimization_time = 0.0;
101 int max_inner_iterations_loc;
102 if (
config.count(
"max_inner_iterations_agent") > 0 ) {
104 config[
"max_inner_iterations_agent"].get_property( value );
105 max_inner_iterations_loc = (
int) value;
107 else if (
config.count(
"max_inner_iterations") > 0 ) {
109 config[
"max_inner_iterations"].get_property( value );
110 max_inner_iterations_loc = (
int) value;
117 double optimization_tolerance_loc;
118 if (
config.count(
"optimization_tolerance_agent") > 0 ) {
119 config[
"optimization_tolerance_agent"].get_property( optimization_tolerance_loc );
121 else if (
config.count(
"optimization_tolerance") > 0 ) {
122 config[
"optimization_tolerance"].get_property( optimization_tolerance_loc );
129 long long export_circuit_2_binary_loc;
130 if (
config.count(
"export_circuit_2_binary_agent") > 0 ) {
131 config[
"export_circuit_2_binary_agent"].get_property( export_circuit_2_binary_loc );
133 else if (
config.count(
"export_circuit_2_binary") > 0 ) {
134 config[
"export_circuit_2_binary"].get_property( export_circuit_2_binary_loc );
137 export_circuit_2_binary_loc = 0;
141 int agent_lifetime_loc;
142 if (
config.count(
"agent_lifetime_agent") > 0 ) {
143 long long agent_lifetime_loc_tmp;
144 config[
"agent_lifetime_agent"].get_property( agent_lifetime_loc_tmp );
145 agent_lifetime_loc = (
int)agent_lifetime_loc_tmp;
147 else if (
config.count(
"agent_lifetime") > 0 ) {
148 long long agent_lifetime_loc_tmp;
149 config[
"agent_lifetime"].get_property( agent_lifetime_loc_tmp );
150 agent_lifetime_loc = (
int)agent_lifetime_loc_tmp;
153 agent_lifetime_loc = 1000;
158 std::stringstream sstream;
159 sstream <<
"max_inner_iterations: " << max_inner_iterations_loc << std::endl;
160 sstream <<
"agent_lifetime_loc: " << agent_lifetime_loc << std::endl;
163 double agent_randomization_rate_loc = 0.2;
164 if (
config.count(
"aagent_randomization_rate_agent") > 0 ) {
166 config[
"agent_randomization_rate_agent"].get_property( agent_randomization_rate_loc );
168 else if (
config.count(
"agent_randomization_rate") > 0 ) {
169 config[
"agent_randomization_rate"].get_property( agent_randomization_rate_loc );
175 if (
config.count(
"agent_num_agent") > 0 ) {
177 config[
"agent_num_agent"].get_property( value );
178 agent_num = (
int) value;
180 else if (
config.count(
"agent_num") > 0 ) {
182 config[
"agent_num"].get_property( value );
183 agent_num = (
int) value;
190 double agent_exploration_rate = 0.2;
191 if (
config.count(
"agent_exploration_rate_agent") > 0 ) {
193 config[
"agent_exploration_rate_agent"].get_property( agent_exploration_rate );
195 else if (
config.count(
"agent_exploration_rate") > 0 ) {
196 config[
"agent_exploration_rate"].get_property( agent_exploration_rate );
199 int convergence_length = 20;
200 if (
config.count(
"convergence_length_agent") > 0 ) {
202 config[
"convergence_length_agent"].get_property( value );
203 convergence_length = (
int) value;
205 else if (
config.count(
"convergence_length") > 0 ) {
207 config[
"convergence_length"].get_property( value );
208 convergence_length = (
int) value;
211 int linesearch_points = 3;
212 if (
config.count(
"linesearch_points_agent") > 0 ) {
214 config[
"linesearch_points_agent"].get_property( value );
215 linesearch_points = (
int) value;
217 else if (
config.count(
"linesearch_points") > 0 ) {
219 config[
"linesearch_points"].get_property( value );
220 linesearch_points = (
int) value;
226 int output_periodicity;
227 if (
config.count(
"output_periodicity_cosine") > 0 ) {
229 config[
"output_periodicity_cosine"].get_property( value );
230 output_periodicity = (
int) value;
232 if (
config.count(
"output_periodicity") > 0 ) {
234 config[
"output_periodicity"].get_property( value );
235 output_periodicity = (
int) value;
238 output_periodicity = 0;
242 sstream <<
"AGENTS: number of agents " << agent_num << std::endl;
243 sstream <<
"AGENTS: exploration_rate " << agent_exploration_rate << std::endl;
244 sstream <<
"AGENTS: lifetime " << agent_lifetime_loc << std::endl;
248 bool terminate_optimization =
false;
251 Matrix_real current_minimum_vec(1, convergence_length);
252 memset( current_minimum_vec.
get_data(), 0, current_minimum_vec.
size()*
sizeof(double) );
253 double current_minimum_mean = 0.0;
254 int current_minimum_idx = 0;
256 double var_current_minimum = DBL_MAX;
262 std::uniform_int_distribution<> distrib_int(0, num_of_parameters-1);
264 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
266 param_idx_agents[ agent_idx ] = distrib_int(
gen);
270 MPI_Bcast( (
void*)param_idx_agents.
get_data(), agent_num, MPI_INT, 0, MPI_COMM_WORLD);
274 int most_successfull_agent = 0;
278 tbb::tick_count t0_CPU = tbb::tick_count::now();
282 std::vector<Matrix_real> solution_guess_mtx_agents( agent_num );
283 solution_guess_mtx_agents.reserve( agent_num );
285 std::uniform_real_distribution<> distrib_real(0.0, M_PI_double);
287 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
292 memset( solution_guess_mtx_agent.
get_data(), 0, solution_guess_mtx_agent.
size()*
sizeof(double) );
295 if ( current_rank == 0 ) {
298 if ( agent_idx == 0 ) {
299 memcpy( solution_guess_mtx_agent.
get_data(), solution_guess.
get_data(), solution_guess.
size()*
sizeof(double) );
312 solution_guess_mtx_agents[ agent_idx ] = solution_guess_mtx_agent;
326 Matrix_real parameter_value_save_agents( agent_num, 1 );
336 bool three_point_line_search_double_period =
cost_fnc ==
VQE && linesearch_points == 3;
342 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
345 for (
long long iter_idx=0; iter_idx<max_inner_iterations_loc; iter_idx++) {
349 t0_CPU = tbb::tick_count::now();
354 memset( param_idx_agents.
get_data(), 0, param_idx_agents.
size()*
sizeof(
int) );
355 memset( parameter_value_save_agents.
get_data(), 0.0, parameter_value_save_agents.
size()*
sizeof(double) );
357 if ( current_rank == 0 ) {
360 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
363 Matrix_real& solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
366 int param_idx = distrib_int(
gen);
367 param_idx_agents[agent_idx] = param_idx;
370 parameter_value_save_agents[agent_idx] = solution_guess_mtx_agent[param_idx];
378 MPI_Bcast( (
void*)param_idx_agents.
get_data(), agent_num, MPI_INT, 0, MPI_COMM_WORLD);
379 MPI_Bcast( (
void*)parameter_value_save_agents.
get_data(), agent_num, MPI_DOUBLE, 0, MPI_COMM_WORLD);
383 if ( three_point_line_search ) {
386 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
387 Matrix_real solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
388 solution_guess_mtx_agent[param_idx_agents[agent_idx]] += M_PI_half;
392 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
398 t0_CPU = tbb::tick_count::now();
401 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
402 Matrix_real solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
403 solution_guess_mtx_agent[param_idx_agents[agent_idx]] += M_PI_half;
407 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
414 t0_CPU = tbb::tick_count::now();
418 for (
int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
420 double current_minimum_agent = current_minimum_agents[agent_idx];
421 double f0_shifted_pi = f0_shifted_pi_agents[agent_idx];
422 double f0_shifted_pi2 = f0_shifted_pi2_agents[agent_idx];
425 double A_times_cos = (current_minimum_agent-f0_shifted_pi)/2;
426 double offset = (current_minimum_agent+f0_shifted_pi)/2;
428 double A_times_sin = offset - f0_shifted_pi2;
430 double phi0 = atan2( A_times_sin, A_times_cos);
433 double parameter_shift = phi0 > 0 ?
M_PI-phi0 : -phi0-
M_PI;
434 double amplitude = sqrt(A_times_sin*A_times_sin + A_times_cos*A_times_cos);
439 Matrix_real& solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
440 solution_guess_mtx_agent[param_idx_agents[ agent_idx ]] = parameter_value_save_agents[ agent_idx ] + parameter_shift;
442 current_minimum_agents[agent_idx] = offset - amplitude;
446 else if ( three_point_line_search_double_period ) {
450 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
451 Matrix_real solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
452 solution_guess_mtx_agent[param_idx_agents[agent_idx]] += M_PI_quarter;
456 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
462 t0_CPU = tbb::tick_count::now();
465 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
466 Matrix_real solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
467 solution_guess_mtx_agent[param_idx_agents[agent_idx]] += M_PI_quarter;
471 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
478 t0_CPU = tbb::tick_count::now();
482 for (
int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
484 double current_minimum_agent = current_minimum_agents[agent_idx];
485 double f0_shifted_pi = f0_shifted_pi_agents[agent_idx];
486 double f0_shifted_pi2 = f0_shifted_pi2_agents[agent_idx];
489 double A_times_cos = (current_minimum_agent-f0_shifted_pi)/2;
490 double offset = (current_minimum_agent+f0_shifted_pi)/2;
492 double A_times_sin = offset - f0_shifted_pi2;
494 double phi0 = atan2( A_times_sin, A_times_cos);
497 double parameter_shift = phi0 > 0 ? M_PI_half-phi0/2 : -phi0/2-M_PI_half;
498 double amplitude = sqrt(A_times_sin*A_times_sin + A_times_cos*A_times_cos);
503 Matrix_real& solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
504 solution_guess_mtx_agent[param_idx_agents[ agent_idx ]] = parameter_value_save_agents[ agent_idx ] + parameter_shift;
506 current_minimum_agents[agent_idx] = offset - amplitude;
544 else if ( five_point_line_search ){
548 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
549 Matrix_real solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
550 solution_guess_mtx_agent[param_idx_agents[agent_idx]] += M_PI_quarter;
554 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
560 t0_CPU = tbb::tick_count::now();
563 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
564 Matrix_real solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
565 solution_guess_mtx_agent[param_idx_agents[agent_idx]] += M_PI_quarter;
569 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
577 t0_CPU = tbb::tick_count::now();
580 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
581 Matrix_real solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
582 solution_guess_mtx_agent[param_idx_agents[agent_idx]] += M_PI_half;
586 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
593 t0_CPU = tbb::tick_count::now();
595 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
596 Matrix_real solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
597 solution_guess_mtx_agent[param_idx_agents[agent_idx]] += M_PI_half;
601 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
608 t0_CPU = tbb::tick_count::now();
612 for (
int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
614 double current_minimum_agent = current_minimum_agents[agent_idx];
615 double f0_shifted_pi4 = f0_shifted_pi4_agents[agent_idx];
616 double f0_shifted_pi2 = f0_shifted_pi2_agents[agent_idx];
617 double f0_shifted_pi = f0_shifted_pi_agents[agent_idx];
618 double f0_shifted_3pi2 = f0_shifted_3pi2_agents[agent_idx];
627 double f1 = current_minimum_agent - f0_shifted_pi;
628 double f2 = f0_shifted_pi2 - f0_shifted_3pi2;
630 double gamma = sqrt( f1*f1 + f2*f2 )*0.5;
633 double varphi = atan2( f1, f2) - parameter_value_save_agents[ agent_idx ];
636 double offset = 0.25*(current_minimum_agent + f0_shifted_pi + f0_shifted_pi2 + f0_shifted_3pi2);
637 double f3 = 0.5*(current_minimum_agent + f0_shifted_pi - 2*offset);
638 double f4 = f0_shifted_pi4 - offset - gamma*sin(parameter_value_save_agents[ agent_idx ]+M_PI_quarter+varphi);
641 double kappa = sqrt( f3*f3 + f4*f4);
644 double xi = atan2( f3, f4) - 2*parameter_value_save_agents[ agent_idx ];
651 params[1] = xi + 2*parameter_value_save_agents[ agent_idx ];
653 params[3] = varphi + parameter_value_save_agents[ agent_idx ];
658 if ( abs(gamma) > abs(kappa) ) {
659 parameter_shift[0] = 3*
M_PI/2 - varphi - parameter_value_save_agents[ agent_idx ];
662 parameter_shift[0] = 3*
M_PI/4 - xi/2 - parameter_value_save_agents[ agent_idx ]/2;
664 parameter_shift[0] = std::fmod( parameter_shift[0], M_PI_double);
670 Matrix_real& solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
671 solution_guess_mtx_agent[param_idx_agents[ agent_idx ]] = parameter_value_save_agents[ agent_idx ] + parameter_shift[0];
673 current_minimum_agents[agent_idx] =
f;
684 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
688 t0_CPU = tbb::tick_count::now();
693 memset( random_numbers.
get_data(), 0, 2*agent_num*
sizeof(double) );
696 if ( current_rank == 0 ) {
699 std::uniform_real_distribution<> distrib_to_choose(0.0, 1.0);
701 for (
int agent_idx=0; agent_idx<2*agent_num; agent_idx++ ) {
702 random_numbers[agent_idx] = distrib_to_choose(
gen );
707 MPI_Bcast( random_numbers.
get_data(), 2*agent_num, MPI_DOUBLE, 0, MPI_COMM_WORLD);
741 if ( iter_idx % agent_lifetime_loc == 0 )
750 for (
int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
751 double& current_minimum_agent = current_minimum_agents[ agent_idx ];
755 if (current_minimum_agent < optimization_tolerance_loc ) {
756 terminate_optimization =
true;
759 most_successfull_agent = agent_idx;
761 Matrix_real& solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
769 Matrix_real& solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
772 if ( iter_idx % agent_lifetime_loc == 0 )
779 most_successfull_agent = agent_idx;
784 if ( export_circuit_2_binary_loc > 0 ) {
785 std::string
filename(
"initial_circuit_iteration.binary");
802 if ( current_rank == 0 ) {
805 double random_num = random_numbers[ agent_idx*random_numbers.
stride ];
807 if ( random_num < agent_exploration_rate && agent_idx != most_successfull_agent) {
810 std::stringstream sstream;
811 sstream <<
"agent " << agent_idx <<
": adopts the state of the most succesful agent. " << most_successfull_agent << std::endl;
814 current_minimum_agents[ agent_idx ] = current_minimum_agents[ most_successfull_agent ];
815 memcpy( solution_guess_mtx_agent.
get_data(), solution_guess_mtx_agents[ most_successfull_agent ].get_data(), solution_guess_mtx_agent.
size()*
sizeof(double) );
818 random_num = random_numbers[ agent_idx*random_numbers.
stride + 1 ];
820 if ( random_num < agent_randomization_rate_loc ) {
835 MPI_Bcast( (
void*)current_minimum_agents.
get_data(), agent_num, MPI_DOUBLE, 0, MPI_COMM_WORLD);
842 if ( agent_idx == 0 ) {
844 if ( output_periodicity>0 && iter_idx % output_periodicity == 0 ) {
848 current_minimum_mean = current_minimum_mean + (
current_minimum - current_minimum_vec[ current_minimum_idx ])/current_minimum_vec.
size();
850 current_minimum_idx = (current_minimum_idx + 1) % current_minimum_vec.
size();
852 var_current_minimum = 0.0;
853 for (
int idx=0; idx<current_minimum_vec.
size(); idx++) {
854 var_current_minimum = var_current_minimum + (current_minimum_vec[idx]-current_minimum_mean)*(current_minimum_vec[idx]-current_minimum_mean);
856 var_current_minimum = std::sqrt(var_current_minimum)/current_minimum_vec.
size();
859 if ( std::abs( current_minimum_mean -
current_minimum) < 1e-7 && var_current_minimum < 1e-7 ) {
860 std::stringstream sstream;
861 sstream <<
"AGENTS, iterations converged to "<<
current_minimum << std::endl;
863 terminate_optimization =
true;
871 if ( iter_idx % agent_lifetime_loc == 0 && agent_idx == 0) {
872 std::stringstream sstream;
873 sstream <<
"AGENTS, agent " << agent_idx <<
": processed iterations " << (double)iter_idx/max_inner_iterations_loc*100 <<
"%";
874 sstream <<
", current minimum of agent 0: " << current_minimum_agents[ 0 ] <<
" global current minimum: " <<
current_minimum <<
" CPU time: " <<
CPU_time;
883 MPI_Barrier(MPI_COMM_WORLD);
887 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
892 if ( terminate_optimization ) {
899 tbb::tick_count optimization_end = tbb::tick_count::now();
900 optimization_time = optimization_time + (optimization_end-optimization_start).seconds();
920 for(
int loop_idx=0; loop_idx<1; loop_idx++ ) {
922 Matrix_real solution_guess_AGENTS(num_of_parameters ,1);
928 Matrix_real solution_guess_COSINE(num_of_parameters, 1);
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.
void solve_layer_optimization_problem_AGENTS(int num_of_parameters, Matrix_real &solution_guess)
Call to solve layer by layer the optimization problem via the AGENT algorithm.
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)
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.
void solve_layer_optimization_problem_GRAD_DESCEND(int num_of_parameters, Matrix_real &solution_guess)
Call to solve layer by layer the optimization problem via the GRAD_DESCEND (line search in the direct...
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.
void randomize_parameters(Matrix_real &input, Matrix_real &output, const double f0)
Call to randomize the parameter.
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.
Header file for a class ???
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
void HS_partial_optimization_problem_combined(Matrix_real parameters, void *void_params, double *f0, Matrix_real &grad)
???????????????
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...
void solve_layer_optimization_problem_AGENTS_COMBINED(int num_of_parameters, Matrix_real &solution_guess)
Call to solve layer by layer the optimization problem via the AGENT COMBINED algorithm.
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()