Sequential Quantum Gate Decomposer  v1.9.3
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  long long sub_iter_idx = 0;
92  double current_minimum_hold = current_minimum;
93 
94 
95  tbb::tick_count optimization_start = tbb::tick_count::now();
96  double optimization_time = 0.0;
97 
98 
99 
100 
101 
103 
104  int max_inner_iterations_loc;
105  if ( config.count("max_inner_iterations_agent") > 0 ) {
106  long long value;
107  config["max_inner_iterations_agent"].get_property( value );
108  max_inner_iterations_loc = (int) value;
109  }
110  else if ( config.count("max_inner_iterations") > 0 ) {
111  long long value;
112  config["max_inner_iterations"].get_property( value );
113  max_inner_iterations_loc = (int) value;
114  }
115  else {
116  max_inner_iterations_loc = max_inner_iterations;
117  }
118 
119 
120  double optimization_tolerance_loc;
121  if ( config.count("optimization_tolerance_agent") > 0 ) {
122  config["optimization_tolerance_agent"].get_property( optimization_tolerance_loc );
123  }
124  else if ( config.count("optimization_tolerance") > 0 ) {
125  config["optimization_tolerance"].get_property( optimization_tolerance_loc );
126  }
127  else {
128  optimization_tolerance_loc = optimization_tolerance;
129  }
130 
131 
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 );
135  }
136  else if ( config.count("export_circuit_2_binary") > 0 ) {
137  config["export_circuit_2_binary"].get_property( export_circuit_2_binary_loc );
138  }
139  else {
140  export_circuit_2_binary_loc = 0;
141  }
142 
143 
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;
149  }
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;
154  }
155  else {
156  agent_lifetime_loc = 1000;
157  }
158 
159 
160 
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;
164  print(sstream, 2);
165 
166  double agent_randomization_rate_loc = 0.2;
167  if ( config.count("aagent_randomization_rate_agent") > 0 ) {
168 
169  config["agent_randomization_rate_agent"].get_property( agent_randomization_rate_loc );
170  }
171  else if ( config.count("agent_randomization_rate") > 0 ) {
172  config["agent_randomization_rate"].get_property( agent_randomization_rate_loc );
173  }
174 
175 
176 
177  int agent_num;
178  if ( config.count("agent_num_agent") > 0 ) {
179  long long value;
180  config["agent_num_agent"].get_property( value );
181  agent_num = (int) value;
182  }
183  else if ( config.count("agent_num") > 0 ) {
184  long long value;
185  config["agent_num"].get_property( value );
186  agent_num = (int) value;
187  }
188  else {
189  agent_num = 64;
190  }
191 
192 
193  double agent_exploration_rate = 0.2;
194  if ( config.count("agent_exploration_rate_agent") > 0 ) {
195 
196  config["agent_exploration_rate_agent"].get_property( agent_exploration_rate );
197  }
198  else if ( config.count("agent_exploration_rate") > 0 ) {
199  config["agent_exploration_rate"].get_property( agent_exploration_rate );
200  }
201 
202  int convergence_length = 20;
203  if ( config.count("convergence_length_agent") > 0 ) {
204  long long value;
205  config["convergence_length_agent"].get_property( value );
206  convergence_length = (int) value;
207  }
208  else if ( config.count("convergence_length") > 0 ) {
209  long long value;
210  config["convergence_length"].get_property( value );
211  convergence_length = (int) value;
212  }
213 
214  int linesearch_points = 3;
215  if ( config.count("linesearch_points_agent") > 0 ) {
216  long long value;
217  config["linesearch_points_agent"].get_property( value );
218  linesearch_points = (int) value;
219  }
220  else if ( config.count("linesearch_points") > 0 ) {
221  long long value;
222  config["linesearch_points"].get_property( value );
223  linesearch_points = (int) value;
224  }
225 
226 
227 
228  // The number if iterations after which the current results are displed/exported
229  int output_periodicity;
230  if ( config.count("output_periodicity_cosine") > 0 ) {
231  long long value = 1;
232  config["output_periodicity_cosine"].get_property( value );
233  output_periodicity = (int) value;
234  }
235  if ( config.count("output_periodicity") > 0 ) {
236  long long value = 1;
237  config["output_periodicity"].get_property( value );
238  output_periodicity = (int) value;
239  }
240  else {
241  output_periodicity = 0;
242  }
243 
244  sstream.str("");
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;
248  print(sstream, 2);
249 
250 
251  bool terminate_optimization = false;
252 
253  // vector stroing the lates values of current minimums to identify convergence
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;
258 
259  double var_current_minimum = DBL_MAX;
260 
261 
262  matrix_base<int> param_idx_agents( agent_num, 1 );
263 
264  // random generator of integers
265  std::uniform_int_distribution<> distrib_int(0, num_of_parameters-1);
266 
267  for(int agent_idx=0; agent_idx<agent_num; agent_idx++) {
268  // initital paraneter index of the agents
269  param_idx_agents[ agent_idx ] = distrib_int(gen);
270  }
271 
272 #ifdef __MPI__
273  MPI_Bcast( (void*)param_idx_agents.get_data(), agent_num, MPI_INT, 0, MPI_COMM_WORLD);
274 #endif
275 
276 
277  int most_successfull_agent = 0;
278 
279 
280 
281 tbb::tick_count t0_CPU = tbb::tick_count::now();
282 
283  // vector storing the parameter set usedby the individual agents.
284 
285  std::vector<Matrix_real> solution_guess_mtx_agents( agent_num );
286  solution_guess_mtx_agents.reserve( agent_num );
287 
288  std::uniform_real_distribution<> distrib_real(0.0, M_PI_double);
289 
290  for(int agent_idx=0; agent_idx<agent_num; agent_idx++) {
291 
292 
293  // initialize random parameters for the agent
294  Matrix_real solution_guess_mtx_agent = Matrix_real( num_of_parameters, 1 );
295  memset( solution_guess_mtx_agent.get_data(), 0.0, solution_guess_mtx_agent.size()*sizeof(double) );
296 
297 #ifdef __MPI__
298  if ( current_rank == 0 ) {
299 #endif
300 
301  if ( agent_idx == 0 ) {
302  memcpy( solution_guess_mtx_agent.get_data(), solution_guess.get_data(), solution_guess.size()*sizeof(double) );
303  }
304  else {
305  randomize_parameters( optimized_parameters_mtx, solution_guess_mtx_agent, current_minimum );
306  }
307 
308 
309 #ifdef __MPI__
310  }
311 
312  MPI_Bcast( solution_guess_mtx_agent.get_data(), num_of_parameters, MPI_DOUBLE, 0, MPI_COMM_WORLD);
313 #endif
314 
315  solution_guess_mtx_agents[ agent_idx ] = solution_guess_mtx_agent;
316 
317  }
318 
319 
320 
321 
322  // array storing the current minimum of th eindividual agents
323  Matrix_real current_minimum_agents;
324 
325  // intitial cost function for each of the agents
326  current_minimum_agents = optimization_problem_batched( solution_guess_mtx_agents );
327 
328  // arrays to store some parameter values needed to be restored later
329  Matrix_real parameter_value_save_agents( agent_num, 1 );
330 
331  // arrays to store the cost functions at shifted parameters
332  Matrix_real f0_shifted_pi2_agents;
333  Matrix_real f0_shifted_pi_agents;
334  Matrix_real f0_shifted_pi4_agents;
335  Matrix_real f0_shifted_3pi2_agents;
336 
337 
338  bool three_point_line_search = cost_fnc == FROBENIUS_NORM;
339  bool three_point_line_search_double_period = cost_fnc == VQE && linesearch_points == 3;
340  bool five_point_line_search = cost_fnc == HILBERT_SCHMIDT_TEST || ( cost_fnc == VQE && linesearch_points == 5 );
341 
342 
343 
344  // CPU time
345  CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
346 
348  for (long long iter_idx=0; iter_idx<max_inner_iterations_loc; iter_idx++) {
349 
350 
351  // CPU time
352  t0_CPU = tbb::tick_count::now();
353 
354 
355 #ifdef __MPI__
356 
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) );
359 
360  if ( current_rank == 0 ) {
361 #endif
362 
363  for(int agent_idx=0; agent_idx<agent_num; agent_idx++) {
364 
365  // agent local parameter set
366  Matrix_real& solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
367 
368  // determine parameter indices to be altered
369  int param_idx = distrib_int(gen);
370  param_idx_agents[agent_idx] = param_idx;
371 
372  // save the parameters to be restored later
373  parameter_value_save_agents[agent_idx] = solution_guess_mtx_agent[param_idx];
374 
375 
376  }
377 
378 #ifdef __MPI__
379  }
380 
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);
383 #endif
384 
385 
386  if ( three_point_line_search ) {
387 
388  // calsulate the cist functions at shifted parameter values
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;
392  }
393 
394  // CPU time
395  CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
396 
397  // calculate batched cost function
398  f0_shifted_pi2_agents = optimization_problem_batched( solution_guess_mtx_agents );
399 
400  // CPU time
401  t0_CPU = tbb::tick_count::now();
402 
403 
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;
407  }
408 
409  // CPU time
410  CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
411 
412  // calculate batched cost function
413  f0_shifted_pi_agents = optimization_problem_batched( solution_guess_mtx_agents );
414 
415 
416  // CPU time
417  t0_CPU = tbb::tick_count::now();
418 
419 
420  // determine the parameters of the cosine function and determine the parameter shift at the minimum
421  for ( int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
422 
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];
426 
427 
428  double A_times_cos = (current_minimum_agent-f0_shifted_pi)/2;
429  double offset = (current_minimum_agent+f0_shifted_pi)/2;
430 
431  double A_times_sin = offset - f0_shifted_pi2;
432 
433  double phi0 = atan2( A_times_sin, A_times_cos);
434 
435 
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);
438  //std::cout << amplitude << " " << offset << std::endl;
439 
440 
441  //update the parameter vector
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;
444 
445  current_minimum_agents[agent_idx] = offset - amplitude;
446 
447  }
448  }
449  else if ( three_point_line_search_double_period ) {
450 
451 
452  // calsulate the cist functions at shifted parameter values
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;
456  }
457 
458  // CPU time
459  CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
460 
461  // calculate batched cost function
462  f0_shifted_pi2_agents = optimization_problem_batched( solution_guess_mtx_agents );
463 
464  // CPU time
465  t0_CPU = tbb::tick_count::now();
466 
467 
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;
471  }
472 
473  // CPU time
474  CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
475 
476  // calculate batched cost function
477  f0_shifted_pi_agents = optimization_problem_batched( solution_guess_mtx_agents );
478 
479 
480  // CPU time
481  t0_CPU = tbb::tick_count::now();
482 
483 
484  // determine the parameters of the cosine function and determine the parameter shift at the minimum
485  for ( int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
486 
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];
490 
491 
492  double A_times_cos = (current_minimum_agent-f0_shifted_pi)/2;
493  double offset = (current_minimum_agent+f0_shifted_pi)/2;
494 
495  double A_times_sin = offset - f0_shifted_pi2;
496 
497  double phi0 = atan2( A_times_sin, A_times_cos);
498 
499 
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);
502  //std::cout << amplitude << " " << offset << std::endl;
503 
504 
505  //update the parameter vector
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;
508 
509  current_minimum_agents[agent_idx] = offset - amplitude;
510 
511  }
512 /*
513 double max = -DBL_MAX;
514 double min = DBL_MAX;
515 
516 double delta = 2*M_PI/1000;
517 for ( int idx =0; idx<1000; idx++ ) {
518 
519 Matrix_real& solution_guess_mtx_agent = solution_guess_mtx_agents[ 0 ];
520 solution_guess_mtx_agent[param_idx_agents[ 0 ]] += delta;
521 double rr = optimization_problem( solution_guess_mtx_agent );
522 //std::cout << rr << std::endl;
523 
524 if ( rr < min ) {
525  min = rr;
526 }
527 
528 
529 if ( rr > max ) {
530  max = rr;
531 }
532 
533 }
534 
535 double amplitude = (max-min)/2;
536 double offset = (max+min)/2;
537 std::cout <<"kkk " << amplitude << " " << offset << " " << param_idx_agents[ 0 ] << " " << parameter_value_save_agents[ 0 ] << std::endl;
538 
539 
540 Matrix_real tmp = optimization_problem_batched( solution_guess_mtx_agents );
541 tmp.print_matrix();
542 
543  current_minimum_agents.print_matrix();
544 exit(-1);
545 */
546  }
547  else if ( five_point_line_search ){
548 
549 
550  // calsulate the cist functions at shifted parameter values
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;
554  }
555 
556  // CPU time
557  CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
558 
559  // calculate batched cost function
560  f0_shifted_pi4_agents = optimization_problem_batched( solution_guess_mtx_agents );
561 
562  // CPU time
563  t0_CPU = tbb::tick_count::now();
564 
565 
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;
569  }
570 
571  // CPU time
572  CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
573 
574  // calculate batched cost function
575  f0_shifted_pi2_agents = optimization_problem_batched( solution_guess_mtx_agents );
576 
577 
578 
579  // CPU time
580  t0_CPU = tbb::tick_count::now();
581 
582 
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;
586  }
587 
588  // CPU time
589  CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
590 
591  // calculate batched cost function
592  f0_shifted_pi_agents = optimization_problem_batched( solution_guess_mtx_agents );
593 
594 
595  // CPU time
596  t0_CPU = tbb::tick_count::now();
597 
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;
601  }
602 
603  // CPU time
604  CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
605 
606  // calculate batched cost function
607  f0_shifted_3pi2_agents = optimization_problem_batched( solution_guess_mtx_agents );
608 
609 
610  // CPU time
611  t0_CPU = tbb::tick_count::now();
612 
613 
614  // determine the parameters of the cosine function and determine the parameter shift at the minimum
615  for ( int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
616 
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];
622 /*
623  f(p) = kappa*sin(2p+xi) + gamma*sin(p+phi) + offset
624  f(p + pi/4) = kappa*cos(2p+xi) + gamma*sin(p+pi/4+phi) + offset
625  f(p + pi/2) = -kappa*sin(2p+xi) + gamma*cos(p+phi) + offset
626  f(p + pi) = kappa*sin(2p+xi) - gamma*sin(p+phi) + offset
627  f(p + 3*pi/2) = -kappa*sin(2p+xi) - gamma*cos(p+phi) + offset
628 */
629 
630  double f1 = current_minimum_agent - f0_shifted_pi;
631  double f2 = f0_shifted_pi2 - f0_shifted_3pi2;
632 
633  double gamma = sqrt( f1*f1 + f2*f2 )*0.5;
634  //print( "gamma: ", gamma )
635 
636  double varphi = atan2( f1, f2) - parameter_value_save_agents[ agent_idx ];
637  //print( "varphi: ", varphi )
638 
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);
642 
643 
644  double kappa = sqrt( f3*f3 + f4*f4);
645  //print( "kappa: ", kappa )
646 
647  double xi = atan2( f3, f4) - 2*parameter_value_save_agents[ agent_idx ];
648  //print( "xi: ", xi )
649 
650 
651  double f;
652  double params[5];
653  params[0] = kappa;
654  params[1] = xi + 2*parameter_value_save_agents[ agent_idx ];
655  params[2] = gamma;
656  params[3] = varphi + parameter_value_save_agents[ agent_idx ];
657  params[4] = offset;
658 
659 
660  Matrix_real parameter_shift(1,1);
661  if ( abs(gamma) > abs(kappa) ) {
662  parameter_shift[0] = 3*M_PI/2 - varphi - parameter_value_save_agents[ agent_idx ];
663  }
664  else {
665  parameter_shift[0] = 3*M_PI/4 - xi/2 - parameter_value_save_agents[ agent_idx ]/2;
666 
667 
668  }
669 
670  parameter_shift[0] = std::fmod( parameter_shift[0], M_PI_double);
671 
672  BFGS_Powell cBFGS_Powell(HS_partial_optimization_problem_combined,(void*)&params);
673  f = cBFGS_Powell.Start_Optimization(parameter_shift, 10);
674 
675  //update the parameter vector
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];
678 
679  current_minimum_agents[agent_idx] = f;
680 
681  }
682 
683  }
684 
685 
686 
687 
688 
689  // CPU time
690  CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
691 
692 
693  // CPU time
694  t0_CPU = tbb::tick_count::now();
695 
696 
697  // generate random numbers to manage the behavior of the agents
698  Matrix_real random_numbers( agent_num, 2 );
699  memset( random_numbers.get_data(), 0.0, 2*agent_num*sizeof(double) );
700 
701 #ifdef __MPI__
702  if ( current_rank == 0 ) {
703 #endif
704 
705  std::uniform_real_distribution<> distrib_to_choose(0.0, 1.0);
706 
707  for ( int agent_idx=0; agent_idx<2*agent_num; agent_idx++ ) {
708  random_numbers[agent_idx] = distrib_to_choose( gen );
709  }
710 
711 #ifdef __MPI__
712  }
713  MPI_Bcast( random_numbers.get_data(), 2*agent_num, MPI_DOUBLE, 0, MPI_COMM_WORLD);
714 #endif
715 
716 
717 /*
718  // build up probability distribution to use to chose between the agents
719  Matrix_real agent_probs( current_minimum_agents.size(), 1 );
720 
721  // create probability distribution in each 1000-th iteration
722  if ( iter_idx % agent_lifetime_loc == 0 ) {
723  double prob_sum = 0.0;
724  double current_minimum_agents_min = DBL_MAX;
725  for( int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
726  if ( current_minimum_agents_min > current_minimum_agents[agent_idx] ) {
727  current_minimum_agents_min = current_minimum_agents[agent_idx];
728  }
729  }
730 
731 
732  for( int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
733  double prob_loc = exp( (current_minimum_agents_min - current_minimum_agents[agent_idx])*40.0/current_minimum_agents_min );
734  agent_probs[agent_idx] = prob_loc;
735  prob_sum = prob_sum + prob_loc;
736  }
737 
738  for( int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
739  agent_probs[agent_idx] = agent_probs[agent_idx]/prob_sum;
740  }
741 
742 
743  }
744 */
745 
746  // ocassionaly recalculate teh current cost functions of the agents
747  if ( iter_idx % agent_lifetime_loc == 0 )
748  {
749  // recalculate the current cost functions
750  current_minimum_agents = optimization_problem_batched( solution_guess_mtx_agents );
751  }
752 
753 
754 
755  // govern the behavior of the agents
756  for ( int agent_idx=0; agent_idx<agent_num; agent_idx++ ) {
757  double& current_minimum_agent = current_minimum_agents[ agent_idx ];
758 
759 
760 
761  if (current_minimum_agent < optimization_tolerance_loc ) {
762  terminate_optimization = true;
763  current_minimum = current_minimum_agent;
764 
765  most_successfull_agent = agent_idx;
766 
767  Matrix_real& solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
768 
769  // export the parameters of the current, most successful agent
770  memcpy(optimized_parameters_mtx.get_data(), solution_guess_mtx_agent.get_data(), num_of_parameters*sizeof(double) );
771  }
772 
773 
774 
775  Matrix_real& solution_guess_mtx_agent = solution_guess_mtx_agents[ agent_idx ];
776 
777  // look for the best agent periodicaly
778  if ( iter_idx % agent_lifetime_loc == 0 )
779  {
780 
781 
782 
783  if ( current_minimum_agent <= current_minimum ) {
784 
785  most_successfull_agent = agent_idx;
786 
787  // export the parameters of the current, most successful agent
788  memcpy(optimized_parameters_mtx.get_data(), solution_guess_mtx_agent.get_data(), num_of_parameters*sizeof(double) );
789 
790  if ( export_circuit_2_binary_loc > 0 ) {
791  std::string filename("initial_circuit_iteration.binary");
792  if (project_name != "") {
793  filename=project_name+ "_" +filename;
794  }
796  }
797 
798 
799  current_minimum = current_minimum_agent;
800 
801 
802 
803  }
804  else {
805  // less successful agent migh choose to keep their current state, or choose the state of more successful agents
806 
807 #ifdef __MPI__
808  if ( current_rank == 0 ) {
809 #endif
810 
811  double random_num = random_numbers[ agent_idx*random_numbers.stride ];
812 
813  if ( random_num < agent_exploration_rate && agent_idx != most_successfull_agent) {
814  // choose the state of the most succesfull agent
815 
816  std::stringstream sstream;
817  sstream << "agent " << agent_idx << ": adopts the state of the most succesful agent. " << most_successfull_agent << std::endl;
818  print(sstream, 5);
819 
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) );
822 
823 
824  random_num = random_numbers[ agent_idx*random_numbers.stride + 1 ];
825 
826  if ( random_num < agent_randomization_rate_loc ) {
827  randomize_parameters( optimized_parameters_mtx, solution_guess_mtx_agent, current_minimum );
828  current_minimum_agents[agent_idx] = optimization_problem( solution_guess_mtx_agent );
829  }
830 
831 
832  }
833  else {
834  // keep the current state of the agent
835  }
836 
837 #ifdef __MPI__
838  }
839 
840  MPI_Bcast( (void*)solution_guess_mtx_agent.get_data(), num_of_parameters, MPI_DOUBLE, 0, MPI_COMM_WORLD);
841  MPI_Bcast( (void*)current_minimum_agents.get_data(), agent_num, MPI_DOUBLE, 0, MPI_COMM_WORLD);
842 #endif
843 
844  }
845 
846 
847  // test global convergence
848  if ( agent_idx == 0 ) {
849 
850  if ( output_periodicity>0 && iter_idx % output_periodicity == 0 ) {
852  }
853 
854  current_minimum_mean = current_minimum_mean + (current_minimum - current_minimum_vec[ current_minimum_idx ])/current_minimum_vec.size();
855  current_minimum_vec[ current_minimum_idx ] = current_minimum;
856  current_minimum_idx = (current_minimum_idx + 1) % current_minimum_vec.size();
857 
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);
861  }
862  var_current_minimum = std::sqrt(var_current_minimum)/current_minimum_vec.size();
863 
864 
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;
868  print(sstream, 3);
869  terminate_optimization = true;
870  }
871 
872  }
873 
874 
875  }
876 
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;
881  sstream << " circuit simulation time: " << circuit_simulation_time << std::endl;
882  print(sstream, 3);
883  }
884 
885 
886 
887 
888 #ifdef __MPI__
889  MPI_Barrier(MPI_COMM_WORLD);
890 #endif
891 
892  } // for agent_idx
893 CPU_time += (tbb::tick_count::now() - t0_CPU).seconds();
894 
895 
896 
897  // terminate the agent if the whole optimization problem was solved
898  if ( terminate_optimization ) {
899  break;
900  }
901 
902  }
903 
904 
905  tbb::tick_count optimization_end = tbb::tick_count::now();
906  optimization_time = optimization_time + (optimization_end-optimization_start).seconds();
907  sstream.str("");
908  sstream << "AGENTS time: " << CPU_time << " " << current_minimum << std::endl;
909 
910  print(sstream, 0);
911 }
912 
913 
914 
921 
922 
923 
924  optimized_parameters_mtx = Matrix_real(solution_guess.get_data(), solution_guess.size(), 1);
925 
926  for( int loop_idx=0; loop_idx<1; loop_idx++ ) {
927 
928  Matrix_real solution_guess_AGENTS(num_of_parameters ,1);
929  memcpy( solution_guess_AGENTS.get_data(), optimized_parameters_mtx.get_data(), optimized_parameters_mtx.size()*sizeof(double) );
930 
931  solve_layer_optimization_problem_AGENTS( num_of_parameters, solution_guess_AGENTS );
932 
933 
934  Matrix_real solution_guess_COSINE(num_of_parameters, 1);
935  memcpy( solution_guess_COSINE.get_data(), optimized_parameters_mtx.get_data(), optimized_parameters_mtx.size()*sizeof(double) );
936 
937  solve_layer_optimization_problem_GRAD_DESCEND( num_of_parameters, solution_guess_COSINE );
938 
939  }
940 
941 
942 }
943 
944 
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
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)
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:46
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.
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...
Header file for a class ???
void export_gate_list_to_binary(Matrix_real &parameters, Gates_block *gates_block, const std::string &filename, int verbosity)
?????????
int qbit_num
number of qubits spanning the matrix of the operation
Definition: Gate.h:81
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.
Definition: AGENTS.cpp:920
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:39
std::mt19937 gen
Standard mersenne_twister_engine seeded with rd()