38 name =
"Decomposition_Interface";
90 std::string projectname =
"";
94 std::random_device rd;
97 gen = std::mt19937(rd());
120 name =
"Decomposition_Interface";
175 std::string projectname =
"";
183 std::random_device rd;
186 gen = std::mt19937(rd());
199 MPI_Comm_rank(MPI_COMM_WORLD, ¤t_rank);
259 if (
gates.size() == 0 ) {
264 const int min_vec_num = 20;
265 double minimum_vec[min_vec_num];
266 for (
int idx=0; idx<min_vec_num; idx++) {
267 minimum_vec[idx] = 0;
274 std::vector<Gate*> gates_loc =
gates;
292 std::uniform_real_distribution<> distrib_real(0.0, 2*M_PI);
295 Matrix_real optimized_parameters(1, parameter_num_loc);
299 for(
int idx = 0; idx <
parameter_num-solution_guess_num; idx++) {
300 optimized_parameters[idx] = 0;
304 for(
int idx = 0; idx <
parameter_num-solution_guess_num; idx++) {
305 optimized_parameters[idx] = distrib_real(
gen);
315 for(
int idx = 0; idx <
parameter_num-solution_guess_num; idx++) {
316 optimized_parameters[idx] = distrib_real(
gen)/100;
325 std::string err(
"bad value for initial guess");
328 if ( solution_guess_num > 0) {
329 memcpy(optimized_parameters.
get_data() +
parameter_num-solution_guess_num, solution_guess, solution_guess_num*
sizeof(double));
334 int pre_gate_parameter_num = 0;
338 int block_idx_start = 0;
340 int block_parameter_num;
342 std::vector<Matrix, tbb::cache_aligned_allocator<Matrix>> gates_mtxs_post;
352 long long max_outer_iterations_loc;
353 if (
config.count(
"max_outer_iterations") > 0 ) {
354 config[
"max_outer_iterations"].get_property( max_outer_iterations_loc );
363 tbb::tick_count
start_time = tbb::tick_count::now();
369 for ( iter_idx=0; iter_idx<max_outer_iterations_loc; iter_idx++) {
373 if (block_idx_end > gates_loc.size()) {
374 block_idx_end = gates_loc.size();
378 block_parameter_num = 0;
379 for (
int block_idx=block_idx_start; block_idx < block_idx_end; block_idx++) {
380 block_parameter_num = block_parameter_num + gates_loc[block_idx]->get_parameter_num();
384 if (block_idx_start > 0 ) {
387 std::vector<Gate*> gates_save =
gates;
389 gates.reserve( gates_save.size()-1 );
390 for( std::vector<Gate*>::iterator gate_it = gates_save.begin(); gate_it != gates_save.end()-1; gate_it++ ) {
391 gates.push_back( *gate_it );
414 for (
int idx=block_idx_start; idx<block_idx_end; idx++ ) {
415 gates.push_back( gates_loc[idx] );
419 if (block_idx_end < gates_loc.size()) {
422 for (
int gate_idx=0; gate_idx<block_idx_end; gate_idx++) {
423 Gate* gate = gates_loc[gate_idx];
429 std::vector<Gate*> gates_save =
gates;
431 gates.reserve( gates_loc.size()-block_idx_end );
432 for( std::vector<Gate*>::iterator gate_it = gates_loc.begin() + block_idx_end; gate_it != gates_loc.end(); gate_it++ ) {
433 gates.push_back( *gate_it );
438 apply_to( optimized_parameters_partial, post_mtx );
444 gates.push_back( fixed_gate_post );
465 double minvec_mean = 0;
466 for (
int idx=min_vec_num-1; idx>0; idx--) {
467 minimum_vec[idx] = minimum_vec[idx-1];
468 minvec_mean = minvec_mean + minimum_vec[idx-1];
472 minvec_mean = minvec_mean/min_vec_num;
480 if (block_idx_end == gates_loc.size()) {
483 pre_gate_parameter_num = 0;
488 pre_gate_parameter_num = pre_gate_parameter_num + block_parameter_num;
493 if (iter_idx % 500 == 0) {
494 tbb::tick_count current_time = tbb::tick_count::now();
495 std::stringstream sstream;
496 sstream <<
"The minimum with " <<
layer_num <<
" layers after " << iter_idx <<
" outer iterations is " << current_minimum <<
" calculated in " << (current_time -
start_time).seconds() <<
" seconds" << std::endl;
498 start_time = tbb::tick_count::now();
503 double minvec_std = 0.0;
504 for (
int kdx=0; kdx<min_vec_num; kdx++ ) {
505 double tmp = minimum_vec[kdx] - minvec_mean;
506 minvec_std += tmp*tmp;
508 minvec_std = sqrt(minvec_std/(min_vec_num-1));
512 std::stringstream sstream;
513 sstream <<
"The iterations converged to minimum " << current_minimum <<
" after " << iter_idx <<
" outer iterations with " <<
layer_num <<
" layers" << std::endl;
518 std::stringstream sstream;
519 sstream <<
"The minimum with " <<
layer_num <<
" layers after " << iter_idx <<
" outer iterations is " << current_minimum << std::endl;
527 if (iter_idx == max_outer_iterations_loc && max_outer_iterations_loc>1) {
528 std::stringstream sstream;
529 sstream <<
"Reached maximal number of outer iterations" << std::endl << std::endl;
548 delete(fixed_gate_post);
589 double optimization_tolerance_loc;
590 if (
config.count(
"optimization_tolerance") > 0 ) {
591 config[
"optimization_tolerance"].get_property( optimization_tolerance_loc );
645 if ( num_of_parameters == 0 ) {
651 std::string err(
"Decomposition_Base::set_optimized_parameters: The number of parameters does not match with the free parameters of the circuit.");
686 return dot( gate_mtx, input_matrix );
698 std::map<int,int>::iterator key_it =
max_layer_num.find( n );
704 max_layer_num.insert( std::pair<int, int>(n, max_layer_num_in) );
719 for ( std::map<int,int>::iterator it = max_layer_num_in.begin(); it!=max_layer_num_in.end(); it++) {
739 std::vector<int> perm_indices;
746 std::vector<int> bin_rep;
748 for (
int i = 1 << (
qbit_num-1); i > 0; i = i / 2) {
749 (idx & i) ? bin_rep.push_back(1) : bin_rep.push_back(0);
753 for (
int jdx=0; jdx<
qbit_num; jdx++) {
754 row_idx = row_idx + bin_rep[qbit_num-1-qbit_list[jdx]]*
Power_of_2(qbit_num-1-jdx);
756 perm_indices.push_back(row_idx);
771 Matrix reordered_mtx =
Matrix(matrix_size, matrix_size);
772 for (
int row_idx = 0; row_idx<
matrix_size; row_idx++) {
773 for (
int col_idx = 0; col_idx<
matrix_size; col_idx++) {
774 int index_reordered = perm_indices[row_idx]*
Umtx.
rows + perm_indices[col_idx];
775 int index_umtx = row_idx*
Umtx.
rows + col_idx;
776 reordered_mtx[index_reordered] =
Umtx[index_umtx];
780 Umtx = reordered_mtx;
813 for ( std::map<int,int>::iterator it=iteration_loops_in.begin(); it!= iteration_loops_in.end(); it++ ) {
940 mult(global_phase_factor, u3_gate);
963 const char* c_filename = filename.c_str();
964 pFile = fopen(c_filename,
"wb");
966 fputs (
"File error",stderr);
967 std::string error(
"Cannot open file.");
972 fwrite(&
Umtx.
rows,
sizeof(
int), 1, pFile);
973 fwrite(&
Umtx.
cols,
sizeof(
int), 1, pFile);
990 const char* c_filename = filename.c_str();
993 pFile = fopen(c_filename,
"rb");
995 fputs (
"File error",stderr);
1000 fread_status = fread(&rows,
sizeof(
int), 1, pFile);
1001 fread_status = fread(&cols,
sizeof(
int), 1, pFile);
1020 if (
config.count(
"parallel") > 0 ) {
1022 config[
"parallel"].get_property( value );
1023 parallel = (
int) value;
1042 int matrix_size_loc = 1 << qbit_num_in;
1044 std::string err(
"Decomposition_Base::set_qbit_num: The new number of qubits is not in line with the input unitary to be decomposed");
void list_gates(int start_index)
Call to print the gates decomposing the initial unitary.
Matrix dot(Matrix &A, Matrix &B)
Call to calculate the product of two complex matrices by calling method zgemm3m from the CBLAS librar...
Gate()
Default constructor of the class.
std::string get_project_name()
Call to get the current name of the project.
void print(const std::stringstream &sstream, int verbose_level=1) const
Call to print output messages in the function of the verbosity level.
Matrix get_decomposed_matrix()
Calculate the decomposed matrix resulted by the effect of the optimized gates on the unitary Umtx...
void set_project_name(std::string &project_name_new)
Call to set the name of the project.
bool decomposition_finalized
The optimized parameters for the gates.
Matrix get_Umtx()
Call to retrive a pointer to the unitary to be transformed.
Matrix_real copy() const
Call to create a copy of the matrix.
double current_minimum
The current minimum of the optimization problem.
bool optimization_problem_solved
logical value describing whether the optimization problem was solved or not
int finalizing_gates_num
number of finalizing (deterministic) opertaions rotating the disentangled qubits into state |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.
double get_current_minimum()
Call to get the obtained minimum of the cost function.
virtual void reorder_qubits(std::vector< int > qbit_list)
Call to reorder the qubits in the matrix of the gates (Obsolete function)
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...
QGD_Complex16 mult(QGD_Complex16 &a, QGD_Complex16 &b)
Call to calculate the product of two complex scalars.
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.
Matrix apply_gate(Matrix &gate_mtx, Matrix &input_matrix)
Apply an gates on the input matrix.
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
static void Init_max_layer_num()
Initializes default layer numbers.
void apply_global_phase_factor()
Call to apply the current global phase to the unitary matrix.
std::vector< Gate * > gates
The list of stored gates.
void set_qbit_num(int qbit_num_in)
Set the number of qubits spanning the matrix of the gates stored in the block of gates.
int max_outer_iterations
Maximal number of iterations allowed in the optimization process.
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...
gate_type type
The type of the operation (see enumeration gate_type)
void set_global_phase(double new_global_phase)
Call to set global phase.
QGD_Complex16 get_global_phase_factor()
Get the global phase of the Unitary matrix.
int rows
The number of rows.
int cols
The number of columns.
double get_decomposition_error()
Call to get the error of the decomposition.
int get_Umtx_size()
Call to get the size of the unitary to be transformed.
double convergence_threshold
The convergence threshold in the optimization process.
Matrix_real get_optimized_parameters()
Call to get the optimized parameters.
std::map< int, int > iteration_loops
A map of <int n: int num> indicating the number of iteration in each step of the decomposition.
void set_optimized_parameters(double *parameters, int num_of_parameters)
Call to set the optimized parameters for initial optimization.
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.
void set_optimization_tolerance(double tolerance_in)
Call to set the tolerance of the optimization processes.
void set_matrix(Matrix input)
Call to set the stored matrix in the operation.
int Power_of_2(int n)
Calculates the n-th power of 2.
Class to store data of complex arrays and its properties.
Header file for a class containing basic methods for the decomposition process.
virtual ~Decomposition_Base()
Destructor of the class.
QGD_Complex16 global_phase_factor
The global phase.
int size() const
Call to get the number of the allocated elements.
int get_parameter_num()
Call to get the number of free parameters.
void set_convergence_threshold(double convergence_threshold_in)
Call to set the threshold of convergence in the optimization processes.
A class responsible for grouping two-qubit (CNOT,CZ,CH) and one-qubit gates into layers.
void calculate_new_global_phase_factor(QGD_Complex16 global_phase_factor_new)
Calculate the new global phase of the Unitary matrix after removing a trivial U3 matrix.
void reorder_qubits(std::vector< int > qbit_list)
Call to reorder the qubits in the matrix of the gate.
std::string name
A string labeling the gate operation.
guess_type
Type definition of the types of the initial guess.
std::map< std::string, Config_Element > config
config metadata utilized during the optimization
Base class for the representation of general gate operations.
Matrix create_identity(int matrix_size)
Call to create an identity matrix.
virtual void solve_layer_optimization_problem(int num_of_parameters, Matrix_real solution_guess_gsl)
Abstarct function to be used to solve a single sub-layer optimization problem.
int parameter_num
the number of free parameters of the operation
void solve_optimization_problem(double *solution_guess, int solution_guess_num)
This method can be used to solve the main optimization problem which is devidid into sub-layer optimi...
Matrix Umtx
The unitary to be decomposed.
Matrix copy()
Call to create a copy of the matrix.
static std::map< int, int > max_layer_num_def
A map of <int n: int num> indicating that how many layers should be used in the subdecomposition proc...
double real
the real part of a complex number
void reset_parameter_start_indices()
Method to reset the parameter start indices of gate operations incorporated in the circuit...
void export_unitary(std::string &filename)
exports unitary matrix to binary file
int qbit_num
number of qubits spanning the matrix of the operation
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.
bool check_optimization_solution()
check_optimization_solution
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.
void list_gates(const Matrix_real ¶meters, int start_index)
Call to print the list of gates stored in the block of gates for a specific set of parameters...
Matrix import_unitary_from_binary(std::string &filename)
Import a Unitary matrix from a file.
Matrix_real optimized_parameters_mtx
The optimized parameters for the gates.
int get_parallel_configuration()
Get the parallel configuration from the config.
double global_target_minimum
The global target minimum of the optimization problem.
Header file for the paralleized calculation of the cost function of the subdecomposition (supporting ...
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.
Decomposition_Base()
Nullary constructor of the class.
std::mt19937 gen
Standard mersenne_twister_engine seeded with rd()
double imag
the imaginary part of a complex number
virtual void set_qbit_num(int qbit_num_in)
Set the number of qubits spanning the matrix of the gates stored in the block of gates.
virtual double optimization_problem(const double *parameters)
This is an abstact definition of function giving the cost functions measuring the entaglement of the ...