120 double optimization_tolerance_loc;
122 if (
config.count(
"optimization_tolerance") > 0 ) {
123 config[
"optimization_tolerance"].get_property( optimization_tolerance_loc );
130 if (
config.count(
"tree_level_max") > 0 ){
131 config[
"tree_level_max"].get_property( level_max );
143 std::stringstream sstream;
144 sstream <<
"Decomposition did not reached prescribed high numerical precision." << std::endl;
163 double optimization_tolerance_loc;
164 if (
config.count(
"optimization_tolerance") > 0 ) {
165 config[
"optimization_tolerance"].get_property( optimization_tolerance_loc );
193 std::uniform_real_distribution<double> unif(0.0,1.0);
194 std::default_random_engine re;
196 std::vector<GrayCodeCNOT> possible_gate_structures;
198 long long use_osr = 0;
199 if (
config.count(
"use_osr") > 0) {
200 config[
"use_osr"].get_property(use_osr);
203 double Fnorm = std::sqrt(static_cast<double>(1 <<
qbit_num));
204 double osr_tol = 1e-3;
206 std::uniform_real_distribution<> distrib_real(0.0, 2 *
M_PI);
208 double inverz_temperature = use_osr ? 3.0 : 1.0;
221 std::stringstream sstream;
222 sstream <<
"Starting optimization with " << gate_structure_loc->
get_gate_num() <<
" decomposing layers." << std::endl;
230 const std::tuple<int, double, std::vector<int>, std::vector<std::pair<int, double>>>& best_osr_result = sn.
get_best_osr_result();
231 int cnot_lower_bound = std::get<0>(best_osr_result);
232 current_minimum_tmp = cnot_lower_bound + std::get<1>(best_osr_result) / (
qbit_num + (
qbit_num >= 4 ? 2 : 0));
234 if (cnot_lower_bound == 0) {
235 double current_inner_min;
237 for (
int iter = 0; iter < 5; iter++) {
240 if ( current_inner_min < optimization_tolerance_loc ) {
244 gcode_best_solution = gcode;
248 delete( gate_structure_loc );
249 gate_structure_loc = NULL;
250 if ( current_inner_min < optimization_tolerance_loc ) {
256 delete( gate_structure_loc );
257 gate_structure_loc = NULL;
263 sstream <<
"Optimization with " << gcode.
size() <<
" levels converged to " << current_minimum_tmp;
282 gcode_best_solution = gcode;
286 possible_gate_structures.clear();
293 double random_double = unif(re);
294 double number_to_test = exp( -inverz_temperature*(current_minimum_tmp-
current_minimum) );
296 if( random_double < number_to_test ) {
300 gcode_best_solution = gcode;
304 possible_gate_structures.clear();
317 if( possible_gate_structures.size() == 0 ) {
325 if( possible_gate_structures.size() == 0 ) {
332 gcode_best_solution = std::get<0>(pair);
337 if( possible_gate_structures.size() > 0 ||
best_solutions.size() == 0 ) {
345 if ( possible_gate_structures.size() == 0 ) {
376 return gcode_best_solution;
398 double minimum = std::get<1>( *it );
400 if( minimum > minimum_) {
421 std::vector<GrayCodeCNOT>
425 std::vector<GrayCodeCNOT> possible_structures_list;
426 int n_ary_limit_max =
static_cast<int>(
topology.size());
435 for(
int gcode_idx=0; gcode_idx<gcode.
size(); gcode_idx++ ) {
437 for(
int gcode_element=0; gcode_element<n_ary_limit_max; gcode_element++ ) {
440 gcode_modified[gcode_idx] = gcode_element;
444 possible_structures_list.push_back( gcode_modified );
453 for(
int gcode_idx=0; gcode_idx<gcode.
size(); gcode_idx++ ) {
459 possible_structures_list.push_back( gcode_modified );
467 return possible_structures_list;
474 for(
int gcode_element=0; gcode_element<n_ary_limit_max; gcode_element++ ) {
477 gcode_modified[ gcode_extended.
size()-1 ] = gcode_element;
481 possible_structures_list.push_back( gcode_modified );
486 return possible_structures_list;
500 if ( gcodes.size() == 0 ) {
501 std::string err(
"N_Qubit_Decomposition_Tabu_Search::draw_gate_structure_from_list: The list of gates structure is empty." );
515 for(
size_t gcode_idx=0; gcode_idx<gcodes.size(); gcode_idx++ ) {
517 gcode = gcodes[ gcode_idx ];
518 weights[
static_cast<int>(gcode_idx) ] = fact*(levels);
520 for(
int gcode_element_idx=0; gcode_element_idx<gcode.
size(); gcode_element_idx++ ) {
521 if( gcode[gcode_element_idx] > -1 ) {
522 weights[
static_cast<int>(gcode_idx) ] = weights[ static_cast<int>(gcode_idx) ] - fact;
534 for(
int idx=0; idx<weights.
size(); idx++ ) {
535 weight_sum = weight_sum + weights[idx];
539 std::random_device dev;
540 std::mt19937 rng(dev());
541 std::uniform_int_distribution<std::mt19937::result_type> dist(0,weight_sum);
543 int random_num = dist(rng);
544 int weight_sum_partial = 0;
546 for(
int idx=0; idx<weights.
size(); idx++ ) {
548 weight_sum_partial = weight_sum_partial + weights[idx];
550 if( random_num < weight_sum_partial ) {
560 gcodes.erase( gcodes.begin() + chosen_idx );
Gates_block * determine_gate_structure(Matrix_real &optimized_parameters_mtx)
Call determine the gate structrue of the decomposing circuit.
void insert_into_best_solution(const GrayCodeCNOT &gcode_, double minimum_)
Call to store a given solution among the best ones.
void print(const std::stringstream &sstream, int verbose_level=1) const
Call to print output messages in the function of the verbosity level.
Copyright 2021 Budapest Quantum Computing Group.
std::vector< std::vector< int > > unique_cuts(int n)
int get_num_iters()
Get the number of processed iterations during the optimization process.
std::vector< std::pair< GrayCodeCNOT, double > > best_solutions
Matrix_real copy() const
Call to create a copy of the matrix.
A base class to determine the decomposition of an N-qubit unitary into a sequence of CNOT and U3 gate...
int levels
[creating decomp class]
double get_current_minimum()
Call to get the obtained minimum of the cost function.
N_Qubit_Decomposition_Tabu_Search()
Nullary constructor of the class.
void increment_num_iters(int delta=1)
Atomically increment the tracked number of optimization iterations.
N_Qubit_Decomposition_custom perform_optimization(Gates_block *gate_structure_loc)
Call to perform the optimization on the given gate structure.
int level_limit
The maximal number of adaptive layers used in the decomposition.
void sync_optimized_parameters_float()
Synchronize the float32 parameter mirror from the double optimizer storage.
int get_gate_num()
Call to get the number of gates grouped in the class.
GrayCodeCNOT draw_gate_structure_from_list(std::vector< GrayCodeCNOT > &gcodes)
Call to sample a gate structure from a list of gate structures to test in the optimization process...
A base class to determine the decomposition of an N-qubit unitary into a sequence of CNOT and U3 gate...
double optimization_tolerance
The maximal allowed error of the optimization problem (The error of the decomposition would scale wit...
GrayCode_base remove_Digit(const int idx) const
Call to add a new digit to the Gray code.
int accelerator_num
number of utilized accelerators
std::vector< matrix_base< int > > topology
A vector of index pairs encoding the connectivity between the qubits.
Matrix_real get_optimized_parameters()
Call to get the optimized parameters.
virtual ~N_Qubit_Decomposition_Tabu_Search()
Destructor of the class.
GrayCode_base add_Digit(const intType n_ary_limit) const
Call to add a new digit to the Gray code.
SearchNode evaluate_path(N_Qubit_Decomposition_custom &cDecomp_custom_random, MinCnotBoundSolver &osr_bound_solver, std::vector< std::vector< int >> &all_cuts, double Fnorm, double osr_tol, std::uniform_real_distribution<> &distrib_real, std::mt19937 &gen, const GrayCodeCNOT &path)
std::vector< GrayCodeCNOT > determine_mutated_structures(const GrayCodeCNOT &gcode)
Call to generate a list of mutated gate structures.
Double-precision complex matrix (float64).
int size() const
Call to get the number of the allocated elements.
GrayCode_base copy() const
Call to create a copy of the state.
A class responsible for grouping two-qubit (CNOT,CZ,CH) and one-qubit gates into layers.
Header file for a class implementing the adaptive gate decomposition algorithm of arXiv:2203...
std::string name
A string labeling the gate operation.
Single-precision complex matrix (float32).
std::map< std::string, Config_Element > config
config metadata utilized during the optimization
Gates_block * construct_gate_structure_from_Gray_code(const GrayCodeCNOT &gcode, bool finalize=true)
Call to construct a gate structure corresponding to the configuration of the two-qubit gates describe...
std::unordered_set< GrayCodeCNOT, GrayCodeHashCNOT > tested_gate_structures
the set of already examined gate structures (mapped to n-ary Gray codes)
const std::tuple< int, double, std::vector< int >, std::vector< std::pair< int, double > > > & get_best_osr_result() const
Header file for the paralleized calculation of the cost function of the final optimization problem (s...
volatile double current_minimum
The current minimum of the optimization problem.
int qbit_num
number of qubits spanning the matrix of the operation
Header file for DFE support in unitary simulation.
Matrix_real optimized_parameters_mtx
The optimized parameters for the gates.
void set_cost_function_variant(cost_function_type variant)
Call to set the variant of the cost function used in the calculations.
Class to store data of complex arrays and its properties.
std::mt19937 gen
Standard mersenne_twister_engine seeded with rd()
GrayCodeCNOT tabu_search_over_gate_structures()
Perform tabu serach over gate structures.