82 std::stringstream sstream;
83 sstream <<
"***************************************************************" << std::endl;
84 sstream <<
"Starting to disentangle " <<
qbit_num <<
"-qubit matrix" << std::endl;
85 sstream <<
"***************************************************************" << std::endl << std::endl << std::endl;
92 #if BLAS==0 // undefined BLAS 97 MKL_Set_Num_Threads(1);
98 #elif BLAS==2 //OpenBLAS 100 openblas_set_num_threads(1);
104 tbb::tick_count
start_time = tbb::tick_count::now();
148 delete cSub_decomposition;
149 cSub_decomposition = NULL;
156 if (finalize_decomp) {
186 for(
auto it=gate_nums.begin(); it != gate_nums.end(); it++ ) {
187 sstream << it->second <<
" " << it->first <<
" gates" << std::endl;
191 sstream << std::endl;
192 tbb::tick_count current_time = tbb::tick_count::now();
194 sstream <<
"--- In total " << (current_time -
start_time).seconds() <<
" seconds elapsed during the decomposition ---" << std::endl;
202 #if BLAS==0 // undefined BLAS 206 #elif BLAS==2 //OpenBLAS 223 std::stringstream sstream;
224 sstream <<
"Decomposition was already finalized" << std::endl;
240 int submatrices_num_row = 2;
247 Matrix most_unitary_submatrix_mtx =
Matrix(submatrix_size, submatrix_size );
249 double unitary_error_min = 1e8;
251 for (
int idx=0; idx<submatrices_num_row; idx++) {
252 for (
int jdx=0; jdx<submatrices_num_row; jdx++) {
254 Matrix submatrix_mtx =
Matrix(submatrix_size, submatrix_size);
257 for (
int row_idx=0; row_idx<submatrix_size; row_idx++ ) {
259 int submatrix_offset = row_idx*submatrix_size;
260 memcpy(submatrix+submatrix_offset, subdecomposed_matrix+matrix_offset, submatrix_size*
sizeof(
QGD_Complex16));
264 Matrix submatrix_mtx_adj = submatrix_mtx;
267 Matrix submatrix_prod =
dot( submatrix_mtx, submatrix_mtx_adj);
271 for (
int row_idx=0; row_idx<submatrix_size; row_idx++) {
272 submatrix_prod[row_idx*submatrix_size+row_idx].real = submatrix_prod[row_idx*submatrix_size+row_idx].real - corner_element.
real;
273 submatrix_prod[row_idx*submatrix_size+row_idx].imag = submatrix_prod[row_idx*submatrix_size+row_idx].imag - corner_element.
imag;
276 double unitary_error =
cblas_dznrm2( submatrix_size*submatrix_size, submatrix_prod.
get_data(), 1 );
278 if (unitary_error < unitary_error_min) {
279 unitary_error_min = unitary_error;
280 memcpy(most_unitary_submatrix, submatrix, submatrix_size*submatrix_size*
sizeof(
QGD_Complex16));
325 delete cdecomposition;
359 memset( solution_guess_tmp.
get_data(), 0, solution_guess_tmp.
size()*
sizeof(double) );
373 Matrix_real parameters_joined( 1, optimized_parameters_mtx_save.
size()+optimized_parameters_mtx_save2.
size() );
374 memcpy( parameters_joined.get_data(), optimized_parameters_mtx_save.
get_data(), optimized_parameters_mtx_save.
size()*
sizeof(double) );
376 memcpy( parameters_joined.get_data()+optimized_parameters_mtx_save.
size(),
377 optimized_parameters_mtx_save2.
get_data(),
378 optimized_parameters_mtx_save2.
size()*
sizeof(double) );
394 std::stringstream sstream;
399 for(
auto it=gate_nums.begin(); it != gate_nums.end(); it++ ) {
400 sstream << it->second <<
" " << it->first <<
" gates" << std::endl;
405 sstream <<
"The error of the decomposition after finalyzing gates is " <<
decomposition_error <<
" with " <<
layer_num <<
" layers" << std::endl;
438 std::vector<Gate*> sub_decomp_ops = cSub_decomposition->
get_gates();
441 for (
int idx = 0; idx<gate_num; idx++) {
442 Gate* op = sub_decomp_ops[idx];
460 for ( std::map<int,Gates_block*>::iterator it=gate_structure_in.begin(); it!= gate_structure_in.end(); it++ ) {
463 std::map<int,Gates_block*>::iterator key_it =
gate_structure.find( key );
469 gate_structure.insert( std::pair<int,Gates_block*>(key, it->second->clone()));
507 for ( std::map<int,int>::iterator it=identical_blocks_in.begin(); it!= identical_blocks_in.end(); it++ ) {
Matrix dot(Matrix &A, Matrix &B)
Call to calculate the product of two complex matrices by calling method zgemm3m from the CBLAS librar...
N_Qubit_Decomposition()
Nullary constructor of the class.
void set_custom_gate_layers(Gates_block *block_in)
Call to set custom layers to the gate structure that are intended to be used in the subdecomposition...
void print(const std::stringstream &sstream, int verbose_level=1) const
Call to print output messages in the function of the verbosity level.
void set_optimizer(optimization_aglorithms alg_in)
Call to set the optimizer engine to be used in solving the optimization problem.
bool decomposition_finalized
The optimized parameters for the gates.
std::map< std::string, int > get_gate_nums()
Call to get the number of the individual gate types in the list of gates.
void disentangle_submatrices()
Start the optimization process to disentangle the most significant qubit from the others...
std::map< int, int > identical_blocks
A map of <int n: int num> indicating that how many identical successive blocks should be used in the ...
virtual Gate * clone()
Call to create a clone of the present class.
void add_gate(Gate *gate)
Append a general gate to the list of gates.
void decompose_submatrix()
Start the decompostion process to recursively decompose the submatrices.
int target_qbit
The index of the qubit on which the operation acts (target_qbit >= 0)
int set_max_layer_num(int n, int max_layer_num_in)
Set the maximal number of layers used in the subdecomposition of the n-th qubit.
std::vector< Gate * > get_gates()
Call to get the gates stored in the class.
void release_gates()
Call to release the stored gates.
int layer_num
number of gate layers
std::map< int, int > max_layer_num
A map of <int n: int num> indicating that how many layers should be used in the subdecomposition proc...
virtual void apply_to(Matrix_real ¶meters_mtx, Matrix &input, int parallel=0)
Call to apply the gate on the input array/matrix Gates_block*input.
int matrix_size
The size N of the NxN matrix associated with the operations.
scalar * get_data() const
Call to get the pointer to the stored data.
guess_type initial_guess
type to guess the initial values for the optimization. Possible values: ZEROS=0, RANDOM=1, CLOSE_TO_ZERO=2
virtual void start_decomposition(bool finalize_decomp=true)
Start the disentanglig process of the unitary.
int get_gate_num()
Call to get the number of gates grouped in the class.
int set_identical_blocks(int qbit, int identical_blocks_in)
Set the number of identical successive blocks during the subdecomposition of the qbit-th qubit...
void finalize_decomposition()
After the main optimization problem is solved, the indepent qubits can be rotated into state |0> by t...
int max_outer_iterations
Maximal number of iterations allowed in the optimization process.
double optimization_tolerance
The maximal allowed error of the optimization problem (The error of the decomposition would scale wit...
int get_parameter_num()
Call to get the number of free parameters.
void set_custom_gate_structure(std::map< int, Gates_block *> gate_structure_in)
Call to set custom layers to the gate structure that are intended to be used in the subdecomposition...
void set_debugfile(std::string debugfile)
Call to set the debugfile name.
virtual ~N_Qubit_Decomposition()
Destructor of the class.
Matrix_real get_optimized_parameters()
Call to get the optimized parameters.
void add_u3(int target_qbit)
Append a U3 gate to the list of gates.
double cblas_dznrm2(OPENBLAS_CONST blasint N, OPENBLAS_CONST void *X, OPENBLAS_CONST blasint incX)
A base class to determine the decomposition of an N-qubit unitary into a sequence of CNOT and U3 gate...
bool subdisentaglement_done
logical value indicating whether the disentamglement of a qubit from the othetrs was done or not ...
void combine(Gates_block *op_block)
Call to append the gates of an gate block to the current block.
std::map< int, int > iteration_loops
A map of <int n: int num> indicating the number of iteration in each step of the decomposition.
int num_threads
Store the number of OpenMP threads. (During the calculations OpenMP multithreading is turned off...
Structure type representing complex numbers in the SQUANDER package.
int verbose
Set the verbosity level of the output messages.
void set_optimization_tolerance(double tolerance_in)
Call to set the tolerance of the optimization processes.
virtual Gates_block * clone()
Create a clone of the present class.
Class to store data of complex arrays and its properties.
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 subtract_diag(Matrix &mtx, QGD_Complex16 scalar)
Call to subtract a scalar from the diagonal of a complex matrix.
std::string debugfile_name
String variable. Set the debug file name.
A class responsible for grouping two-qubit (CNOT,CZ,CH) and one-qubit gates into layers.
void omp_set_num_threads(int num_threads)
Set the number of threads on runtime in MKL.
void transpose()
Call to transpose (or un-transpose) the matrix for CBLAS functions.
void extract_subdecomposition_results(Sub_Matrix_Decomposition *cSub_decomposition)
Call to extract and store the calculated parameters and gates of the sub-decomposition processes...
guess_type
Type definition of the types of the initial guess.
void set_verbose(int verbose_in)
Call to set the verbose attribute.
std::map< std::string, Config_Element > config
config metadata utilized during the optimization
Base class for the representation of general gate operations.
std::map< int, Gates_block * > gate_structure
A map of <int n: Gates_block* block> describing custom gate structure to be used in the decomposition...
int parameter_num
the number of free parameters of the operation
void solve_layer_optimization_problem(int num_of_parameters, Matrix_real solution_guess)
Call to solve layer by layer the optimization problem via calling one of the implemented algorithms...
Header file for the paralleized calculation of the cost function of the final optimization problem (s...
Matrix Umtx
The unitary to be decomposed.
Matrix copy()
Call to create a copy of the matrix.
double real
the real part of a complex number
void final_optimization()
final optimization procedure improving the accuracy of the decompositin when all the qubits were alre...
void conjugate()
Call to conjugate (or un-conjugate) the matrix for CBLAS functions.
int qbit_num
number of qubits spanning the matrix of the operation
bool optimize_layer_num
logical value. Set true to optimize the minimum number of gate layers required in the decomposition...
int finalizing_parameter_num
the number of the finalizing (deterministic) parameters of gates rotating the disentangled qubits int...
void set_max_iteration(int max_outer_iterations_in)
Call to set the maximal number of the iterations in the optimization process.
A class responsible for the disentanglement of one qubit from the others.
int optimization_block
number of gate blocks used in one shot of the optimization process
double decomposition_error
error of the final decomposition
int set_iteration_loops(int n, int iteration_loops_in)
Set the number of iteration loops during the subdecomposition of the n-th qubit.
Header file for a class to determine the decomposition of an N-qubit unitary into a sequence of CNOT ...
Matrix_real optimized_parameters_mtx
The optimized parameters for the gates.
int set_identical_blocks(int n, int identical_blocks_in)
Set the number of identical successive blocks during the subdecomposition of the n-th qubit...
void set_optimization_blocks(int optimization_block_in)
Call to set the number of gate blocks to be optimized in one shot.
Class to store data of complex arrays and its properties.
A base class to determine the decomposition of an N-qubit unitary into a sequence of CNOT and U3 gate...
double imag
the imaginary part of a complex number
int omp_get_max_threads()
get the number of threads in MKL