68 if (qbit_num_in > 30) {
69 std::string err(
"Gate::Gate: Number of qubits supported up to 30");
104 if (qbit_num_in > 30) {
105 std::string err(
"Gate::set_qbit_num: Number of qubits supported up to 30");
110 std::string err(
"Gate::set_qbit_num: The number of qbits is too small, conflicting with either target_qbit os control_qbit");
143 std::string err(
"Gate::get_matrix: Unimplemented function");
157 std::string err(
"Gate::get_matrix: Unimplemented function");
173 std::string err(
"Gate::get_matrix: Unimplemented function");
190 if ( parallel == 0 ) {
191 work_batch = inputs.size();
198 tbb::parallel_for( tbb::blocked_range<int>(0,inputs.size(),work_batch), [&](tbb::blocked_range<int> r) {
199 for (
int idx=r.begin(); idx<r.end(); ++idx) {
201 Matrix* input = &inputs[idx];
240 std::string err(
"Gate::apply_to: Wrong matrix size in Gate gate apply.");
273 std::vector<Matrix> ret;
310 if ( control_qbit_in >=
qbit_num ) {
311 std::string err(
"Gate::set_target_qbit: Wrong value of the control qbit: of out of the range given by qbit_num");
327 std::string err(
"Gate::set_target_qbit: Wrong value of the target qbit: out of the range given by qbit_num");
342 if ((
int)qbit_list.size() !=
qbit_num ) {
343 std::string err(
"Gate::reorder_qubits: Wrong number of qubits.");
352 for (
int idx=0; idx<
qbit_num; idx++) {
354 target_qbit_new = qbit_num-1-idx;
357 control_qbit_new = qbit_num-1-idx;
388 std::vector<int> involved_qbits;
399 return involved_qbits;
546 else if ( input.
cols == 1 ) {
547 if ( parallel == 1 ) {
550 else if ( parallel == 2 ) {
554 std::string err(
"Gate::apply_kernel_to: the argument parallel should be either 0,1 or 2. Set 0 for sequential execution (default), 1 for parallel execution with OpenMP and 2 for parallel with TBB");
567 else if (
qbit_num < 10 || !parallel) {
584 else if ( input.
cols == 1 ) {
618 int current_idx_pair = current_idx+index_step_target;
622 while ( current_idx_pair < input.
cols ) {
624 for(
int idx=0; idx<index_step_target; idx++) {
627 int current_idx_loc = current_idx + idx;
628 int current_idx_pair_loc = current_idx_pair + idx;
633 for (
int row_idx=0; row_idx<
matrix_size; row_idx++) {
635 int row_offset = row_idx*input.
stride;
638 int index = row_offset+current_idx_loc;
639 int index_pair = row_offset+current_idx_pair_loc;
646 input[index].real = tmp1.
real + tmp2.
real;
647 input[index].imag = tmp1.
imag + tmp2.
imag;
649 tmp1 =
mult(u3_1qbit[1], element);
650 tmp2 =
mult(u3_1qbit[3], element_pair);
651 input[index_pair].real = tmp1.
real + tmp2.
real;
652 input[index_pair].imag = tmp1.
imag + tmp2.
imag;
670 current_idx = current_idx + (index_step_target << 1);
671 current_idx_pair = current_idx_pair + (index_step_target << 1);
680 void sincos(
double x,
double *s,
double *c)
682 *s = sin(x), *c = cos(x);
684 #elif defined(__APPLE__) 685 #define sincos __sincos 699 if (isnan(ThetaOver2)) {
700 std::stringstream sstream;
701 sstream <<
"Matrix U3::calc_one_qubit_u3: ThetaOver2 is NaN." << std::endl;
705 std::stringstream sstream;
706 sstream <<
"Matrix U3::calc_one_qubit_u3: Phi is NaN." << std::endl;
710 std::stringstream sstream;
711 sstream <<
"Matrix U3::calc_one_qubit_u3: Lambda is NaN." << std::endl;
716 double cos_theta = 1.0, sin_theta = 0.0;
717 double cos_phi = 1.0, sin_phi = 0.0;
718 double cos_lambda = 1.0, sin_lambda = 0.0;
720 if (ThetaOver2!=0.0) sincos(ThetaOver2, &sin_theta, &cos_theta);
721 if (Phi!=0.0) sincos(Phi, &sin_phi, &cos_phi);
722 if (Lambda!=0.0) sincos(Lambda, &sin_lambda, &cos_lambda);
725 u3_1qbit[0].real = cos_theta;
726 u3_1qbit[0].imag = 0;
728 u3_1qbit[1].real = -cos_lambda*sin_theta;
729 u3_1qbit[1].imag = -sin_lambda*sin_theta;
731 u3_1qbit[2].real = cos_phi*sin_theta;
732 u3_1qbit[2].imag = sin_phi*sin_theta;
736 u3_1qbit[3].real = (cos_phi*cos_lambda-sin_phi*sin_lambda)*cos_theta;
737 u3_1qbit[3].imag = (sin_phi*cos_lambda+cos_phi*sin_lambda)*cos_theta;
752 std::string err(
"Gate::calc_one_qubit_u3: Unimplemented abstract function");
std::vector< Gate * > parents
list of parent gates to be applied in the circuit prior to this current gate
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 parameters_for_calc_one_qubit(double &ThetaOver2, double &Phi, double &Lambda)
Calculate the matrix of a U3 gate gate corresponding to the given parameters acting on a single qbit ...
void print(const std::stringstream &sstream, int verbose_level=1) const
Call to print output messages in the function of the verbosity level.
Header file for a class for the representation of general gate operations.
void add_child(Gate *child)
Call to add a child gate to the current gate.
virtual Matrix get_matrix()
Call to retrieve the operation matrix.
void clear_children()
Call to erase data on children.
int control_qbit
The index of the qubit which acts as a control qubit (control_qbit >= 0) in controlled operations...
virtual std::vector< Matrix > apply_derivate_to(Matrix_real ¶meters_mtx_in, Matrix &input, int parallel)
Call to evaluate the derivate of the circuit on an inout with respect to all of the free parameters...
virtual Gate * clone()
Call to create a clone of the present class.
int stride
The column stride of the array. (The array elements in one row are a_0, a_1, ... a_{cols-1}, 0, 0, 0, 0. The number of zeros is stride-cols)
void set_children(std::vector< Gate *> &children_)
Call to set the children of the current gate.
virtual void set_qbit_num(int qbit_num_in)
Set the number of qubits spanning the matrix of the operation.
int target_qbit
The index of the qubit on which the operation acts (target_qbit >= 0)
void apply_kernel_from_right(Matrix &u3_1qbit, Matrix &input)
Call to apply the gate kernel on the input state or unitary from right (no AVX support) ...
virtual ~Gate()
Destructor of the class.
QGD_Complex16 mult(QGD_Complex16 &a, QGD_Complex16 &b)
Call to calculate the product of two complex scalars.
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.
int parameter_start_idx
the index in the parameter array (corrensponding to the encapsulated circuit) where the gate paramete...
gate_type type
The type of the operation (see enumeration gate_type)
virtual void apply_from_right(Matrix &input)
Call to apply the gate on the input array/matrix by input*Gate.
int rows
The number of rows.
int cols
The number of columns.
gate_type get_type()
Call to get the type of the operation.
void set_control_qbit(int control_qbit_in)
Call to set the control qubit for the gate operation.
void set_parameter_start_idx(int start_idx)
Call to set the starting index of the parameters in the parameter array corresponding to the circuit ...
std::vector< Gate * > get_parents()
Call to get the parents of the current gate.
int get_parameter_start_idx()
Call to get the starting index of the parameters in the parameter array corresponding to the circuit ...
void add_parent(Gate *parent)
Call to add a parent gate to the current gate.
void set_target_qbit(int target_qbit_in)
Call to set the target qubit for the gate operation.
Structure type representing complex numbers in the SQUANDER package.
virtual Matrix_real extract_parameters(Matrix_real ¶meters)
Call to extract parameters from the parameter array corresponding to the circuit, in which the gate i...
void clear_parents()
Call to erase data on parents.
virtual Matrix calc_one_qubit_u3()
Calculate the matrix of the constans gates.
void set_matrix(Matrix input)
Call to set the stored matrix in the operation.
std::vector< Gate * > get_children()
Call to get the children of the current gate.
int Power_of_2(int n)
Calculates the n-th power of 2.
Class to store data of complex arrays and its properties.
int size() const
Call to get the number of the allocated elements.
int get_parameter_num()
Call to get the number of free parameters.
std::string name
A string labeling the gate operation.
std::vector< Gate * > children
list of child gates to be applied after this current gate
int get_target_qbit()
Call to get the index of the target qubit.
void apply_kernel_to(Matrix &u3_1qbit, Matrix &input, bool deriv=false, int parallel=0)
Call to apply the gate kernel on the input state or unitary with optional AVX support.
Base class for the representation of general gate operations.
std::string get_name()
Call to get the name label of the gate.
virtual std::vector< int > get_involved_qubits()
Call to get the qubits involved in the gate operation.
int parameter_num
the number of free parameters of the operation
Header file for commonly used functions and wrappers to CBLAS functions.
virtual void apply_to_list(std::vector< Matrix > &inputs, int parallel)
Call to apply the gate on a list of inputs.
void set_parents(std::vector< Gate *> &parents_)
Call to set the parents of the current gate.
double real
the real part of a complex number
int qbit_num
number of qubits spanning the matrix of the operation
int get_qbit_num()
Call to get the number of qubits composing the unitary.
gate_type
Type definition of operation types (also generalized for decomposition classes derived from the class...
virtual void apply_to(Matrix &input, int parallel)
Call to apply the gate on the input array/matrix.
virtual void reorder_qubits(std::vector< int > qbit_list)
Call to reorder the qubits in the matrix of the operation.
Matrix matrix_alloc
Matrix of the operation.
int get_control_qbit()
Call to get the index of the control qubit.
Class to store data of complex arrays and its properties.
double imag
the imaginary part of a complex number