Sequential Quantum Gate Decomposer  v1.9.3
Powerful decomposition of general unitarias into one- and two-qubit gates gates
common/Bayes_Opt.cpp
Go to the documentation of this file.
1 /*
2 Copyright 2020 Peter Rakyta, Ph.D.
3 
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #define _USE_MATH_DEFINES
20 #include <math.h>
21 #include <cfloat>
22 #include <Bayes_Opt.h>
23 #include <Powells_method.h>
24 #include <common.h>
25 #include "tbb/tbb.h"
26 
27 extern "C" int LAPACKE_dposv(int matrix_layout, char uplo, int n, int nrhs, double* A, int LDA, double* B, int LDB);
28 
29 
35 
36  double* params = (double*)void_params;
37 
38  return params[0]*sin(2*parameters[0] + params[1]) + params[2]*sin(parameters[0] + params[3] ) + params[4];
39 }
40 
41 
47 
48 
49  double* params = (double*)void_params;
50  grad[0] = 2*params[0]*cos(2*parameters[0] + params[1]) + params[2]*cos(parameters[0] + params[3] );
51 
52 }
53 
54 
59 void HS_partial_optimization_problem_combined( Matrix_real parameters, void* void_params, double* f0, Matrix_real& grad) {
60 
61  *f0 = HS_partial_optimization_problem( parameters, void_params );
62  HS_partial_optimization_problem_grad( parameters, void_params, grad);
63 
64 
65 }
66 
67 
68 
69 
76 Bayes_Opt::Bayes_Opt(double (* f_pointer) (Matrix_real, void *), void* meta_data_in) {
77 
78  maximal_iterations = 101;
79 
80  // numerical precision used in the calculations
81  num_precision = 1.42e-14;
82 
83  alpha0 = 1;
84 
85  costfnc = f_pointer;
86 
87  meta_data = meta_data_in;
88 
89 
90  initial_samples = 12;
91 
92  mu_0 = M_PI;
93 
94  current_maximum = -10000.;
95 
96  // Will be used to obtain a seed for the random number engine
97  std::random_device rd;
98 
99  // seedign the random generator
100  gen = std::mt19937(rd());
101 
102 }
103 
104 double Bayes_Opt::Start_Optimization(Matrix_real& x, int max_iterations_in){
105 
106  variable_num = x.size();
107 
108 
109  maximal_iterations = max_iterations_in;
110 
111  //get samples of f0 at n0 points
112  for (int sample_idx=0; sample_idx<initial_samples; sample_idx++){
113  Matrix_real covariance_new(sample_idx,sample_idx);
114  Matrix_real parameters_new(1,variable_num);
115  std::normal_distribution<> distrib_real(0, M_PI/4);
116  double f_random;
117  for(int idx = 0; idx < variable_num; idx++) {
118  double random = distrib_real(gen);
119  parameters_new[idx] = x[idx] + random;
120  }
121  f_random = -1.*costfnc(parameters_new,meta_data);
122 
123  x_prev.push_back(parameters_new);
124  f_prev.push_back(f_random);
125  if (f_random>current_maximum) {
126  current_maximum = f_random;
127  memcpy(x.get_data(),parameters_new.get_data(),sizeof(double)*variable_num);
128  }
129  }
130  //construct covariance matrix
131  covariance = Matrix_real(initial_samples,initial_samples);
132  for (int idx=0; idx<initial_samples; idx++){
133  for (int jdx=0; jdx<initial_samples; jdx++){
134  covariance[idx*initial_samples + jdx] = kernel(x_prev[idx],x_prev[jdx]);
135  if (idx==jdx){
136  covariance[idx*initial_samples + jdx] = covariance[idx*initial_samples + jdx] +1e-4;
137  }
138  }
139  }
140 
141  //Start optimization
142  int iterations = initial_samples;
143  for (int iter = iterations; iter<maximal_iterations;iter++){
144 
145 
146  Matrix_real solution_guess = x_prev[iterations-1];
147 
148  Powells_method cPowells_method(optimization_problem,this);
149  double f_Powell = cPowells_method.Start_Optimization(solution_guess, 100);
150  double f = -1.*costfnc(solution_guess,meta_data);
151 
152  Matrix_real cov_x(1,(int)x_prev.size());
153 
154  for (int idx=0; idx<(int)x_prev.size();idx++){
155  cov_x[idx] = kernel(x_prev[idx],solution_guess);
156  }
157 
158  update_covariance(cov_x);
159  x_prev.push_back(solution_guess);
160  f_prev.push_back(f);
161  if (f>current_maximum){
162  current_maximum = f;
163  memcpy(x.get_data(),solution_guess.get_data(),sizeof(double)*variable_num);
164  }
165  /*Grad_Descend cBFGS_Powell(optimization_problem_combined, this);
166 
167  double f_bfgs = cBFGS_Powell.Start_Optimization(solution_guess, 100);
168  //solution_guess.print_matrix();
169  double f = -1.*costfnc(solution_guess,meta_data);
170 
171 
172  Matrix_real cov_x(1,(int)x_prev.size());
173  double self_cov = 1e-4;
174 
175  for (int idx=0; idx<(int)x_prev.size();idx++){
176  cov_x[idx] = kernel(x_prev[idx],solution_guess);
177  }
178 
179  update_covariance(cov_x);
180 
181  x_prev.push_back(solution_guess);
182  f_prev.push_back(f);
183  if (f>current_maximum){
184  current_maximum = f;
185  memcpy(solution_guess.get_data(),x.get_data(),sizeof(double)*variable_num);
186  }
187 
188  //std::cout<<iter<<std::endl;*/
189 
190  }
191  return -1.*current_maximum;
192 
193 }
194 
195 double Bayes_Opt::optimization_problem(Matrix_real x_Powell, void* void_instance){
196  Bayes_Opt* instance = reinterpret_cast<Bayes_Opt*>(void_instance);
197  int samples_n = (int)instance->x_prev.size();
198  int parameter_num = instance->variable_num;
199  Matrix_real cov_x(1,samples_n);
200  for (int idx=0; idx<samples_n; idx++){
201  cov_x[idx] = instance->kernel(x_Powell,(Matrix_real)instance->x_prev[idx]);
202  }
203  double mu_n = 0.0;
204  double sigma2_n = 0.0;
205  instance->calculate_conditional_distribution(x_Powell, cov_x, mu_n, sigma2_n);
206  double sigma_n = std::sqrt(std::fabs(sigma2_n));
207  double EI = -1.0*instance->expected_improvement(mu_n, sigma_n);
208  return EI;
209 }
210 
211 double Bayes_Opt::expected_improvement(double mu_n, double sigma_n){
212  double deltax = mu_n - current_maximum;
213  double deltax_max = (deltax>0.) ? deltax:0.0;
214 
215  double EI = deltax_max + sigma_n*pdf(deltax,sigma_n) - fabs(deltax)*cdf(deltax,sigma_n);
216  return EI;
217 }
218 
219 
220 void Bayes_Opt::calculate_conditional_distribution(Matrix_real x, Matrix_real cov_x, double& mu_n, double& sigma2_n){
221  double tol = 1e-6;
222  int samples = (int)f_prev.size();
223  Matrix_real mu_rhs(1,samples);
224  Matrix_real x0(1,samples);
225  for (int idx=0;idx<samples;idx++){
226  mu_rhs[idx] = f_prev[idx] - mu_0;
227  x0[idx] = M_PI;
228  }
229 
230  conjugate_gradient(covariance,mu_rhs,x0,tol);
231 
232  for (int idx=0;idx<samples;idx++){
233  mu_n = mu_n + x0[idx]*cov_x[idx];
234  }
235 
236  Matrix_real sigma2_rhs = cov_x.copy();
237  memset(x0.get_data(), M_PI, samples*sizeof(double) );
238  conjugate_gradient(covariance,mu_rhs,x0,tol);
239 
240  for (int idx=0;idx<mu_rhs.cols;idx++){
241  sigma2_n = sigma2_n + x0[idx] * cov_x[idx];
242  }
243 
244  sigma2_n = -1.0*(sigma2_n - kernel(x,x));
245 
246 
247  return;
248 
249 }
250 
251 
252 
254 
255  double dist=0.;
256  double sigma01 = 0.;
257  for (int idx=0; idx<variable_num; idx++){
258  dist = dist + (x0[idx]-x1[idx])*(x0[idx]-x1[idx]);
259  }
260  dist = std::sqrt(dist)/variable_num/variable_num;
261  sigma01 = alpha0*std::exp(-1.*std::sin(2*dist)*std::sin(2*dist)) + 1e-6;
262 
263  return sigma01;
264 
265 }
266 
267 double Bayes_Opt::pdf(double mu, double sigma){
268  return 1/sigma/std::sqrt(2*M_PI)*std::exp(0.5*(mu/sigma)*(mu/sigma));
269 }
270 
271 double Bayes_Opt::cdf(double mu, double sigma){
272  return 0.5+0.5*std::erf(mu/sigma/std::sqrt(2));
273 }
274 
275 double Bayes_Opt::grad_pdf(double mu, double sigma, double grad_mu, double grad_sigma){
276  return -1.0/sigma*grad_sigma*pdf(mu,sigma) - pdf(mu,sigma)*(grad_mu*sigma - mu*grad_sigma)/sigma/sigma;
277 }
278 
280 
281  int samples = covariance.cols+1;
282 
283  Matrix_real covariance_new(samples,samples);
284  double* data_new = covariance_new.get_data();
285  double* data_old = covariance.get_data();
287 
288  //copy old covariance matrix
289 
290  for (int idx=0;idx<covariance.cols; idx++){
291  memcpy(data_new + samples*idx,data_old + idx*covariance.cols,sizeof(double)*covariance.cols);
292  covariance_new[samples-1+idx*samples] = cov_new[idx];
293  }
294 
295  memcpy(data_new + (samples-1)*samples,cov_new.get_data(),sizeof(double)*covariance.cols);
296  covariance_new[samples*samples-1] = alpha0;
297 
298  covariance = covariance_new;
299  return;
300 }
301 
302 void Bayes_Opt::kernel_combined(Matrix_real x0, Matrix_real x, double& f, Matrix_real& grad, int grad_var, bool self){
303 
304  double dist=0.;
305  for (int idx=0; idx<variable_num; idx++){
306  dist = dist + (x0[idx]-x[idx])*(x0[idx]-x[idx]);
307  }
308  dist = std::sqrt(dist);
309  double cost_func_base = alpha0*std::exp(-1.*dist) + 1e-6;
310  f = cost_func_base;
311  for (int grad_idx=0; grad_idx<variable_num; grad_idx++){
312  double x1 = x[grad_idx];
313  grad[grad_var*variable_num + grad_idx] = 0.;
314  for (int idx=0; idx<variable_num; idx++){
315  if (grad_idx == idx && self == true){
316  grad[grad_var*variable_num + grad_idx] = 0.;
317  continue;
318  }
319  grad[grad_var*variable_num + grad_idx] = grad[grad_var*variable_num + grad_idx] - cost_func_base*(2.*x1-2.*x0[idx]);
320  }
321  }
322  return;
323 
324 }
325 
326 void Bayes_Opt::calculate_conditional_distribution_combined(Matrix_real x, Matrix_real cov_x, Matrix_real cov_x_grad, Matrix_real cov_self_grad, double& mu_n, double& sigma2_n, Matrix_real& grad_mu, Matrix_real& grad_sigma){
327 
328  int samples = (int)f_prev.size();
329  double tol = 1e-4;
330  Matrix_real b(1,samples);
331  Matrix_real mu_rhs(1,samples);
332  Matrix_real sigma2_rhs(1,samples);
333 
334 
335  Matrix_real sigma2_grad_rhs (samples,variable_num);
336  for (int idx=0;idx<samples;idx++){
337  b[idx] = f_prev[idx] - mu_0;
338  mu_rhs[idx] = 1.0;
339  sigma2_rhs[idx] = M_PI;
340  }
341  conjugate_gradient(covariance,b,mu_rhs,tol);
342  mu_n = 0.;
343  for (int idx=0; idx<samples; idx++){
344  mu_n = mu_n + mu_rhs[idx]*cov_x[idx];
345  }
346  mu_n = std::fabs(mu_n);
347  for (int grad_idx=0; grad_idx<variable_num; grad_idx++){
348  for (int idx=0;idx<samples;idx++){
349  grad_mu[grad_idx] = grad_mu[grad_idx] + cov_x_grad[idx*variable_num + grad_idx]*mu_rhs[idx];
350  //sigma2_grad_rhs[idx*variable_num + grad_idx] = M_PI;
351  }
352  }
353 
354  b = cov_x.copy();
355 
356  conjugate_gradient(covariance,b,sigma2_rhs,tol);
357  sigma2_n = 0.;
358  for (int idx=0;idx<samples;idx++){
359  sigma2_n = sigma2_n + sigma2_rhs[idx] * cov_x[idx];
360  }
361  sigma2_n = kernel(x,x)-sigma2_n;
362  //std::cout<<mu_n<<" "<<sigma2_n<<std::endl;
363  //b = cov_x_grad.copy();
364  // conjugate_gradient_parallel(covariance,b,sigma2_grad_rhs,tol);
365  for (int grad_idx=0; grad_idx<variable_num; grad_idx++){
366  b = Matrix_real(1,samples);
367  for (int idx=0;idx<samples;idx++){
368  b[idx] = cov_x_grad[idx*variable_num+grad_idx];
369  }
370  conjugate_gradient(covariance,b,sigma2_rhs,tol);
371  grad_sigma[grad_idx] = cov_self_grad[grad_idx];
372  for (int idx=0;idx<samples;idx++){
373  grad_sigma[grad_idx] = grad_sigma[grad_idx] - 2.*cov_x_grad[idx*variable_num + grad_idx];
374  }
375  grad_sigma[grad_idx] = grad_sigma[grad_idx]/std::sqrt(sigma2_n)/2;
376  }
377  //grad_sigma.print_matrix();
378  return;
379 
380 }
381 
382 void Bayes_Opt::expected_improvement_combined(double mu_n, double sigma_n, Matrix_real& grad_mu, Matrix_real& grad_sigma, double* f, Matrix_real& grad){
383  double deltax = mu_n - current_maximum;
384  double deltax_max = (deltax>0.) ? deltax:0.0;
385 
386  double pdf_mu = pdf(mu_n,sigma_n);
387  double cdf_mu = cdf(mu_n,sigma_n);
388  *f = -1.*(deltax_max + sigma_n*pdf_mu - fabs(deltax)*cdf_mu);
389 
390  for (int idx=0; idx<variable_num; idx++){
391  double deltax_grad = grad_mu[idx];
392  double deltax_max_grad = (deltax_grad>0.) ? grad_mu[idx] : 0.0;
393  double grad_rhs = -1.*std::fabs(deltax_grad)*cdf_mu - std::fabs(deltax)*pdf_mu*(grad_mu[idx]*sigma_n-mu_n*grad_sigma[idx])/sigma_n/sigma_n;
394  double grad_lhs = grad_sigma[idx]*pdf_mu + sigma_n*grad_pdf(mu_n,sigma_n,grad_mu[idx],grad_sigma[idx]);
395  grad[idx] = -1.;//*(deltax_max_grad + grad_lhs + grad_rhs);
396  }
397  return;
398 }
399 void Bayes_Opt::optimization_problem_combined(Matrix_real x_bfgs, void* void_instance, double* f0, Matrix_real& grad ){
400 
401  Bayes_Opt* instance = reinterpret_cast<Bayes_Opt*>(void_instance);
402  int samples_n = (int)instance->x_prev.size();
403  int parameter_num = instance->variable_num;
404  Matrix_real cov_x(1,samples_n);
405  Matrix_real cov_x_grad(samples_n,parameter_num);
406  //x_bfgs.print_matrix();
407  for (int grad_idx=0; grad_idx<samples_n; grad_idx++){
408  double cov_new;
409  instance->kernel_combined(x_bfgs, (Matrix_real)instance->x_prev[grad_idx], cov_new, cov_x_grad, grad_idx, false);
410  cov_x[grad_idx] = cov_new;
411  }
412  //cov_x_grad.print_matrix();
413  double placeholder;
414  Matrix_real cov_self_grad(1,parameter_num);
415 
416  instance->kernel_combined(x_bfgs, x_bfgs, placeholder,cov_self_grad,0,true);
417 
418  double mu_n = M_PI;
419  double sigma2_n;
420  Matrix_real grad_mu(1,parameter_num);
421  Matrix_real grad_sigma(1,parameter_num);
422 
423  instance -> calculate_conditional_distribution_combined(x_bfgs, cov_x, cov_x_grad, cov_self_grad, mu_n, sigma2_n, grad_mu, grad_sigma);
424 
425  double sigma_n = std::sqrt(sigma2_n);
426  instance -> expected_improvement_combined(mu_n,sigma_n,grad_mu,grad_sigma,f0,grad);
427  //grad.print_matrix();
428  return;
429 }
434 
435 }
436 
437 
438 
439 Bayes_Opt_Beam::Bayes_Opt_Beam(double (* f_pointer) (Matrix_real, void *), void* meta_data_in, int start_in, Matrix_real parameters_original_in) {
440 
441  maximal_iterations = 101;
442 
443  costfnc = f_pointer;
444 
445  meta_data = meta_data_in;
446 
447  current_maximum = -10000.;
448 
449  // Will be used to obtain a seed for the random number engine
450  std::random_device rd;
451 
452  // seedign the random generator
453  gen = std::mt19937(rd());
454 
455  parameters = parameters_original_in;
456 
457  start = start_in;
458 
459 
460 }
461 
462 
463 
464 double Bayes_Opt_Beam::optimization_problem(Matrix_real x_Beam, void* void_instance){
465  Bayes_Opt_Beam* instance = reinterpret_cast<Bayes_Opt_Beam*>(void_instance);
466  Matrix_real x = instance->parameters.copy();
467  memcpy(x.get_data() + instance->start,x_Beam.get_data(),sizeof(double)*x_Beam.size());
468  return instance->costfnc(x,instance->meta_data);
469 }
470 
471 
472 
473 double Bayes_Opt_Beam::Start_Optimization(Matrix_real& x, int max_iterations_in){
474 
475  variable_num = x.size();
476 
477  maximal_iterations = max_iterations_in;
478  Bayes_Opt cBayes_opt(optimization_problem,this);
479  double f = cBayes_opt.Start_Optimization(x,maximal_iterations);
480 
481  return f;
482 }
484 
485 }
parameter_num
[set adaptive gate structure]
void conjugate_gradient(Matrix_real A, Matrix_real b, Matrix_real &x0, double tol)
Definition: common.cpp:395
std::vector< double > f_prev
Definition: Bayes_Opt.h:90
Matrix_real copy() const
Call to create a copy of the matrix.
Matrix_real covariance
covariance matrix
Definition: Bayes_Opt.h:65
A class implementing the BayesOpt algorithm as seen in: https://browse.arxiv.org/pdf/1807.02811.pdf.
Definition: Bayes_Opt.h:59
double HS_partial_optimization_problem(Matrix_real parameters, void *void_params)
???????????????
double current_maximum
Definition: Bayes_Opt.h:94
std::mt19937 gen
Definition: Bayes_Opt.h:99
double Start_Optimization(Matrix_real &x, int max_iterations_in)
double expected_improvement(double mu_n, double sigma_n)
double grad_pdf(double mu, double sigma, double grad_mu, double grad_sigma)
scalar * get_data() const
Call to get the pointer to the stored data.
double Start_Optimization(Matrix_real &x, int max_iterations_in)
Matrix_real parameters
Definition: Bayes_Opt.h:156
int initial_samples
Definition: Bayes_Opt.h:97
double alpha0
amplitude of the kernel
Definition: Bayes_Opt.h:77
int cols
The number of columns.
Definition: matrix_base.hpp:44
long maximal_iterations
maximal count of iterations during the optimization
Definition: Bayes_Opt.h:71
void * meta_data
additional data needed to evaluate the cost function
Definition: Bayes_Opt.h:151
double mu_0
constant for the mean function
Definition: Bayes_Opt.h:62
double Start_Optimization(Matrix_real &x, long max_iter)
Bayes_Opt(double(*f_pointer)(Matrix_real, void *), void *meta_data_in)
Constructor of the class.
Bayes_Opt_Beam(double(*f_pointer)(Matrix_real, void *), void *meta_data_in, int start_in, Matrix_real parameters_original_in)
double kernel(Matrix_real x0, Matrix_real x1)
double num_precision
numerical precision used in the calculations
Definition: Bayes_Opt.h:74
int size() const
Call to get the number of the allocated elements.
A class implementing the Powells-algorithm as seen in: https://academic.oup.com/comjnl/article-abstra...
void update_covariance(Matrix_real cov_new)
double(* costfnc)(Matrix_real x, void *params)
function pointer to evaluate the cost function and its gradient vector
Definition: Bayes_Opt.h:80
void HS_partial_optimization_problem_grad(Matrix_real parameters, void *void_params, Matrix_real &grad)
???????????????
std::vector< Matrix_real > x_prev
previous parameters
Definition: Bayes_Opt.h:86
double cdf(double mu, double sigma)
static double optimization_problem(Matrix_real x_Beam, void *void_instance)
double pdf(double mu, double sigma)
Header file for commonly used functions and wrappers to CBLAS functions.
~Bayes_Opt()
Destructor of the class.
int LAPACKE_dposv(int matrix_layout, char uplo, int n, int nrhs, double *A, int LDA, double *B, int LDB)
void calculate_conditional_distribution(Matrix_real x, Matrix_real cov_x, double &mu_n, double &sigma2_n)
static void optimization_problem_combined(Matrix_real x, void *void_instance, double *f0, Matrix_real &grad)
void HS_partial_optimization_problem_combined(Matrix_real parameters, void *void_params, double *f0, Matrix_real &grad)
???????????????
void expected_improvement_combined(double mu_n, double sigma_n, Matrix_real &grad_mu, Matrix_real &grad_sigma, double *f, Matrix_real &grad)
void kernel_combined(Matrix_real x0, Matrix_real x, double &f, Matrix_real &grad, int grad_var, bool self)
int variable_num
number of independent variables in the problem
Definition: Bayes_Opt.h:68
void * meta_data
additional data needed to evaluate the cost function
Definition: Bayes_Opt.h:83
void calculate_conditional_distribution_combined(Matrix_real x, Matrix_real cov_x, Matrix_real cov_x_grad, Matrix_real cov_self_grad, double &mu_n, double &sigma2_n, Matrix_real &grad_mu, Matrix_real &grad_sigma)
Class to store data of complex arrays and its properties.
Definition: matrix_real.h:39
static double optimization_problem(Matrix_real x_Powell, void *void_instance)
double(* costfnc)(Matrix_real x, void *params)
function pointer to evaluate the cost function and its gradient vector
Definition: Bayes_Opt.h:148