Sequential Quantum Gate Decomposer  v1.9.3
Powerful decomposition of general unitarias into one- and two-qubit gates gates
R.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 "R.h"
24 
25 
26 
27 //static tbb::spin_mutex my_mutex;
31 R::R() {
32 
33  name = "R";
34 
35  // number of qubits spanning the matrix of the gate
36  qbit_num = -1;
37  // the size of the matrix
38  matrix_size = -1;
39  // A string describing the type of the gate
40  type = R_OPERATION;
41 
42  // The index of the qubit on which the gate acts (target_qbit >= 0)
43  target_qbit = -1;
44  // The index of the qubit which acts as a control qubit (control_qbit >= 0) in controlled gates
45  control_qbit = -1;
46 
47  parameter_num = 0;
48 
49 }
50 
51 
52 
61 R::R(int qbit_num_in, int target_qbit_in) {
62 
63  name = "R";
64 
65  // number of qubits spanning the matrix of the gate
66  qbit_num = qbit_num_in;
67  // the size of the matrix
69  // A string describing the type of the gate
70  type = R_OPERATION;
71 
72  if (target_qbit_in >= qbit_num) {
73  std::stringstream sstream;
74  sstream << "The index of the target qubit is larger than the number of qubits" << std::endl;
75  print(sstream, 0);
76  throw "The index of the target qubit is larger than the number of qubits";
77  }
78 
79  // The index of the qubit on which the gate acts (target_qbit >= 0)
80  target_qbit = target_qbit_in;
81  // The index of the qubit which acts as a control qubit (control_qbit >= 0) in controlled gates
82  control_qbit = -1;
83 
84  parameter_num = 2;
85 
86 }
87 
88 
92 R::~R() {
93 
94 }
95 
96 
97 
98 
105 void
106 R::apply_to( Matrix_real& parameters, Matrix& input, int parallel ) {
107 
108  if (input.rows != matrix_size ) {
109  std::stringstream sstream;
110  sstream << "Wrong matrix size in RX gate apply" << std::endl;
111  print(sstream, 0);
112  exit(-1);
113  }
114 
115 
116  double ThetaOver2, Phi, Lambda;
117 
118  ThetaOver2 = parameters[0];
119  Phi = parameters[1];
120 
121 
122  Matrix u3_1qbit = Matrix(2,2);
123  u3_1qbit[0].real = std::cos(ThetaOver2);
124  u3_1qbit[0].imag = 0;
125 
126  u3_1qbit[1].real = -1.*std::sin(ThetaOver2)*std::sin(Phi);
127  u3_1qbit[1].imag = -1.*std::sin(ThetaOver2)*std::cos(Phi);
128 
129  u3_1qbit[2].real = std::sin(ThetaOver2)*std::sin(Phi);
130  u3_1qbit[2].imag = -1.*std::sin(ThetaOver2)*std::cos(Phi);
131 
132  u3_1qbit[3].real = std::cos(ThetaOver2);
133  u3_1qbit[3].imag = 0;
134 
135 
136  apply_kernel_to( u3_1qbit, input, false, parallel );
137 
138 
139 }
140 
141 
142 
148 void
150 
151  if (input.cols != matrix_size ) {
152  std::stringstream sstream;
153  sstream << "Wrong matrix size in U3 apply_from_right" << std::endl;
154  print(sstream, 0);
155  exit(-1);
156  }
157 
158 
159  double ThetaOver2, Phi, Lambda;
160 
161  ThetaOver2 = parameters[0];
162  Phi = parameters[1] - M_PI/2;
163  Lambda = -1.*parameters[1] + M_PI/2;
164 
165 
166  // get the U3 gate of one qubit
167  Matrix u3_1qbit = calc_one_qubit_u3(ThetaOver2, Phi, Lambda );
168 
169 
170  apply_kernel_from_right(u3_1qbit, input);
171 
172 
173 }
174 
175 
176 
183 std::vector<Matrix>
184 R::apply_derivate_to( Matrix_real& parameters_mtx, Matrix& input, int parallel ) {
185 
186  if (input.rows != matrix_size ) {
187  std::stringstream sstream;
188  sstream << "Wrong matrix size in RX apply_derivate_to" << std::endl;
189  print(sstream, 0);
190  exit(-1);
191  }
192 
193 
194  std::vector<Matrix> ret;
195 
196 
197 
198  double ThetaOver2,Phi;
199  ThetaOver2 = parameters_mtx[0];
200  Phi = parameters_mtx[1];
201 
202  Matrix res_mtx = input.copy();
203  Matrix u3_1qbit = Matrix(2,2);
204  u3_1qbit[0].real = std::cos(ThetaOver2+ M_PI/2);
205  u3_1qbit[0].imag = 0;
206 
207  u3_1qbit[1].real = -1.*std::sin(ThetaOver2+ M_PI/2)*std::sin(Phi);
208  u3_1qbit[1].imag = -1.*std::sin(ThetaOver2+ M_PI/2)*std::cos(Phi);
209 
210  u3_1qbit[2].real = std::sin(ThetaOver2+ M_PI/2)*std::sin(Phi);
211  u3_1qbit[2].imag = -1.*std::sin(ThetaOver2+ M_PI/2)*std::cos(Phi);
212 
213  u3_1qbit[3].real = std::cos(ThetaOver2+ M_PI/2);
214  u3_1qbit[3].imag = 0;
215 
216  apply_kernel_to( u3_1qbit, res_mtx, true, parallel );
217  ret.push_back(res_mtx);
218 
219 
220  Matrix res_mtx2 = input.copy();
221  u3_1qbit = Matrix(2,2);
222  u3_1qbit[0].real = 0;
223  u3_1qbit[0].imag = 0;
224 
225  u3_1qbit[1].real = -1.*std::sin(ThetaOver2)*std::sin(Phi+ M_PI/2);
226  u3_1qbit[1].imag = -1.*std::sin(ThetaOver2)*std::cos(Phi+ M_PI/2);
227 
228  u3_1qbit[2].real = std::sin(ThetaOver2)*std::sin(Phi+ M_PI/2);
229  u3_1qbit[2].imag = -1.*std::sin(ThetaOver2)*std::cos(Phi+ M_PI/2);
230 
231  u3_1qbit[3].real = 0;
232  u3_1qbit[3].imag = 0;
233 
234  apply_kernel_to( u3_1qbit, res_mtx2, true, parallel );
235  ret.push_back(res_mtx2);
236 
237  return ret;
238 
239 
240 }
241 
242 
248 
249  R* ret = new R(qbit_num, target_qbit);
250 
252  ret->set_parents( parents );
253  ret->set_children( children );
254 
255  return ret;
256 
257 }
258 
259 
260 
261 
269 
270  if ( get_parameter_start_idx() + get_parameter_num() > parameters.size() ) {
271  std::string err("R::extract_parameters: Cant extract parameters, since the dinput arary has not enough elements.");
272  throw err;
273  }
274 
275  Matrix_real extracted_parameters(1,2);
276 
277  extracted_parameters[0] = std::fmod( 2*parameters[ get_parameter_start_idx() ], 4*M_PI);
278  extracted_parameters[1] = std::fmod( parameters[ get_parameter_start_idx() +1], 2*M_PI);
279 
280  return extracted_parameters;
281 
282 }
std::vector< Gate * > parents
list of parent gates to be applied in the circuit prior to this current gate
Definition: Gate.h:95
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
Header file for a class representing a rotation gate around the X axis.
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: R.cpp:184
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
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
int matrix_size
The size N of the NxN matrix associated with the operations.
Definition: Gate.h:89
~R()
Destructor of the class.
Definition: R.cpp:92
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: R.cpp:268
gate_type type
The type of the operation (see enumeration gate_type)
Definition: Gate.h:83
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
void apply_from_right(Matrix_real &parameters, Matrix &input)
Call to apply the gate on the input array/matrix by input*U3.
Definition: R.cpp:149
R()
Nullary constructor of the class.
Definition: R.cpp:31
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
void apply_to(Matrix_real &parameters, Matrix &input, int parallel)
Call to apply the gate on the input array/matrix by R*input.
Definition: R.cpp:106
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
std::string name
A string labeling the gate operation.
Definition: Gate.h:79
A class representing a U3 gate.
Definition: R.h:36
std::vector< Gate * > children
list of child gates to be applied after this current gate
Definition: Gate.h:97
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
R * clone()
Call to create a clone of the present class.
Definition: R.cpp:247
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
Class to store data of complex arrays and its properties.
Definition: matrix_real.h:39