Sequential Quantum Gate Decomposer  v1.9.3
Powerful decomposition of general unitarias into one- and two-qubit gates gates
U3.cpp
Go to the documentation of this file.
1 /*
2 Created on Fri Jun 26 14:13:26 2020
3 Copyright 2020 Peter Rakyta, Ph.D.
4 
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8 
9  http://www.apache.org/licenses/LICENSE-2.0
10 
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 
17 @author: Peter Rakyta, Ph.D.
18 */
23 #include "U3.h"
24 #include "tbb/tbb.h"
25 
26 // pi/2
27 static double M_PIOver2 = M_PI/2;
28 
29 //static tbb::spin_mutex my_mutex;
33 U3::U3() {
34 
35  // A string labeling the gate operation
36  name = "U3";
37 
38  // number of qubits spanning the matrix of the gate
39  qbit_num = -1;
40  // the size of the matrix
41  matrix_size = -1;
42  // A string describing the type of the gate
44 
45  // The index of the qubit on which the gate acts (target_qbit >= 0)
46  target_qbit = -1;
47  // The index of the qubit which acts as a control qubit (control_qbit >= 0) in controlled gates
48  control_qbit = -1;
49 
50  parameter_num = 0;
51 
52 }
53 
59 U3::U3(int qbit_num_in, int target_qbit_in) {
60 
61  // A string labeling the gate operation
62  name = "U3";
63 
64  // number of qubits spanning the matrix of the gate
65  qbit_num = qbit_num_in;
66  // the size of the matrix
68  // A string describing the type of the gate
70 
71  if (target_qbit_in >= qbit_num) {
72  std::stringstream sstream;
73  sstream << "The index of the target qubit is larger than the number of qubits" << std::endl;
74  print(sstream, 0);
75  throw "The index of the target qubit is larger than the number of qubits";
76  }
77 
78  // The index of the qubit on which the gate acts (target_qbit >= 0)
79  target_qbit = target_qbit_in;
80  // The index of the qubit which acts as a control qubit (control_qbit >= 0) in controlled gates
81  control_qbit = -1;
82 
83  parameter_num = 3;
84 
85 }
86 
87 
92 
93 }
94 
95 
101 Matrix
103 
104  return get_matrix( parameters, false );
105 }
106 
107 
114 Matrix
116 
117  Matrix U3_matrix = create_identity(matrix_size);
118  apply_to(parameters, U3_matrix, parallel);
119 
120 #ifdef DEBUG
121  if (U3_matrix.isnan()) {
122  std::stringstream sstream;
123  sstream << "U3::get_matrix: U3_matrix contains NaN." << std::endl;
124  verbose_level=1;
125  print(sstream,verbose_level);
126  }
127 #endif
128 
129  return U3_matrix;
130 
131 }
132 
133 
140 void
141 U3::apply_to_list( Matrix_real& parameters_mtx, std::vector<Matrix>& inputs, int parallel ) {
142 
143  int work_batch = 1;
144  if ( parallel == 0 ) {
145  work_batch = inputs.size();
146  }
147  else {
148  work_batch = 1;
149  }
150 
151 
152  tbb::parallel_for( tbb::blocked_range<int>(0,inputs.size(),work_batch), [&](tbb::blocked_range<int> r) {
153  for (int idx=r.begin(); idx<r.end(); ++idx) {
154 
155  Matrix* input = &inputs[idx];
156 
157  apply_to( parameters_mtx, *input, parallel );
158 
159  }
160 
161  });
162 
163 }
164 
165 
172 void
173 U3::apply_to( Matrix_real& parameters_mtx, Matrix& input, int parallel ) {
174 
175  if (input.rows != matrix_size ) {
176  std::string err("U3::apply_to: Wrong input size in U3 gate apply.");
177  throw err;
178  }
179 
180  double ThetaOver2 = parameters_mtx[0];
181  double Phi = parameters_mtx[1];
182  double Lambda = parameters_mtx[2];
183 
184  // get the U3 gate of one qubit
185  Matrix u3_1qbit = calc_one_qubit_u3(ThetaOver2, Phi, Lambda );
186 
187  apply_kernel_to( u3_1qbit, input, false, parallel );
188 }
189 
195 void
196 U3::apply_from_right( Matrix_real& parameters_mtx, Matrix& input ) {
197 
198  if (input.cols != matrix_size ) {
199  std::string err("U3::apply_from_right: Wrong matrix size in U3 apply_from_right.");
200  throw err;
201  }
202 
203  double ThetaOver2 = parameters_mtx[0];
204  double Phi = parameters_mtx[1];
205  double Lambda = parameters_mtx[2];
206 
207  // get the U3 gate of one qubit
208  Matrix u3_1qbit = calc_one_qubit_u3(ThetaOver2, Phi, Lambda );
209 
210  apply_kernel_from_right(u3_1qbit, input);
211 }
212 
219 std::vector<Matrix>
220 U3::apply_derivate_to( Matrix_real& parameters_mtx, Matrix& input, int parallel ) {
221 
222  if (input.rows != matrix_size ) {
223  std::string err("U3::apply_derivate_to: Wrong matrix size in U3 gate apply.");
224  throw err;
225  }
226 
227  std::vector<Matrix> ret;
228 
229  double ThetaOver2 = parameters_mtx[0];
230  double Phi = parameters_mtx[1];
231  double Lambda = parameters_mtx[2];
232  bool deriv = true;
233 
234 
235  Matrix u3_1qbit_theta = calc_one_qubit_u3(ThetaOver2+M_PIOver2, Phi, Lambda);
236  Matrix res_mtx_theta = input.copy();
237  apply_kernel_to( u3_1qbit_theta, res_mtx_theta, deriv, parallel );
238  ret.push_back(res_mtx_theta);
239 
240 
241  Matrix u3_1qbit_phi = calc_one_qubit_u3(ThetaOver2, Phi+M_PIOver2, Lambda );
242  memset(u3_1qbit_phi.get_data(), 0.0, 2*sizeof(QGD_Complex16) );
243  Matrix res_mtx_phi = input.copy();
244  apply_kernel_to( u3_1qbit_phi, res_mtx_phi, deriv, parallel );
245  ret.push_back(res_mtx_phi);
246 
247 
248  Matrix u3_1qbit_lambda = calc_one_qubit_u3(ThetaOver2, Phi, Lambda+M_PIOver2 );
249  memset(u3_1qbit_lambda.get_data(), 0.0, sizeof(QGD_Complex16) );
250  memset(u3_1qbit_lambda.get_data()+2, 0.0, sizeof(QGD_Complex16) );
251  Matrix res_mtx_lambda = input.copy();
252  apply_kernel_to( u3_1qbit_lambda, res_mtx_lambda, deriv, parallel );
253  ret.push_back(res_mtx_lambda);
254 
255 
256  return ret;
257 }
258 
263 void U3::set_qbit_num(int qbit_num_in) {
264  Gate::set_qbit_num(qbit_num_in); // setting the number of qubits
265 }
266 
271 void U3::reorder_qubits( std::vector<int> qbit_list) {
272  Gate::reorder_qubits(qbit_list);
273 }
274 
280 
281  U3* ret = new U3(qbit_num, target_qbit);
282 
284  ret->set_parents( parents );
285  ret->set_children( children );
286 
287  return ret;
288 }
289 
290 
298 
299  if ( get_parameter_start_idx() + get_parameter_num() > parameters.size() ) {
300  std::string err("U3::extract_parameters: Cant extract parameters, since the dinput arary has not enough elements.");
301  throw err;
302  }
303 
304  Matrix_real extracted_parameters(1, 3);
305 
306  extracted_parameters[0] = std::fmod( 2*parameters[ get_parameter_start_idx() ], 4*M_PI);
307  extracted_parameters[1] = std::fmod( parameters[ get_parameter_start_idx()+1 ], 2*M_PI);
308  extracted_parameters[2] = std::fmod( parameters[ get_parameter_start_idx()+2 ], 2*M_PI);
309 
310  return extracted_parameters;
311 }
std::vector< Gate * > parents
list of parent gates to be applied in the circuit prior to this current gate
Definition: Gate.h:95
bool isnan()
Call to check the array for NaN entries.
Definition: matrix.cpp:128
A class representing a U3 gate.
Definition: U3.h:36
void print(const std::stringstream &sstream, int verbose_level=1) const
Call to print output messages in the function of the verbosity level.
Definition: logging.cpp:55
virtual Matrix get_matrix()
Call to retrieve the operation matrix.
Definition: Gate.cpp:129
virtual void apply_to(Matrix_real &parameters, Matrix &input, int parallel)
Call to apply the gate on the input array/matrix by U3*input.
Definition: U3.cpp:173
int control_qbit
The index of the qubit which acts as a control qubit (control_qbit >= 0) in controlled operations...
Definition: Gate.h:87
void set_children(std::vector< Gate *> &children_)
Call to set the children of the current gate.
Definition: Gate.cpp:802
virtual void set_qbit_num(int qbit_num_in)
Set the number of qubits spanning the matrix of the operation.
Definition: Gate.cpp:102
U3()
Nullary constructor of the class.
Definition: U3.cpp:33
int target_qbit
The index of the qubit on which the operation acts (target_qbit >= 0)
Definition: Gate.h:85
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) ...
Definition: Gate.cpp:613
void apply_to_list(Matrix_real &parameters, std::vector< Matrix > &inputs, int parallel)
Call to apply the gate on the input array/matrix by U3*input.
Definition: U3.cpp:141
int matrix_size
The size N of the NxN matrix associated with the operations.
Definition: Gate.h:89
scalar * get_data() const
Call to get the pointer to the stored data.
static double M_PIOver2
Definition: U3.cpp:27
virtual void reorder_qubits(std::vector< int > qbit_list)
Call to reorder the qubits in the matrix of the gate.
Definition: U3.cpp:271
virtual U3 * clone()
Call to create a clone of the present class.
Definition: U3.cpp:279
gate_type type
The type of the operation (see enumeration gate_type)
Definition: Gate.h:83
virtual void apply_from_right(Matrix_real &parameters, Matrix &input)
Call to apply the gate on the input array/matrix by input*U3.
Definition: U3.cpp:196
int rows
The number of rows.
Definition: matrix_base.hpp:42
int cols
The number of columns.
Definition: matrix_base.hpp:44
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 ...
Definition: Gate.cpp:779
int get_parameter_start_idx()
Call to get the starting index of the parameters in the parameter array corresponding to the circuit ...
Definition: Gate.cpp:814
Structure type representing complex numbers in the SQUANDER package.
Definition: QGDTypes.h:38
virtual Matrix calc_one_qubit_u3()
Calculate the matrix of the constans gates.
Definition: Gate.cpp:750
int Power_of_2(int n)
Calculates the n-th power of 2.
Definition: common.cpp:117
Class to store data of complex arrays and its properties.
Definition: matrix.h:38
int size() const
Call to get the number of the allocated elements.
int get_parameter_num()
Call to get the number of free parameters.
Definition: Gate.cpp:486
Header file for a class representing a U3 gate.
virtual Matrix_real extract_parameters(Matrix_real &parameters)
Call to extract parameters from the parameter array corresponding to the circuit, in which the gate i...
Definition: U3.cpp:297
std::string name
A string labeling the gate operation.
Definition: Gate.h:79
std::vector< Gate * > children
list of child gates to be applied after this current gate
Definition: Gate.h:97
virtual std::vector< Matrix > apply_derivate_to(Matrix_real &parameters, Matrix &input, int parallel)
Call to evaluate the derivate of the circuit on an inout with respect to all of the free parameters...
Definition: U3.cpp:220
virtual ~U3()
Destructor of the class.
Definition: U3.cpp:91
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.
Definition: Gate.cpp:537
Matrix create_identity(int matrix_size)
Call to create an identity matrix.
Definition: common.cpp:164
int parameter_num
the number of free parameters of the operation
Definition: Gate.h:91
void set_parents(std::vector< Gate *> &parents_)
Call to set the parents of the current gate.
Definition: Gate.cpp:790
Matrix copy()
Call to create a copy of the matrix.
Definition: matrix.cpp:105
int qbit_num
number of qubits spanning the matrix of the operation
Definition: Gate.h:81
virtual void set_qbit_num(int qbit_num_in)
Call to set the number of qubits spanning the matrix of the gate.
Definition: U3.cpp:263
virtual void reorder_qubits(std::vector< int > qbit_list)
Call to reorder the qubits in the matrix of the operation.
Definition: Gate.cpp:339
Class to store data of complex arrays and its properties.
Definition: matrix_real.h:39