Sequential Quantum Gate Decomposer  v1.9.3
Powerful decomposition of general unitarias into one- and two-qubit gates gates
Powells_method.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 #include <math.h>
20 #include <cfloat>
21 #include <Powells_method.h>
22 #include "tbb/tbb.h"
23 
24 extern "C" int LAPACKE_dposv(int matrix_layout, char uplo, int n, int nrhs, double* A, int LDA, double* B, int LDB);
31 Powells_method::Powells_method(double (* f_pointer) (Matrix_real, void *), void* meta_data_in) {
32 
33  costfnc = f_pointer;
34 
35  meta_data = meta_data_in;
36 
37 }
38 
40  Matrix_real x_new(1,variable_num);
41  for (int idx=0;idx<variable_num;idx++){
42  x_new[idx] = x[idx] + s*v[idx];
43  }
44  return costfnc(x_new,meta_data);
45 }
46 
47 void Powells_method::bracket(double x1, double h, double& a, double& b, Matrix_real x){
48  double c=1.618033989;
49  double f1 = direction(x1,x);
50  double x2 = x1 + h;
51  double f2 = direction(x2,x);
52  if (f2>f1){
53  h = -1.*h;
54  x2 = x1 +h;
55  f2 = direction(x2,x);
56  if (f2>f1){
57  a = x2;
58  b = x1 - h;
59  return;
60  }
61  }
62  for (int idx=0;idx<100;idx++){
63  h = c*h;
64  double x3 = x2 + h;
65  double f3 = direction(x3,x);
66  if (f3>f2){
67  a = x1;
68  b = x3;
69  return;
70  }
71  x1 = x2;
72  x2 = x3;
73  f1 = f2;
74  f2 = f3;
75  }
76 }
77 void Powells_method::search(double a, double b, double& s, double& f_val, double tol, Matrix_real x){
78 
79  int nIter = (int)std::ceil(-2.078087*std::log(tol/std::fabs(b-a)));
80  double R = 0.618033989;
81  double C = 1.0 - R;
82  double x1 = R*a + C*b;
83  double x2 = C*a + R*b;
84  double f1 = direction(x1,x);
85  double f2 = direction(x2,x);
86  for (int iter=0; iter<nIter;iter++){
87  if (f1>f2){
88  a = x1;
89  x1 = x2;
90  f1 = f2;
91  x2 = C*a + R*b;
92  f2 = direction(x2,x);
93  }
94  else {
95  b=x2;
96  x2 = x1;
97  f2 = f1;
98  x1 = R*a + C*b;
99  f1 = direction(x1,x);
100  }
101  }
102  if (f1<f2){
103  s = x1;
104  f_val = f1;
105  }
106  else{
107  s = x2;
108  f_val = f2;
109  }
110  return;
111 }
113  double h = 0.1;
114  double tol = 1e-6;
115  variable_num = x.size();
117  memset(u.get_data(), 0.0, variable_num*variable_num*sizeof(double) );
118  for (int var_idx=0;var_idx<variable_num;var_idx++){
119  u[var_idx*variable_num + var_idx] = 1.0;
120  }
121  Matrix_real df(1,variable_num);
122  memset(df.get_data(), 0.0, variable_num*sizeof(double) );
123  double a;
124  double b;
125  double s;
126  double fMin;
127  double fLast;
128  v = Matrix_real(1,variable_num);
129  for (int iter=0;iter<max_iter;iter++){
130  Matrix_real xOld = x.copy();
131  double fOld = costfnc(xOld,meta_data);
132  for (int var_idx=0;var_idx<variable_num;var_idx++){
133  memcpy(v.get_data(),u.get_data()+var_idx*variable_num,sizeof(double)*variable_num);
134  bracket(0.0,h,a,b,x);
135  search(a,b,s,fMin,tol,x);
136  df[var_idx] = fOld - fMin;
137  fOld = fMin;
138  for (int idx=0;idx<variable_num;idx++){
139  x[idx] = x[idx] + s*v[idx];
140  }
141  }
142  for (int idx=0;idx<variable_num;idx++){
143  v[idx] = x[idx] - xOld[idx];
144  }
145  bracket(0.0,h,a,b,x);
146  search(a,b,s,fLast,tol,x);
147  double dot=0.;
148  for (int idx=0;idx<variable_num;idx++){
149  x[idx] = x[idx] + s*v[idx];
150  dot = dot + (x[idx] - xOld[idx])*(x[idx] - xOld[idx]);
151  }
152  if(std::sqrt(dot)/variable_num<tol){return costfnc(x,meta_data);}
153  int Imax=0.;
154  for (int idx=1;idx<variable_num;idx++){
155  Imax = (df[idx]>df[Imax]) ? idx:Imax;
156  }
157  for (int idx = Imax;idx<variable_num-1;idx++){
158  memcpy(u.get_data()+idx*variable_num,u.get_data()+(idx+1)*variable_num,sizeof(double)*variable_num);
159  }
160  memcpy(u.get_data()+(variable_num-1)*variable_num,v.get_data(),sizeof(double)*variable_num);
161  }
162  return costfnc(x,meta_data);
163 }
168 
169 }
Matrix dot(Matrix &A, Matrix &B)
Call to calculate the product of two complex matrices by calling method zgemm3m from the CBLAS librar...
Definition: dot.cpp:38
void search(double a, double b, double &s, double &f_val, double tol, Matrix_real x)
double(* costfnc)(Matrix_real x, void *params)
function pointer to evaluate the cost function and its gradient vector
Matrix_real v
Matrix_real copy() const
Call to create a copy of the matrix.
int LAPACKE_dposv(int matrix_layout, char uplo, int n, int nrhs, double *A, int LDA, double *B, int LDB)
Powells_method(double(*f_pointer)(Matrix_real, void *), void *meta_data_in)
Constructor of the class.
void bracket(double x1, double h, double &a, double &b, Matrix_real x)
scalar * get_data() const
Call to get the pointer to the stored data.
Matrix_real u
double Start_Optimization(Matrix_real &x, long max_iter)
~Powells_method()
Destructor of the class.
int size() const
Call to get the number of the allocated elements.
A class representing a U3 gate.
Definition: R.h:36
double direction(double s, Matrix_real x)
void * meta_data
additional data needed to evaluate the cost function
int variable_num
number of independent variables in the problem
Class to store data of complex arrays and its properties.
Definition: matrix_real.h:39