Sequential Quantum Gate Decomposer  v1.9.6
Powerful decomposition of general unitarias into one- and two-qubit gates gates
AGENTS.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 #include "Optimization_Interface.h"
25 
26 #include "RL_experience.h"
27 
28 #include <fstream>
29 
30 
31 #ifdef __DFE__
32 #include "common_DFE.h"
33 #endif
34 
35 
36 
43 
44 
45 
46  if ( (((cost_fnc != FROBENIUS_NORM) && (cost_fnc != HILBERT_SCHMIDT_TEST)) && cost_fnc != VQE ) && (cost_fnc != INFIDELITY)) {
47  std::string err("Optimization_Interface::solve_layer_optimization_problem_AGENTS: Only cost functions 0 and 3 are implemented");
48  throw err;
49  }
50 
51 #ifdef __DFE__
52  if ( qbit_num >= 5 && get_accelerator_num() > 0 ) {
53  upload_Umtx_to_DFE();
54  }
55 #endif
56 
57 
58  if (gates.size() == 0 ) {
59  return;
60  }
61 
62 
63  double M_PI_quarter = M_PI/4;
64  double M_PI_half = M_PI/2;
65  double M_PI_double = M_PI*2;
66 
67  if (solution_guess.size() == 0 ) {
68  solution_guess = Matrix_real(num_of_parameters,1);
69  std::uniform_real_distribution<> distrib_real(0, M_PI_double);
70  for ( int idx=0; idx<num_of_parameters; idx++) {
71  solution_guess[idx] = distrib_real(gen);
72  }
73 
74  }
75 
76 
77 #ifdef __MPI__
78  MPI_Bcast( (void*)solution_guess.get_data(), num_of_parameters, MPI_DOUBLE, 0, MPI_COMM_WORLD);
79 #endif
80 
81 
82 
83 
84 
85  if (optimized_parameters_mtx.size() == 0) {
86  optimized_parameters_mtx = Matrix_real(1, num_of_parameters);
87  memcpy(optimized_parameters_mtx.get_data(), solution_guess.get_data(), num_of_parameters*sizeof(double) );
88  }
89 
90 
91 
92  tbb::tick_count optimization_start = tbb::tick_count::now();
93  double optimization_time = 0.0;
94 
95 
96 
97 
98 
100 
101  int max_inner_iterations_loc;
102  if ( config.count("max_inner_iterations_agent") > 0 ) {
103  long long value;
104  config["max_inner_iterations_agent"].get_property( value );
105  max_inner_iterations_loc = (int) value;
106  }
107  else if ( config.count("max_inner_iterations") > 0 ) {
108  long long value;
109  config["max_inner_iterations"].get_property( value );
110  max_inner_iterations_loc = (int) value;
111  }
112  else {
113  max_inner_iterations_loc = max_inner_iterations;
114  }
115 
116 
117  double optimization_tolerance_loc;
118  if ( config.count("optimization_tolerance_agent") > 0 ) {
119  config["optimization_tolerance_agent"].get_property( optimization_tolerance_loc );
120  }
121  else if ( config.count("optimization_tolerance") > 0 ) {
122  config["optimization_tolerance"].get_property( optimization_tolerance_loc );
123  }
124  else {
125  optimization_tolerance_loc = optimization_tolerance;
126  }
127 
128 
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 );
132  }
133  else if ( config.count("export_circuit_2_binary") > 0 ) {
134  config["export_circuit_2_binary"].get_property( export_circuit_2_binary_loc );
135  }
136  else {
137  export_circuit_2_binary_loc = 0;
138  }
139 
140 
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;
146  }
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;
151  }
152  else {
153  agent_lifetime_loc = 1000;
154  }
155 
156 
157 
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;
161  print(sstream, 2);
162 
163  double agent_randomization_rate_loc = 0.2;
164  if ( config.count("aagent_randomization_rate_agent") > 0 ) {
165 
166  config["agent_randomization_rate_agent"].get_property( agent_randomization_rate_loc );
167  }
168  else if ( config.count("agent_randomization_rate") > 0 ) {
169  config["agent_randomization_rate"].get_property( agent_randomization_rate_loc );
170  }
171 
172 
173 
174  int agent_num;
175  if ( config.count("agent_num_agent") > 0 ) {
176  long long value;
177  config["agent_num_agent"].get_property( value );
178  agent_num = (int) value;
179  }
180  else if ( config.count("agent_num") > 0 ) {
181  long long value;
182  config["agent_num"].get_property( value );
183  agent_num = (int) value;
184  }
185  else {
186  agent_num = 64;
187  }
188 
189 
190  double agent_exploration_rate = 0.2;
191  if ( config.count("agent_exploration_rate_agent") > 0 ) {
192 
193  config["agent_exploration_rate_agent"].get_property( agent_exploration_rate );
194  }
195  else if ( config.count("agent_exploration_rate") > 0 ) {
196  config["agent_exploration_rate"].get_property( agent_exploration_rate );
197  }
198 
199  int convergence_length = 20;
200  if ( config.count("convergence_length_agent") > 0 ) {
201  long long value;
202  config["convergence_length_agent"].get_property( value );
203  convergence_length = (int) value;
204  }
205  else if ( config.count("convergence_length") > 0 ) {
206  long long value;
207  config["convergence_length"].get_property( value );
208  convergence_length = (int) value;
209  }
210 
211  int linesearch_points = 3;
212  if ( config.count("linesearch_points_agent") > 0 ) {
213  long long value;
214  config["linesearch_points_agent"].get_property( value );
215  linesearch_points = (int) value;
216  }
217  else if ( config.count("linesearch_points") > 0 ) {
218  long long value;
219  config["linesearch_points"].get_property( value );
220  linesearch_points = (int) value;
221  }
222 
223 
224 
225  // The number if iterations after which the current results are displed/exported
226  int output_periodicity;
227  if ( config.count("output_periodicity_cosine") > 0 ) {
228  long long value = 1;
229  config["output_periodicity_cosine"].get_property( value );
230  output_periodicity = (int) value;
231  }
232  if ( config.count("output_periodicity") > 0 ) {
233  long long value = 1;
234  config["output_periodicity"].get_property( value );
235  output_periodicity = (int) value;
236  }
237  else {
238  output_periodicity = 0;
239  }
240 
241  sstream.str("");
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;
245  print(sstream, 2);
246 
247 
248  bool terminate_optimization = false;
249 
250  // vector stroing the lates values of current minimums to identify convergence
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;
255 
256  double var_current_minimum = DBL_MAX;
257 
258 
259  matrix_base<int> param_idx_agents( agent_num, 1 );
260 
261  // random generator of integers
262  std::uniform_int_distribution<> distrib_int(0, num_of_parameters-1);
263 
264  for(int agent_idx=0; agent_idx<agent_num; agent_idx++) {
265  // initital paraneter index of the agents
266  param_idx_agents[ agent_idx ] = distrib_int(gen);
267  }
268 
269 #ifdef __MPI__
270  MPI_Bcast( (void*)param_idx_agents.get_data(), agent_num, MPI_INT, 0, MPI_COMM_WORLD);
271 #endif
272 
273 
274  int most_successfull_agent = 0;
275 
276 
277 
278 tbb::tick_count t0_CPU = tbb::tick_count::now();
279 
280  // vector storing the parameter set usedby the individual agents.
281 
282  std::vector<Matrix_real> solution_guess_mtx_agents( agent_num );
283  solution_guess_mtx_agents.reserve( agent_num );
284 
285  std::uniform_real_distribution<> distrib_real(0.0, M_PI_double);
286 
287  for(int agent_idx=0; agent_idx<agent_num; agent_idx++) {
288 
289 
290  // initialize random parameters for the agent
291  Matrix_real solution_guess_mtx_agent = Matrix_real( num_of_parameters, 1 );
292  memset( solution_guess_mtx_agent.get_data(), 0, solution_guess_mtx_agent.size()*sizeof(double) );
293 
294 #ifdef __MPI__
295  if ( current_rank == 0 ) {
296 #endif
297 
298  if ( agent_idx == 0 ) {
299  memcpy( solution_guess_mtx_agent.get_data(), solution_guess.get_data(), solution_guess.size()*sizeof(double) );
300  }
301  else {
302  randomize_parameters( optimized_parameters_mtx, solution_guess_mtx_agent, current_minimum );
303  }
304 
305 
306 #ifdef __MPI__
307  }
308 
309  MPI_Bcast( solution_guess_mtx_agent.get_data(), num_of_parameters, MPI_DOUBLE, 0, MPI_COMM_WORLD);
310 #endif
311 
312  solution_guess_mtx_agents[ agent_idx ] = solution_guess_mtx_agent;
313 
314  }
315 
316 
317 
318 
319  // array storing the current minimum of th eindividual agents
320  Matrix_real current_minimum_agents;
321 
322  // intitial cost function for each of the agents
323  current_minimum_agents = optimization_problem_batched( solution_guess_mtx_agents );
324 
325  // arrays to store some parameter values needed to be restored later
326  Matrix_real parameter_value_save_agents( agent_num, 1 );
327 
328  // arrays to store the cost functions at shifted parameters
329  Matrix_real f0_shifted_pi2_agents;
330  Matrix_real f0_shifted_pi_agents;
331  Matrix_real f0_shifted_pi4_agents;
332  Matrix_real f0_shifted_3pi2_agents;
333 
334 
335  bool three_point_line_search = cost_fnc == FROBENIUS_NORM;
336  bool three_point_line_search_double_period = cost_fnc == VQE && linesearch_points == 3;
337  bool five_point_line_search = cost_fnc == HILBERT_SCHMIDT_TEST || ( cost_fnc == VQE && linesearch_points == 5 );
338 
339 
340 
341  // CPU time
342  CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
343 
345  for (long long iter_idx=0; iter_idx<max_inner_iterations_loc; iter_idx++) {
346 
347 
348  // CPU time
349  t0_CPU = tbb::tick_count::now();
350 
351 
352 #ifdef __MPI__
353 
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) );
356 
357  if ( current_rank == 0 ) {
358 #endif
359 
360  for(int agent_idx=0; agent_idx<agent_num; agent_idx++) {
361 
362  // agent local parameter set
363  Matrix_real& solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
364 
365  // determine parameter indices to be altered
366  int param_idx = distrib_int(gen);
367  param_idx_agents[agent_idx] = param_idx;
368 
369  // save the parameters to be restored later
370  parameter_value_save_agents[agent_idx] = solution_guess_mtx_agent[param_idx];
371 
372 
373  }
374 
375 #ifdef __MPI__
376  }
377 
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);
380 #endif
381 
382 
383  if ( three_point_line_search ) {
384 
385  // calsulate the cist functions at shifted parameter values
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;
389  }
390 
391  // CPU time
392  CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
393 
394  // calculate batched cost function
395  f0_shifted_pi2_agents = optimization_problem_batched( solution_guess_mtx_agents );
396 
397  // CPU time
398  t0_CPU = tbb::tick_count::now();
399 
400 
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;
404  }
405 
406  // CPU time
407  CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
408 
409  // calculate batched cost function
410  f0_shifted_pi_agents = optimization_problem_batched( solution_guess_mtx_agents );
411 
412 
413  // CPU time
414  t0_CPU = tbb::tick_count::now();
415 
416 
417  // determine the parameters of the cosine function and determine the parameter shift at the minimum
418  for ( int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
419 
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];
423 
424 
425  double A_times_cos = (current_minimum_agent-f0_shifted_pi)/2;
426  double offset = (current_minimum_agent+f0_shifted_pi)/2;
427 
428  double A_times_sin = offset - f0_shifted_pi2;
429 
430  double phi0 = atan2( A_times_sin, A_times_cos);
431 
432 
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);
435  //std::cout << amplitude << " " << offset << std::endl;
436 
437 
438  //update the parameter vector
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;
441 
442  current_minimum_agents[agent_idx] = offset - amplitude;
443 
444  }
445  }
446  else if ( three_point_line_search_double_period ) {
447 
448 
449  // calsulate the cist functions at shifted parameter values
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;
453  }
454 
455  // CPU time
456  CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
457 
458  // calculate batched cost function
459  f0_shifted_pi2_agents = optimization_problem_batched( solution_guess_mtx_agents );
460 
461  // CPU time
462  t0_CPU = tbb::tick_count::now();
463 
464 
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;
468  }
469 
470  // CPU time
471  CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
472 
473  // calculate batched cost function
474  f0_shifted_pi_agents = optimization_problem_batched( solution_guess_mtx_agents );
475 
476 
477  // CPU time
478  t0_CPU = tbb::tick_count::now();
479 
480 
481  // determine the parameters of the cosine function and determine the parameter shift at the minimum
482  for ( int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
483 
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];
487 
488 
489  double A_times_cos = (current_minimum_agent-f0_shifted_pi)/2;
490  double offset = (current_minimum_agent+f0_shifted_pi)/2;
491 
492  double A_times_sin = offset - f0_shifted_pi2;
493 
494  double phi0 = atan2( A_times_sin, A_times_cos);
495 
496 
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);
499  //std::cout << amplitude << " " << offset << std::endl;
500 
501 
502  //update the parameter vector
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;
505 
506  current_minimum_agents[agent_idx] = offset - amplitude;
507 
508  }
509 /*
510 double max = -DBL_MAX;
511 double min = DBL_MAX;
512 
513 double delta = 2*M_PI/1000;
514 for ( int idx =0; idx<1000; idx++ ) {
515 
516 Matrix_real& solution_guess_mtx_agent = solution_guess_mtx_agents[ 0 ];
517 solution_guess_mtx_agent[param_idx_agents[ 0 ]] += delta;
518 double rr = optimization_problem( solution_guess_mtx_agent );
519 //std::cout << rr << std::endl;
520 
521 if ( rr < min ) {
522  min = rr;
523 }
524 
525 
526 if ( rr > max ) {
527  max = rr;
528 }
529 
530 }
531 
532 double amplitude = (max-min)/2;
533 double offset = (max+min)/2;
534 std::cout <<"kkk " << amplitude << " " << offset << " " << param_idx_agents[ 0 ] << " " << parameter_value_save_agents[ 0 ] << std::endl;
535 
536 
537 Matrix_real tmp = optimization_problem_batched( solution_guess_mtx_agents );
538 tmp.print_matrix();
539 
540  current_minimum_agents.print_matrix();
541 exit(-1);
542 */
543  }
544  else if ( five_point_line_search ){
545 
546 
547  // calsulate the cist functions at shifted parameter values
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;
551  }
552 
553  // CPU time
554  CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
555 
556  // calculate batched cost function
557  f0_shifted_pi4_agents = optimization_problem_batched( solution_guess_mtx_agents );
558 
559  // CPU time
560  t0_CPU = tbb::tick_count::now();
561 
562 
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;
566  }
567 
568  // CPU time
569  CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
570 
571  // calculate batched cost function
572  f0_shifted_pi2_agents = optimization_problem_batched( solution_guess_mtx_agents );
573 
574 
575 
576  // CPU time
577  t0_CPU = tbb::tick_count::now();
578 
579 
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;
583  }
584 
585  // CPU time
586  CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
587 
588  // calculate batched cost function
589  f0_shifted_pi_agents = optimization_problem_batched( solution_guess_mtx_agents );
590 
591 
592  // CPU time
593  t0_CPU = tbb::tick_count::now();
594 
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;
598  }
599 
600  // CPU time
601  CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
602 
603  // calculate batched cost function
604  f0_shifted_3pi2_agents = optimization_problem_batched( solution_guess_mtx_agents );
605 
606 
607  // CPU time
608  t0_CPU = tbb::tick_count::now();
609 
610 
611  // determine the parameters of the cosine function and determine the parameter shift at the minimum
612  for ( int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
613 
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];
619 /*
620  f(p) = kappa*sin(2p+xi) + gamma*sin(p+phi) + offset
621  f(p + pi/4) = kappa*cos(2p+xi) + gamma*sin(p+pi/4+phi) + offset
622  f(p + pi/2) = -kappa*sin(2p+xi) + gamma*cos(p+phi) + offset
623  f(p + pi) = kappa*sin(2p+xi) - gamma*sin(p+phi) + offset
624  f(p + 3*pi/2) = -kappa*sin(2p+xi) - gamma*cos(p+phi) + offset
625 */
626 
627  double f1 = current_minimum_agent - f0_shifted_pi;
628  double f2 = f0_shifted_pi2 - f0_shifted_3pi2;
629 
630  double gamma = sqrt( f1*f1 + f2*f2 )*0.5;
631  //print( "gamma: ", gamma )
632 
633  double varphi = atan2( f1, f2) - parameter_value_save_agents[ agent_idx ];
634  //print( "varphi: ", varphi )
635 
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);
639 
640 
641  double kappa = sqrt( f3*f3 + f4*f4);
642  //print( "kappa: ", kappa )
643 
644  double xi = atan2( f3, f4) - 2*parameter_value_save_agents[ agent_idx ];
645  //print( "xi: ", xi )
646 
647 
648  double f;
649  double params[5];
650  params[0] = kappa;
651  params[1] = xi + 2*parameter_value_save_agents[ agent_idx ];
652  params[2] = gamma;
653  params[3] = varphi + parameter_value_save_agents[ agent_idx ];
654  params[4] = offset;
655 
656 
657  Matrix_real parameter_shift(1,1);
658  if ( abs(gamma) > abs(kappa) ) {
659  parameter_shift[0] = 3*M_PI/2 - varphi - parameter_value_save_agents[ agent_idx ];
660  }
661  else {
662  parameter_shift[0] = 3*M_PI/4 - xi/2 - parameter_value_save_agents[ agent_idx ]/2;
663  }
664  parameter_shift[0] = std::fmod( parameter_shift[0], M_PI_double);
665 
666  BFGS_Powell cBFGS_Powell(HS_partial_optimization_problem_combined,(void*)&params);
667  f = cBFGS_Powell.Start_Optimization(parameter_shift, 10);
668 
669  //update the parameter vector
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];
672 
673  current_minimum_agents[agent_idx] = f;
674 
675  }
676 
677  }
678 
679 
680 
681 
682 
683  // CPU time
684  CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
685 
686 
687  // CPU time
688  t0_CPU = tbb::tick_count::now();
689 
690 
691  // generate random numbers to manage the behavior of the agents
692  Matrix_real random_numbers( agent_num, 2 );
693  memset( random_numbers.get_data(), 0, 2*agent_num*sizeof(double) );
694 
695 #ifdef __MPI__
696  if ( current_rank == 0 ) {
697 #endif
698 
699  std::uniform_real_distribution<> distrib_to_choose(0.0, 1.0);
700 
701  for ( int agent_idx=0; agent_idx<2*agent_num; agent_idx++ ) {
702  random_numbers[agent_idx] = distrib_to_choose( gen );
703  }
704 
705 #ifdef __MPI__
706  }
707  MPI_Bcast( random_numbers.get_data(), 2*agent_num, MPI_DOUBLE, 0, MPI_COMM_WORLD);
708 #endif
709 
710 
711 /*
712  // build up probability distribution to use to chose between the agents
713  Matrix_real agent_probs( current_minimum_agents.size(), 1 );
714 
715  // create probability distribution in each 1000-th iteration
716  if ( iter_idx % agent_lifetime_loc == 0 ) {
717  double prob_sum = 0.0;
718  double current_minimum_agents_min = DBL_MAX;
719  for( int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
720  if ( current_minimum_agents_min > current_minimum_agents[agent_idx] ) {
721  current_minimum_agents_min = current_minimum_agents[agent_idx];
722  }
723  }
724 
725 
726  for( int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
727  double prob_loc = exp( (current_minimum_agents_min - current_minimum_agents[agent_idx])*40.0/current_minimum_agents_min );
728  agent_probs[agent_idx] = prob_loc;
729  prob_sum = prob_sum + prob_loc;
730  }
731 
732  for( int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
733  agent_probs[agent_idx] = agent_probs[agent_idx]/prob_sum;
734  }
735 
736 
737  }
738 */
739 
740  // ocassionaly recalculate teh current cost functions of the agents
741  if ( iter_idx % agent_lifetime_loc == 0 )
742  {
743  // recalculate the current cost functions
744  current_minimum_agents = optimization_problem_batched( solution_guess_mtx_agents );
745  }
746 
747 
748 
749  // govern the behavior of the agents
750  for ( int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
751  double& current_minimum_agent = current_minimum_agents[ agent_idx ];
752 
753 
754 
755  if (current_minimum_agent < optimization_tolerance_loc ) {
756  terminate_optimization = true;
757  current_minimum = current_minimum_agent;
758 
759  most_successfull_agent = agent_idx;
760 
761  Matrix_real& solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
762 
763  // export the parameters of the current, most successful agent
764  memcpy(optimized_parameters_mtx.get_data(), solution_guess_mtx_agent.get_data(), num_of_parameters*sizeof(double) );
765  }
766 
767 
768 
769  Matrix_real& solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
770 
771  // look for the best agent periodicaly
772  if ( iter_idx % agent_lifetime_loc == 0 )
773  {
774 
775 
776 
777  if ( current_minimum_agent <= current_minimum ) {
778 
779  most_successfull_agent = agent_idx;
780 
781  // export the parameters of the current, most successful agent
782  memcpy(optimized_parameters_mtx.get_data(), solution_guess_mtx_agent.get_data(), num_of_parameters*sizeof(double) );
783 
784  if ( export_circuit_2_binary_loc > 0 ) {
785  std::string filename("initial_circuit_iteration.binary");
786  if (project_name != "") {
787  filename=project_name+ "_" +filename;
788  }
790  }
791 
792 
793  current_minimum = current_minimum_agent;
794 
795 
796 
797  }
798  else {
799  // less successful agent migh choose to keep their current state, or choose the state of more successful agents
800 
801 #ifdef __MPI__
802  if ( current_rank == 0 ) {
803 #endif
804 
805  double random_num = random_numbers[ agent_idx*random_numbers.stride ];
806 
807  if ( random_num < agent_exploration_rate && agent_idx != most_successfull_agent) {
808  // choose the state of the most succesfull agent
809 
810  std::stringstream sstream;
811  sstream << "agent " << agent_idx << ": adopts the state of the most succesful agent. " << most_successfull_agent << std::endl;
812  print(sstream, 5);
813 
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) );
816 
817 
818  random_num = random_numbers[ agent_idx*random_numbers.stride + 1 ];
819 
820  if ( random_num < agent_randomization_rate_loc ) {
821  randomize_parameters( optimized_parameters_mtx, solution_guess_mtx_agent, current_minimum );
822  current_minimum_agents[agent_idx] = optimization_problem( solution_guess_mtx_agent );
823  }
824 
825 
826  }
827  else {
828  // keep the current state of the agent
829  }
830 
831 #ifdef __MPI__
832  }
833 
834  MPI_Bcast( (void*)solution_guess_mtx_agent.get_data(), num_of_parameters, MPI_DOUBLE, 0, MPI_COMM_WORLD);
835  MPI_Bcast( (void*)current_minimum_agents.get_data(), agent_num, MPI_DOUBLE, 0, MPI_COMM_WORLD);
836 #endif
837 
838  }
839 
840 
841  // test global convergence
842  if ( agent_idx == 0 ) {
843 
844  if ( output_periodicity>0 && iter_idx % output_periodicity == 0 ) {
846  }
847 
848  current_minimum_mean = current_minimum_mean + (current_minimum - current_minimum_vec[ current_minimum_idx ])/current_minimum_vec.size();
849  current_minimum_vec[ current_minimum_idx ] = current_minimum;
850  current_minimum_idx = (current_minimum_idx + 1) % current_minimum_vec.size();
851 
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);
855  }
856  var_current_minimum = std::sqrt(var_current_minimum)/current_minimum_vec.size();
857 
858 
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;
862  print(sstream, 3);
863  terminate_optimization = true;
864  }
865 
866  }
867 
868 
869  }
870 
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;
875  sstream << " circuit simulation time: " << circuit_simulation_time << std::endl;
876  print(sstream, 3);
877  }
878 
879 
880 
881 
882 #ifdef __MPI__
883  MPI_Barrier(MPI_COMM_WORLD);
884 #endif
885 
886  } // for agent_idx
887 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
888 
889 
890 
891  // terminate the agent if the whole optimization problem was solved
892  if ( terminate_optimization ) {
893  break;
894  }
895 
896  }
897 
898 
899  tbb::tick_count optimization_end = tbb::tick_count::now();
900  optimization_time = optimization_time + (optimization_end-optimization_start).seconds();
901  sstream.str("");
902  sstream << "AGENTS time: " << CPU_time << " " << current_minimum << std::endl;
903 
904  print(sstream, 1);
905 }
906 
907 
908 
915 
916 
917 
918  optimized_parameters_mtx = Matrix_real(solution_guess.get_data(), solution_guess.size(), 1);
919 
920  for( int loop_idx=0; loop_idx<1; loop_idx++ ) {
921 
922  Matrix_real solution_guess_AGENTS(num_of_parameters ,1);
923  memcpy( solution_guess_AGENTS.get_data(), optimized_parameters_mtx.get_data(), optimized_parameters_mtx.size()*sizeof(double) );
924 
925  solve_layer_optimization_problem_AGENTS( num_of_parameters, solution_guess_AGENTS );
926 
927 
928  Matrix_real solution_guess_COSINE(num_of_parameters, 1);
929  memcpy( solution_guess_COSINE.get_data(), optimized_parameters_mtx.get_data(), optimized_parameters_mtx.size()*sizeof(double) );
930 
931  solve_layer_optimization_problem_GRAD_DESCEND( num_of_parameters, solution_guess_COSINE );
932 
933  }
934 
935 
936 }
937 
938 
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.
Definition: logging.cpp:55
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.
Definition: AGENTS.cpp:42
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)
Definition: matrix_base.hpp:46
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.
Definition: Gates_block.h:49
A class implementing the BFGS optimizer based on conjugate gradient direction method of M...
Definition: BFGS_Powell.h:26
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.
#define M_PI
Definition: qgd_math.h:42
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.
Definition: logging.h:50
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 &parameters, 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
Definition: Gate.h:94
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.
Definition: AGENTS.cpp:914
Matrix_real optimized_parameters_mtx
The optimized parameters for the gates.
Matrix_real optimization_problem_batched(std::vector< Matrix_real > &parameters_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.
Definition: matrix_real.h:41
std::mt19937 gen
Standard mersenne_twister_engine seeded with rd()