38 name =
"Decomposition_Interface";
92 std::string projectname =
"";
96 std::random_device rd;
99 gen = std::mt19937(rd());
122 name =
"Decomposition_Interface";
177 std::string projectname =
"";
184 if (
config.count(
"use_float") > 0 ) {
193 std::random_device rd;
196 gen = std::mt19937(rd());
209 MPI_Comm_rank(MPI_COMM_WORLD, ¤t_rank);
221 name =
"Decomposition_Interface";
273 std::string projectname =
"";
280 std::random_device rd;
283 gen = std::mt19937(rd());
296 MPI_Comm_rank(MPI_COMM_WORLD, ¤t_rank);
368 if (
gates.size() == 0 ) {
373 const int min_vec_num = 20;
374 double minimum_vec[min_vec_num];
375 for (
int idx=0; idx<min_vec_num; idx++) {
376 minimum_vec[idx] = 0;
383 std::vector<Gate*> gates_loc =
gates;
405 std::uniform_real_distribution<> distrib_real(0.0, 2*
M_PI);
408 Matrix_real optimized_parameters(1, parameter_num_loc);
412 for(
int idx = 0; idx <
parameter_num-solution_guess_num; idx++) {
413 optimized_parameters[idx] = 0;
417 for(
int idx = 0; idx <
parameter_num-solution_guess_num; idx++) {
418 optimized_parameters[idx] = distrib_real(
gen);
428 for(
int idx = 0; idx <
parameter_num-solution_guess_num; idx++) {
429 optimized_parameters[idx] = distrib_real(
gen)/100;
438 std::string err(
"bad value for initial guess");
441 if ( solution_guess_num > 0) {
442 memcpy(optimized_parameters.
get_data() +
parameter_num-solution_guess_num, solution_guess, solution_guess_num*
sizeof(double));
447 int pre_gate_parameter_num = 0;
450 size_t block_idx_end;
451 size_t block_idx_start = 0;
453 int block_parameter_num;
455 std::vector<Matrix, tbb::cache_aligned_allocator<Matrix>> gates_mtxs_post;
465 long long max_outer_iterations_loc;
466 if (
config.count(
"max_outer_iterations") > 0 ) {
467 config[
"max_outer_iterations"].get_property( max_outer_iterations_loc );
476 tbb::tick_count
start_time = tbb::tick_count::now();
482 for ( iter_idx=0; iter_idx<max_outer_iterations_loc; iter_idx++) {
486 if (block_idx_end > gates_loc.size()) {
487 block_idx_end = gates_loc.size();
491 block_parameter_num = 0;
492 for (
size_t block_idx=block_idx_start; block_idx < block_idx_end; block_idx++) {
493 block_parameter_num = block_parameter_num + gates_loc[block_idx]->get_parameter_num();
497 if (block_idx_start > 0 ) {
500 std::vector<Gate*> gates_save =
gates;
502 gates.reserve( gates_save.size()-1 );
503 for( std::vector<Gate*>::iterator gate_it = gates_save.begin(); gate_it != gates_save.end()-1; gate_it++ ) {
504 gates.push_back( *gate_it );
539 for (
size_t idx=block_idx_start; idx<block_idx_end; idx++ ) {
540 gates.push_back( gates_loc[idx] );
544 if (block_idx_end < gates_loc.size()) {
547 for (
size_t gate_idx=0; gate_idx<block_idx_end; gate_idx++) {
548 Gate* gate = gates_loc[gate_idx];
554 std::vector<Gate*> gates_save =
gates;
556 gates.reserve( gates_loc.size()-block_idx_end );
557 for( std::vector<Gate*>::iterator gate_it = gates_loc.begin() + block_idx_end; gate_it != gates_loc.end(); gate_it++ ) {
558 gates.push_back( *gate_it );
564 for (
int pidx=0; pidx<optimized_parameters_partial.
size(); pidx++) {
565 optimized_parameters_partial_float[pidx] =
static_cast<float>(optimized_parameters_partial[pidx]);
576 apply_to( optimized_parameters_partial, post_mtx );
583 gates.push_back( fixed_gate_post );
606 double minvec_mean = 0;
607 for (
int idx=min_vec_num-1; idx>0; idx--) {
608 minimum_vec[idx] = minimum_vec[idx-1];
609 minvec_mean = minvec_mean + minimum_vec[idx-1];
613 minvec_mean = minvec_mean/min_vec_num;
621 if (block_idx_end == gates_loc.size()) {
624 pre_gate_parameter_num = 0;
629 pre_gate_parameter_num = pre_gate_parameter_num + block_parameter_num;
634 if (iter_idx % 500 == 0) {
635 tbb::tick_count current_time = tbb::tick_count::now();
636 std::stringstream sstream;
637 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;
639 start_time = tbb::tick_count::now();
644 double minvec_std = 0.0;
645 for (
int kdx=0; kdx<min_vec_num; kdx++ ) {
646 double tmp = minimum_vec[kdx] - minvec_mean;
647 minvec_std += tmp*tmp;
649 minvec_std = sqrt(minvec_std/(min_vec_num-1));
653 std::stringstream sstream;
654 sstream <<
"The iterations converged to minimum " << current_minimum <<
" after " << iter_idx <<
" outer iterations with " <<
layer_num <<
" layers" << std::endl;
659 std::stringstream sstream;
660 sstream <<
"The minimum with " <<
layer_num <<
" layers after " << iter_idx <<
" outer iterations is " << current_minimum << std::endl;
668 if (iter_idx == max_outer_iterations_loc && max_outer_iterations_loc>1) {
669 std::stringstream sstream;
670 sstream <<
"Reached maximal number of outer iterations" << std::endl << std::endl;
690 delete(fixed_gate_post);
734 double optimization_tolerance_loc;
735 if (
config.count(
"optimization_tolerance") > 0 ) {
736 config[
"optimization_tolerance"].get_property( optimization_tolerance_loc );
805 if ( num_of_parameters == 0 ) {
812 std::string err(
"Decomposition_Base::set_optimized_parameters: The number of parameters does not match with the free parameters of the circuit.");
854 return dot( gate_mtx, input_matrix );
866 std::map<int,int>::iterator key_it =
max_layer_num.find( n );
872 max_layer_num.insert( std::pair<int, int>(n, max_layer_num_in) );
887 for ( std::map<int,int>::iterator it = max_layer_num_in.begin(); it!=max_layer_num_in.end(); it++) {
908 std::vector<int> perm_indices;
916 for(
int qbit_idx=0; qbit_idx<
qbit_num; qbit_idx++ ) {
919 int qbit_state = ( idx >> qbit_list[qbit_idx] ) & 1;
921 row_idx = row_idx + qbit_state*
Power_of_2(qbit_idx);
924 perm_indices.push_back(row_idx);
929 Matrix reordered_mtx =
Matrix(matrix_size, matrix_size);
930 for (
int row_idx = 0; row_idx<
matrix_size; row_idx++) {
931 for (
int col_idx = 0; col_idx<
matrix_size; col_idx++) {
932 int index_reordered = perm_indices[row_idx]*
Umtx.
rows + perm_indices[col_idx];
933 int index_umtx = row_idx*
Umtx.
rows + col_idx;
934 reordered_mtx[index_reordered] =
Umtx[index_umtx];
938 Umtx = reordered_mtx;
972 for ( std::map<int,int>::iterator it=iteration_loops_in.begin(); it!= iteration_loops_in.end(); it++ ) {
1099 mult(global_phase_factor, u3_gate);
1122 const char* c_filename = filename.c_str();
1123 pFile = fopen(c_filename,
"wb");
1125 fputs (
"File error",stderr);
1126 std::string error(
"Cannot open file.");
1131 fwrite(&
Umtx.
rows,
sizeof(
int), 1, pFile);
1132 fwrite(&
Umtx.
cols,
sizeof(
int), 1, pFile);
1149 const char* c_filename = filename.c_str();
1152 pFile = fopen(c_filename,
"rb");
1154 fputs (
"File error",stderr);
1177 if (
config.count(
"parallel") > 0 ) {
1179 config[
"parallel"].get_property( value );
1180 parallel = (
int) value;
1199 int matrix_size_loc = 1 << qbit_num_in;
1201 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.
virtual void reorder_qubits(std::vector< int > qbit_list) override
Call to reorder the qubits in the matrix of the gates (Obsolete function)
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.
Class to store single-precision real arrays and properties.
Matrix_float to_float32() const
Convert to single precision.
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.
bool optimization_problem_solved
logical value describing whether the optimization problem was solved or not
Matrix to_float64() const
Convert to double precision.
int finalizing_gates_num
number of finalizing (deterministic) opertaions rotating the disentangled qubits into state |0>...
bool use_float
Selects float32 circuit application for parameter/unitary/state data.
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.
Matrix_real_float optimized_parameters_mtx_float
Float32 optimized parameters used by the hot gate-application path.
double get_current_minimum()
Call to get the obtained minimum of the cost function.
Matrix_real_float get_optimized_parameters_float()
Return optimized parameters in float32.
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 set_qbit_num(int qbit_num_in) override
Set the number of qubits spanning the matrix of the gates stored in the block of gates.
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 sync_optimized_parameters_float()
Synchronize the float32 parameter mirror from the double optimizer storage.
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.
Matrix_real_float copy() const
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_float Umtx_float
Float32 copy of the unitary used when config["use_float"] is true.
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.
virtual void apply_to(Matrix_real ¶meters_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...
Structure type representing complex numbers in the SQUANDER package.
Matrix copy() const
Call to create a copy of the matrix.
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.
Double-precision complex matrix (float64).
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.
virtual 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.
Single-precision complex matrix (float32).
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
volatile double current_minimum
The current minimum of the optimization problem.
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.
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...
Matrix_float get_Umtx_float()
Return the float32 unitary copy used by float execution.
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 fread_wrapper(void *buffer, size_t size, size_t count, FILE *stream)
Wrapper function aound fread with error handling.
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.
Matrix_float copy() const
Call to create a copy of the matrix.
bool get_use_float() const
True when config["use_float"] requests float32 circuit execution.
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
Matrix_float create_identity_float(int matrix_size)
Call to create a single-precision complex identity matrix.
virtual double optimization_problem(const double *parameters)
This is an abstact definition of function giving the cost functions measuring the entaglement of the ...