28 #include <tbb/enumerable_thread_specific.h> 91 max_layer_num.insert( std::pair<int, int>(it->first, it->second) );
127 std::stringstream sstream;
128 sstream <<
"Sub-disentaglement already done." << std::endl;
133 std::stringstream sstream;
134 sstream << std::endl <<
"Disentagling submatrices." << std::endl;
144 std::stringstream sstream;
145 sstream <<
"Disentanglig not needed" << std::endl;
157 tbb::tick_count
start_time = tbb::tick_count::now();
160 int max_layer_num_loc;
165 std::stringstream sstream;
166 sstream <<
"Layer number not given" << std::endl;
171 while (
layer_num < max_layer_num_loc ) {
193 tbb::tick_count current_time = tbb::tick_count::now();
195 std::stringstream sstream;
196 sstream <<
"--- " << (current_time -
start_time).seconds() <<
" seconds elapsed during the decomposition ---" << std::endl << std::endl;
204 std::stringstream sstream;
205 sstream <<
"Sub-disentaglement was succesfull." << std::endl << std::endl;
209 std::stringstream sstream;
210 sstream <<
"Sub-disentaglement did not reach the tolerance limit." << std::endl << std::endl;
239 int identical_blocks_loc;
242 if (identical_blocks_loc==0) {
243 identical_blocks_loc = 1;
247 identical_blocks_loc=1;
253 for (std::vector<Gate*>::iterator gates_it = gates.begin(); gates_it != gates.end(); gates_it++ ) {
256 Gate* gate = *gates_it;
258 for (
int idx=0; idx<identical_blocks_loc; idx++) {
277 int identical_blocks_loc;
280 if (identical_blocks_loc==0) {
281 identical_blocks_loc = 1;
285 identical_blocks_loc=1;
289 for (
int target_qbit_loc = 0; target_qbit_loc<control_qbit_loc; target_qbit_loc++ ) {
291 for (
int idx=0; idx<identical_blocks_loc; idx++) {
297 block->
add_u3(target_qbit_loc);
298 block->
add_u3(control_qbit_loc);
302 block->
add_cnot(target_qbit_loc, control_qbit_loc);
337 if (
gates.size() == 0 ) {
342 if (solution_guess.
size() == 0 ) {
354 int iteration_loops_max;
359 iteration_loops_max = 1;
363 long long max_inner_iterations_loc;
364 if (
config.count(
"max_inner_iterations") > 0 ) {
365 config[
"max_inner_iterations"].get_property( max_inner_iterations_loc );
372 std::uniform_real_distribution<> distrib_real(0.0, 2*
M_PI);
375 for (
long long idx=0; idx<iteration_loops_max; idx++) {
385 solution_guess[jdx] = solution_guess[jdx] + distrib_real(
gen)/100;
390 solution_guess[jdx] = solution_guess[jdx] + distrib_real(
gen);
417 static tbb::enumerable_thread_specific<Matrix> matrix_new_tls;
418 Matrix& matrix_new = matrix_new_tls.local();
420 apply_to( parameters_mtx, matrix_new );
423 if (matrix_new.
isnan()) {
424 std::stringstream sstream;
425 sstream <<
"Sub_Matrix_Decomposition::optimization_problem: matrix_new contains NaN a. Exiting" << std::endl;
433 return cost_function;
446 std::vector<Gate*> gates_loc = instance->
get_gates();
448 static tbb::enumerable_thread_specific<Matrix> matrix_new_tls;
449 Matrix& matrix_new = matrix_new_tls.local();
451 instance->
apply_to( parameters, matrix_new );
454 if (matrix_new.
isnan()) {
455 std::stringstream sstream;
456 sstream <<
"Sub_Matrix_Decomposition::optimization_problem matrix_new contains NaN b." << std::endl;
464 return cost_function;
506 double dparam = 1e-8;
508 auto calculate_displaced_cost = [&](
int i) {
509 if (i == (
int)parameters.
size()) {
515 static tbb::enumerable_thread_specific<Matrix_real> parameters_d_tls;
516 Matrix_real& parameters_d = parameters_d_tls.local();
517 parameters.
copy_to(parameters_d);
518 parameters_d[i] = parameters_d[i] + dparam;
527 for (
int i=0; i<parameter_num_loc+1; ++i) {
528 calculate_displaced_cost(i);
533 tbb::parallel_for(0, parameter_num_loc+1, 1, [&](
int i) {
534 calculate_displaced_cost(i);
549 for (
int idx=0; idx<parameter_num_loc; idx++) {
552 if (isnan(
f->data[idx])) {
553 std::string err(
"Sub_Matrix_Decomposition::optimization_problem_combined: f->data[i] is NaN.");
557 grad[idx] = (
f[idx]-(*f0))/dparam;
601 for ( std::map<int,int>::iterator it=identical_blocks_in.begin(); it!= identical_blocks_in.end(); it++ ) {
627 std::string err(
"Sub_Matrix_Decomposition::clone(): extracting gates was not succesfull.");
bool optimize_layer_num
logical value. Set true to optimize the minimum number of gate layers required in the decomposition...
Sub_Matrix_Decomposition()
Nullary constructor of the class.
static void optimization_problem_grad(Matrix_real parameters, void *void_instance, Matrix_real &grad)
Calculate the approximate derivative (f-f0)/(x-x0) of the cost function with respect to the free para...
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.
Gates_block * unit_gate_structure
Custom gate structure describing the gate structure used in the decomposition. The gate structure is ...
Matrix get_Umtx()
Call to retrive a pointer to the unitary to be transformed.
void disentangle_submatrices()
Start the optimization process to disentangle the most significant qubit from the others...
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.
long long max_inner_iterations
maximal number of inner iterations
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.
virtual Gates_block * clone() override
Create a clone of the present class.
int layer_num
number of gate layers
void add_cnot(int target_qbit, int control_qbit)
Append a CNOT gate gate to the list of gates.
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...
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
std::map< int, int > identical_blocks
A map of <int n: int num> indicating that how many identical succesive blocks should be used in the d...
double get_submatrix_cost_function(Matrix &matrix)
Call to calculate the cost function of a given matrix during the submatrix decomposition process...
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...
std::vector< Gate * > gates
The list of stored gates.
int max_outer_iterations
Maximal number of iterations allowed in the optimization process.
A class implementing the BFGS optimizer based on conjugate gradient direction method of M...
gate_type type
The type of the operation (see enumeration gate_type)
double Start_Optimization(Matrix_real &x, long maximal_iterations_in=5001)
Call this method to start the optimization.
void add_u3(int target_qbit)
Append a U3 gate to the list of gates.
bool subdisentaglement_done
logical value indicating whether the disentamglement of a qubit from the othetrs was done or not ...
virtual void add_gate_layers()
Call to add further layer to the gate structure used in the subdecomposition.
Sub_Matrix_Decomposition * clone()
Call to create a clone of the present class.
std::map< int, int > iteration_loops
A map of <int n: int num> indicating the number of iteration in each step of the decomposition.
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.
~Sub_Matrix_Decomposition()
Destructor of the class.
void add_default_gate_layers()
Call to add default gate layers to the gate structure used in the subdecomposition.
A class containing basic methods for the decomposition process.
Matrix copy() const
Call to create a copy of the matrix.
void copy_to(Matrix_real &target) const
Copy the matrix to a reusable double-precision target matrix.
int extract_gates(Gates_block *op_block)
Call to extract the gates stored in the class.
Double-precision complex matrix (float64).
void copy_to(matrix_base< scalar > &target) const
Copy the current matrix storage into a reusable target matrix.
int size() const
Call to get the number of the allocated elements.
Gates_block()
Default constructor of the class.
A class responsible for grouping two-qubit (CNOT,CZ,CH) and one-qubit gates into layers.
Matrix subdecomposed_mtx
The subdecomposed matrix.
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.
static void optimization_problem_combined(Matrix_real parameters, void *void_instance, double *f0, Matrix_real &grad)
Call to calculate both the cost function and the its gradient components.
Header file for a class responsible for the disentanglement of one qubit from the others...
int parameter_num
the number of free parameters of the operation
double optimization_problem(double *parameters)
The optimization problem of the final optimization.
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...
int qbit_num
number of qubits spanning the matrix of the operation
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
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
int set_iteration_loops(int n, int iteration_loops_in)
Set the number of iteration loops during the subdecomposition of the n-th qubit.
Matrix_real optimized_parameters_mtx
The optimized parameters for the gates.
int get_parallel_configuration()
Get the parallel configuration from the config.
int get_parameter_num() override
Call to get the number of free parameters.
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.
std::mt19937 gen
Standard mersenne_twister_engine seeded with rd()
void solve_layer_optimization_problem(int num_of_parameters, Matrix_real solution_guess_gsl)
Call to solve layer by layer the optimization problem.