Sequential Quantum Gate Decomposer  v1.9.6
Powerful decomposition of general unitarias into one- and two-qubit gates gates
N_Qubit_Decomposition_custom.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 */
26 
27 
28 
34 
35  // BFGS is better for smaller problems, while ADAM for larger ones
36  if ( qbit_num <= 5 ) {
38 
39  // Maximal number of iteartions in the optimization process
41  }
42  else {
44 
45  // Maximal number of iteartions in the optimization process
47  }
48 
49 }
50 
59 N_Qubit_Decomposition_custom::N_Qubit_Decomposition_custom( Matrix Umtx_in, int qbit_num_in, bool optimize_layer_num_in, std::map<std::string, Config_Element>& config, guess_type initial_guess_in= CLOSE_TO_ZERO, int accelerator_num ) : Optimization_Interface(Umtx_in, qbit_num_in, optimize_layer_num_in, config, initial_guess_in, accelerator_num) {
60 
61 
62  // BFGS is better for smaller problems, while ADAM for larger ones
63  if ( qbit_num <= 5 ) {
65 
66  // Maximal number of iteartions in the optimization process
68  }
69  else {
71 
72  // Maximal number of iteartions in the optimization process
74  }
75 
76 }
77 
81 N_Qubit_Decomposition_custom::N_Qubit_Decomposition_custom( Matrix_float Umtx_in, int qbit_num_in, bool optimize_layer_num_in, std::map<std::string, Config_Element>& config, guess_type initial_guess_in, int accelerator_num ) : Optimization_Interface(Umtx_in, qbit_num_in, optimize_layer_num_in, config, initial_guess_in, accelerator_num) {
82 
83 
84  // BFGS is better for smaller problems, while ADAM for larger ones
85  if ( qbit_num <= 5 ) {
87 
88  // Maximal number of iteartions in the optimization process
90  }
91  else {
93 
94  // Maximal number of iteartions in the optimization process
96  }
97 
98 }
99 
100 
101 
106 
107 }
108 
109 
110 
115 void
117 
118 
119  //The stringstream input to store the output messages.
120  std::stringstream sstream;
121  sstream << "***************************************************************" << std::endl;
122  sstream << "Starting to disentangle " << qbit_num << "-qubit matrix via custom gate structure" << std::endl;
123  sstream << "***************************************************************" << std::endl << std::endl << std::endl;
124  print(sstream, 1);
125 
126 
127 
128  // temporarily turn off OpenMP parallelism
129 #if BLAS==0 // undefined BLAS
132 #elif BLAS==1 // MKL
133  num_threads = mkl_get_max_threads();
134  MKL_Set_Num_Threads(1);
135 #elif BLAS==2 //OpenBLAS
136  num_threads = openblas_get_num_threads();
137  openblas_set_num_threads(1);
138 #endif
139 
140  //measure the time for the decompositin
141  tbb::tick_count start_time = tbb::tick_count::now();
142 
143 
144 
145 
146  if (optimized_parameters_mtx.size() > 0 ) {
147  sstream.str("");
148  sstream << "cost function of the imported circuit: " << optimization_problem( optimized_parameters_mtx ) << std::endl;
149  print(sstream, 1);
150  }
151 
152 
153  // final tuning of the decomposition parameters
155 
156  // calculating the final error of the decomposition
157  Matrix matrix_decomposed = Umtx.copy();
158  apply_to(optimized_parameters_mtx, matrix_decomposed );
159  calc_decomposition_error( matrix_decomposed );
160 
161 
162  sstream.str("");
163  sstream << "In the decomposition with error = " << decomposition_error << " were used " << layer_num << " layers with:" << std::endl;
164 
165 
166  // get the number of gates used in the decomposition
167  std::map<std::string, int>&& gate_nums = get_gate_nums();
168 
169  for( auto it=gate_nums.begin(); it != gate_nums.end(); it++ ) {
170  sstream << it->second << " " << it->first << " gates" << std::endl;
171  }
172 
173 
174  sstream << std::endl;
175  tbb::tick_count current_time = tbb::tick_count::now();
176 
177  sstream << "--- In total " << (current_time - start_time).seconds() << " seconds elapsed during the decomposition ---" << std::endl;
178  print(sstream, 1);
179 
180 
181 
182 #if BLAS==0 // undefined BLAS
184 #elif BLAS==1 //MKL
185  MKL_Set_Num_Threads(num_threads);
186 #elif BLAS==2 //OpenBLAS
187  openblas_set_num_threads(num_threads);
188 #endif
189 
190 }
191 
192 
193 
194 
195 
196 
197 
198 
199 
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
virtual ~N_Qubit_Decomposition_custom()
Destructor of the class.
void set_optimizer(optimization_aglorithms alg_in)
Call to set the optimizer engine to be used in solving the optimization problem.
std::map< std::string, int > get_gate_nums()
Call to get the number of the individual gate types in the list of gates.
N_Qubit_Decomposition_custom()
Nullary constructor of the class.
double optimization_problem(double *parameters)
Evaluate the optimization problem of the optimization.
int layer_num
number of gate layers
Definition: Gates_block.h:51
int max_outer_iterations
Maximal number of iterations allowed in the optimization process.
int accelerator_num
number of utilized accelerators
A base class to determine the decomposition of an N-qubit unitary into a sequence of CNOT and U3 gate...
virtual void apply_to(Matrix_real &parameters_mtx, Matrix &input, int parallel=0) override
Call to apply the gate on the input array/matrix Gates_block*input.
int num_threads
Store the number of OpenMP threads. (During the calculations OpenMP multithreading is turned off...
Matrix copy() const
Call to create a copy of the matrix.
Definition: matrix.h:57
Double-precision complex matrix (float64).
Definition: matrix.h:38
void calc_decomposition_error(Matrix &decomposed_matrix)
Calculate the error of the decomposition according to the spectral norm of , where is the unitary pr...
int size() const
Call to get the number of the allocated elements.
void omp_set_num_threads(int num_threads)
Set the number of threads on runtime in MKL.
Single-precision complex matrix (float32).
Definition: matrix_float.h:41
guess_type
Type definition of the types of the initial guess.
std::map< std::string, Config_Element > config
config metadata utilized during the optimization
virtual void start_decomposition()
Start the disentanglig process of the unitary.
Header file for the paralleized calculation of the cost function of the final optimization problem (s...
Matrix Umtx
The unitary to be decomposed.
void final_optimization()
final optimization procedure improving the accuracy of the decompositin when all the qubits were alre...
int qbit_num
number of qubits spanning the matrix of the operation
Definition: Gate.h:94
double decomposition_error
error of the final decomposition
Matrix_real optimized_parameters_mtx
The optimized parameters for the gates.
int omp_get_max_threads()
get the number of threads in MKL