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);
91 long long sub_iter_idx = 0;
95 tbb::tick_count optimization_start = tbb::tick_count::now();
96 double optimization_time = 0.0;
104 int max_inner_iterations_loc;
105 if (
config.count(
"max_inner_iterations_agent") > 0 ) {
107 config[
"max_inner_iterations_agent"].get_property( value );
108 max_inner_iterations_loc = (
int) value;
110 else if (
config.count(
"max_inner_iterations") > 0 ) {
112 config[
"max_inner_iterations"].get_property( value );
113 max_inner_iterations_loc = (
int) value;
120 double optimization_tolerance_loc;
121 if (
config.count(
"optimization_tolerance_agent") > 0 ) {
122 config[
"optimization_tolerance_agent"].get_property( optimization_tolerance_loc );
124 else if (
config.count(
"optimization_tolerance") > 0 ) {
125 config[
"optimization_tolerance"].get_property( optimization_tolerance_loc );
132 long long export_circuit_2_binary_loc;
133 if (
config.count(
"export_circuit_2_binary_agent") > 0 ) {
134 config[
"export_circuit_2_binary_agent"].get_property( export_circuit_2_binary_loc );
136 else if (
config.count(
"export_circuit_2_binary") > 0 ) {
137 config[
"export_circuit_2_binary"].get_property( export_circuit_2_binary_loc );
140 export_circuit_2_binary_loc = 0;
144 int agent_lifetime_loc;
145 if (
config.count(
"agent_lifetime_agent") > 0 ) {
146 long long agent_lifetime_loc_tmp;
147 config[
"agent_lifetime_agent"].get_property( agent_lifetime_loc_tmp );
148 agent_lifetime_loc = (
int)agent_lifetime_loc_tmp;
150 else if (
config.count(
"agent_lifetime") > 0 ) {
151 long long agent_lifetime_loc_tmp;
152 config[
"agent_lifetime"].get_property( agent_lifetime_loc_tmp );
153 agent_lifetime_loc = (
int)agent_lifetime_loc_tmp;
156 agent_lifetime_loc = 1000;
161 std::stringstream sstream;
162 sstream <<
"max_inner_iterations: " << max_inner_iterations_loc << std::endl;
163 sstream <<
"agent_lifetime_loc: " << agent_lifetime_loc << std::endl;
166 double agent_randomization_rate_loc = 0.2;
167 if (
config.count(
"aagent_randomization_rate_agent") > 0 ) {
169 config[
"agent_randomization_rate_agent"].get_property( agent_randomization_rate_loc );
171 else if (
config.count(
"agent_randomization_rate") > 0 ) {
172 config[
"agent_randomization_rate"].get_property( agent_randomization_rate_loc );
178 if (
config.count(
"agent_num_agent") > 0 ) {
180 config[
"agent_num_agent"].get_property( value );
181 agent_num = (
int) value;
183 else if (
config.count(
"agent_num") > 0 ) {
185 config[
"agent_num"].get_property( value );
186 agent_num = (
int) value;
193 double agent_exploration_rate = 0.2;
194 if (
config.count(
"agent_exploration_rate_agent") > 0 ) {
196 config[
"agent_exploration_rate_agent"].get_property( agent_exploration_rate );
198 else if (
config.count(
"agent_exploration_rate") > 0 ) {
199 config[
"agent_exploration_rate"].get_property( agent_exploration_rate );
202 int convergence_length = 20;
203 if (
config.count(
"convergence_length_agent") > 0 ) {
205 config[
"convergence_length_agent"].get_property( value );
206 convergence_length = (
int) value;
208 else if (
config.count(
"convergence_length") > 0 ) {
210 config[
"convergence_length"].get_property( value );
211 convergence_length = (
int) value;
214 int linesearch_points = 3;
215 if (
config.count(
"linesearch_points_agent") > 0 ) {
217 config[
"linesearch_points_agent"].get_property( value );
218 linesearch_points = (
int) value;
220 else if (
config.count(
"linesearch_points") > 0 ) {
222 config[
"linesearch_points"].get_property( value );
223 linesearch_points = (
int) value;
229 int output_periodicity;
230 if (
config.count(
"output_periodicity_cosine") > 0 ) {
232 config[
"output_periodicity_cosine"].get_property( value );
233 output_periodicity = (
int) value;
235 if (
config.count(
"output_periodicity") > 0 ) {
237 config[
"output_periodicity"].get_property( value );
238 output_periodicity = (
int) value;
241 output_periodicity = 0;
245 sstream <<
"AGENTS: number of agents " << agent_num << std::endl;
246 sstream <<
"AGENTS: exploration_rate " << agent_exploration_rate << std::endl;
247 sstream <<
"AGENTS: lifetime " << agent_lifetime_loc << std::endl;
251 bool terminate_optimization =
false;
254 Matrix_real current_minimum_vec(1, convergence_length);
255 memset( current_minimum_vec.
get_data(), 0.0, current_minimum_vec.
size()*
sizeof(double) );
256 double current_minimum_mean = 0.0;
257 int current_minimum_idx = 0;
259 double var_current_minimum = DBL_MAX;
265 std::uniform_int_distribution<> distrib_int(0, num_of_parameters-1);
267 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
269 param_idx_agents[ agent_idx ] = distrib_int(
gen);
273 MPI_Bcast( (
void*)param_idx_agents.
get_data(), agent_num, MPI_INT, 0, MPI_COMM_WORLD);
277 int most_successfull_agent = 0;
281 tbb::tick_count t0_CPU = tbb::tick_count::now();
285 std::vector<Matrix_real> solution_guess_mtx_agents( agent_num );
286 solution_guess_mtx_agents.reserve( agent_num );
288 std::uniform_real_distribution<> distrib_real(0.0, M_PI_double);
290 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
295 memset( solution_guess_mtx_agent.
get_data(), 0.0, solution_guess_mtx_agent.
size()*
sizeof(double) );
298 if ( current_rank == 0 ) {
301 if ( agent_idx == 0 ) {
302 memcpy( solution_guess_mtx_agent.
get_data(), solution_guess.
get_data(), solution_guess.
size()*
sizeof(double) );
315 solution_guess_mtx_agents[ agent_idx ] = solution_guess_mtx_agent;
329 Matrix_real parameter_value_save_agents( agent_num, 1 );
339 bool three_point_line_search_double_period =
cost_fnc ==
VQE && linesearch_points == 3;
345 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
348 for (
long long iter_idx=0; iter_idx<max_inner_iterations_loc; iter_idx++) {
352 t0_CPU = tbb::tick_count::now();
357 memset( param_idx_agents.
get_data(), 0, param_idx_agents.
size()*
sizeof(
int) );
358 memset( parameter_value_save_agents.
get_data(), 0.0, parameter_value_save_agents.
size()*
sizeof(double) );
360 if ( current_rank == 0 ) {
363 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
366 Matrix_real& solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
369 int param_idx = distrib_int(
gen);
370 param_idx_agents[agent_idx] = param_idx;
373 parameter_value_save_agents[agent_idx] = solution_guess_mtx_agent[param_idx];
381 MPI_Bcast( (
void*)param_idx_agents.
get_data(), agent_num, MPI_INT, 0, MPI_COMM_WORLD);
382 MPI_Bcast( (
void*)parameter_value_save_agents.
get_data(), agent_num, MPI_DOUBLE, 0, MPI_COMM_WORLD);
386 if ( three_point_line_search ) {
389 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
390 Matrix_real solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
391 solution_guess_mtx_agent[param_idx_agents[agent_idx]] += M_PI_half;
395 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
401 t0_CPU = tbb::tick_count::now();
404 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
405 Matrix_real solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
406 solution_guess_mtx_agent[param_idx_agents[agent_idx]] += M_PI_half;
410 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
417 t0_CPU = tbb::tick_count::now();
421 for (
int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
423 double current_minimum_agent = current_minimum_agents[agent_idx];
424 double f0_shifted_pi = f0_shifted_pi_agents[agent_idx];
425 double f0_shifted_pi2 = f0_shifted_pi2_agents[agent_idx];
428 double A_times_cos = (current_minimum_agent-f0_shifted_pi)/2;
429 double offset = (current_minimum_agent+f0_shifted_pi)/2;
431 double A_times_sin = offset - f0_shifted_pi2;
433 double phi0 = atan2( A_times_sin, A_times_cos);
436 double parameter_shift = phi0 > 0 ? M_PI-phi0 : -phi0-M_PI;
437 double amplitude = sqrt(A_times_sin*A_times_sin + A_times_cos*A_times_cos);
442 Matrix_real& solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
443 solution_guess_mtx_agent[param_idx_agents[ agent_idx ]] = parameter_value_save_agents[ agent_idx ] + parameter_shift;
445 current_minimum_agents[agent_idx] = offset - amplitude;
449 else if ( three_point_line_search_double_period ) {
453 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
454 Matrix_real solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
455 solution_guess_mtx_agent[param_idx_agents[agent_idx]] += M_PI_quarter;
459 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
465 t0_CPU = tbb::tick_count::now();
468 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
469 Matrix_real solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
470 solution_guess_mtx_agent[param_idx_agents[agent_idx]] += M_PI_quarter;
474 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
481 t0_CPU = tbb::tick_count::now();
485 for (
int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
487 double current_minimum_agent = current_minimum_agents[agent_idx];
488 double f0_shifted_pi = f0_shifted_pi_agents[agent_idx];
489 double f0_shifted_pi2 = f0_shifted_pi2_agents[agent_idx];
492 double A_times_cos = (current_minimum_agent-f0_shifted_pi)/2;
493 double offset = (current_minimum_agent+f0_shifted_pi)/2;
495 double A_times_sin = offset - f0_shifted_pi2;
497 double phi0 = atan2( A_times_sin, A_times_cos);
500 double parameter_shift = phi0 > 0 ? M_PI_half-phi0/2 : -phi0/2-M_PI_half;
501 double amplitude = sqrt(A_times_sin*A_times_sin + A_times_cos*A_times_cos);
506 Matrix_real& solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
507 solution_guess_mtx_agent[param_idx_agents[ agent_idx ]] = parameter_value_save_agents[ agent_idx ] + parameter_shift;
509 current_minimum_agents[agent_idx] = offset - amplitude;
547 else if ( five_point_line_search ){
551 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
552 Matrix_real solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
553 solution_guess_mtx_agent[param_idx_agents[agent_idx]] += M_PI_quarter;
557 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
563 t0_CPU = tbb::tick_count::now();
566 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
567 Matrix_real solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
568 solution_guess_mtx_agent[param_idx_agents[agent_idx]] += M_PI_quarter;
572 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
580 t0_CPU = tbb::tick_count::now();
583 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
584 Matrix_real solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
585 solution_guess_mtx_agent[param_idx_agents[agent_idx]] += M_PI_half;
589 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
596 t0_CPU = tbb::tick_count::now();
598 for(
int agent_idx=0; agent_idx<agent_num; agent_idx++) {
599 Matrix_real solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
600 solution_guess_mtx_agent[param_idx_agents[agent_idx]] += M_PI_half;
604 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
611 t0_CPU = tbb::tick_count::now();
615 for (
int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
617 double current_minimum_agent = current_minimum_agents[agent_idx];
618 double f0_shifted_pi4 = f0_shifted_pi4_agents[agent_idx];
619 double f0_shifted_pi2 = f0_shifted_pi2_agents[agent_idx];
620 double f0_shifted_pi = f0_shifted_pi_agents[agent_idx];
621 double f0_shifted_3pi2 = f0_shifted_3pi2_agents[agent_idx];
630 double f1 = current_minimum_agent - f0_shifted_pi;
631 double f2 = f0_shifted_pi2 - f0_shifted_3pi2;
633 double gamma = sqrt( f1*f1 + f2*f2 )*0.5;
636 double varphi = atan2( f1, f2) - parameter_value_save_agents[ agent_idx ];
639 double offset = 0.25*(current_minimum_agent + f0_shifted_pi + f0_shifted_pi2 + f0_shifted_3pi2);
640 double f3 = 0.5*(current_minimum_agent + f0_shifted_pi - 2*offset);
641 double f4 = f0_shifted_pi4 - offset - gamma*sin(parameter_value_save_agents[ agent_idx ]+M_PI_quarter+varphi);
644 double kappa = sqrt( f3*f3 + f4*f4);
647 double xi = atan2( f3, f4) - 2*parameter_value_save_agents[ agent_idx ];
654 params[1] = xi + 2*parameter_value_save_agents[ agent_idx ];
656 params[3] = varphi + parameter_value_save_agents[ agent_idx ];
661 if ( abs(gamma) > abs(kappa) ) {
662 parameter_shift[0] = 3*M_PI/2 - varphi - parameter_value_save_agents[ agent_idx ];
665 parameter_shift[0] = 3*M_PI/4 - xi/2 - parameter_value_save_agents[ agent_idx ]/2;
670 parameter_shift[0] = std::fmod( parameter_shift[0], M_PI_double);
676 Matrix_real& solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
677 solution_guess_mtx_agent[param_idx_agents[ agent_idx ]] = parameter_value_save_agents[ agent_idx ] + parameter_shift[0];
679 current_minimum_agents[agent_idx] = f;
690 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
694 t0_CPU = tbb::tick_count::now();
699 memset( random_numbers.
get_data(), 0.0, 2*agent_num*
sizeof(double) );
702 if ( current_rank == 0 ) {
705 std::uniform_real_distribution<> distrib_to_choose(0.0, 1.0);
707 for (
int agent_idx=0; agent_idx<2*agent_num; agent_idx++ ) {
708 random_numbers[agent_idx] = distrib_to_choose(
gen );
713 MPI_Bcast( random_numbers.
get_data(), 2*agent_num, MPI_DOUBLE, 0, MPI_COMM_WORLD);
747 if ( iter_idx % agent_lifetime_loc == 0 )
756 for (
int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
757 double& current_minimum_agent = current_minimum_agents[ agent_idx ];
761 if (current_minimum_agent < optimization_tolerance_loc ) {
762 terminate_optimization =
true;
765 most_successfull_agent = agent_idx;
767 Matrix_real& solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
775 Matrix_real& solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
778 if ( iter_idx % agent_lifetime_loc == 0 )
785 most_successfull_agent = agent_idx;
790 if ( export_circuit_2_binary_loc > 0 ) {
791 std::string
filename(
"initial_circuit_iteration.binary");
808 if ( current_rank == 0 ) {
811 double random_num = random_numbers[ agent_idx*random_numbers.
stride ];
813 if ( random_num < agent_exploration_rate && agent_idx != most_successfull_agent) {
816 std::stringstream sstream;
817 sstream <<
"agent " << agent_idx <<
": adopts the state of the most succesful agent. " << most_successfull_agent << std::endl;
820 current_minimum_agents[ agent_idx ] = current_minimum_agents[ most_successfull_agent ];
821 memcpy( solution_guess_mtx_agent.
get_data(), solution_guess_mtx_agents[ most_successfull_agent ].get_data(), solution_guess_mtx_agent.
size()*
sizeof(double) );
824 random_num = random_numbers[ agent_idx*random_numbers.
stride + 1 ];
826 if ( random_num < agent_randomization_rate_loc ) {
841 MPI_Bcast( (
void*)current_minimum_agents.
get_data(), agent_num, MPI_DOUBLE, 0, MPI_COMM_WORLD);
848 if ( agent_idx == 0 ) {
850 if ( output_periodicity>0 && iter_idx % output_periodicity == 0 ) {
854 current_minimum_mean = current_minimum_mean + (
current_minimum - current_minimum_vec[ current_minimum_idx ])/current_minimum_vec.
size();
856 current_minimum_idx = (current_minimum_idx + 1) % current_minimum_vec.
size();
858 var_current_minimum = 0.0;
859 for (
int idx=0; idx<current_minimum_vec.
size(); idx++) {
860 var_current_minimum = var_current_minimum + (current_minimum_vec[idx]-current_minimum_mean)*(current_minimum_vec[idx]-current_minimum_mean);
862 var_current_minimum = std::sqrt(var_current_minimum)/current_minimum_vec.
size();
865 if ( std::abs( current_minimum_mean -
current_minimum) < 1e-7 && var_current_minimum < 1e-7 ) {
866 std::stringstream sstream;
867 sstream <<
"AGENTS, iterations converged to "<<
current_minimum << std::endl;
869 terminate_optimization =
true;
877 if ( iter_idx % agent_lifetime_loc == 0 && agent_idx == 0) {
878 std::stringstream sstream;
879 sstream <<
"AGENTS, agent " << agent_idx <<
": processed iterations " << (double)iter_idx/max_inner_iterations_loc*100 <<
"\%";
880 sstream <<
", current minimum of agent 0: " << current_minimum_agents[ 0 ] <<
" global current minimum: " <<
current_minimum <<
" CPU time: " <<
CPU_time;
889 MPI_Barrier(MPI_COMM_WORLD);
893 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
898 if ( terminate_optimization ) {
905 tbb::tick_count optimization_end = tbb::tick_count::now();
906 optimization_time = optimization_time + (optimization_end-optimization_start).seconds();
926 for(
int loop_idx=0; loop_idx<1; loop_idx++ ) {
928 Matrix_real solution_guess_AGENTS(num_of_parameters ,1);
934 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.
double current_minimum
The current minimum of the optimization problem.
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.
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...
Header file for a class ???
void export_gate_list_to_binary(Matrix_real ¶meters, Gates_block *gates_block, const std::string &filename, int verbosity)
?????????
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.
void randomize_parameters(Matrix_real &input, Matrix_real &output, const double &f0)
Call to randomize the parameter.
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()