Sequential Quantum Gate Decomposer  v1.9.6
Powerful decomposition of general unitarias into one- and two-qubit gates gates
CU.cpp
Go to the documentation of this file.
2 #include "CU.h"
3 
4 static const double M_PIOver2 = M_PI / 2.0;
5 
6 namespace {
7 template<typename RealMatrixT, typename RealT>
8 void read_cu_trig(
9  const RealMatrixT& precomputed_sincos,
10  RealT& sin_theta,
11  RealT& cos_theta,
12  RealT& sin_phi,
13  RealT& cos_phi,
14  RealT& sin_lambda,
15  RealT& cos_lambda,
16  RealT& sin_gamma,
17  RealT& cos_gamma) {
18 
19  const int theta_offset = 0 * precomputed_sincos.stride;
20  const int phi_offset = 1 * precomputed_sincos.stride;
21  const int lambda_offset = 2 * precomputed_sincos.stride;
22  const int gamma_offset = 3 * precomputed_sincos.stride;
23  sin_theta = precomputed_sincos[theta_offset + 0];
24  cos_theta = precomputed_sincos[theta_offset + 1];
25  sin_phi = precomputed_sincos[phi_offset + 0];
26  cos_phi = precomputed_sincos[phi_offset + 1];
27  sin_lambda = precomputed_sincos[lambda_offset + 0];
28  cos_lambda = precomputed_sincos[lambda_offset + 1];
29  sin_gamma = precomputed_sincos[gamma_offset + 0];
30  cos_gamma = precomputed_sincos[gamma_offset + 1];
31 }
32 }
33 
34 CU::CU() : CU(-1, -1, -1) {}
35 
36 CU::CU(int qbit_num_in, int target_qbit_in, int control_qbit_in)
37  : U3(qbit_num_in, target_qbit_in) {
38  name = "CU";
40  parameter_num = 4;
41  if (qbit_num > 0 && (control_qbit_in < 0 || control_qbit_in >= qbit_num)) {
42  std::string err("CU: control qubit index out of range.");
43  throw err;
44  }
45  control_qbit = control_qbit_in;
46 }
47 
48 CU::~CU() {}
49 
51  CU* ret = new CU(qbit_num, target_qbit, control_qbit);
53  ret->set_parents(parents);
54  ret->set_children(children);
55  return ret;
56 }
57 
58 std::vector<double> CU::get_parameter_multipliers() const {
59  return {2.0, 1.0, 1.0, 1.0};
60 }
61 
62 Matrix CU::gate_kernel(const Matrix_real& precomputed_sincos) {
63  Matrix ret;
64  gate_kernel_to(precomputed_sincos, ret);
65  return ret;
66 }
67 
68 Matrix_float CU::gate_kernel(const Matrix_real_float& precomputed_sincos) {
69  Matrix_float ret;
70  gate_kernel_to(precomputed_sincos, ret);
71  return ret;
72 }
73 
74 Matrix CU::inverse_gate_kernel(const Matrix_real& precomputed_sincos) {
75  Matrix ret;
76  inverse_gate_kernel_to(precomputed_sincos, ret);
77  return ret;
78 }
79 
81  Matrix_float ret;
82  inverse_gate_kernel_to(precomputed_sincos, ret);
83  return ret;
84 }
85 
86 Matrix CU::derivative_kernel(const Matrix_real& precomputed_sincos, int param_idx) {
87  Matrix ret;
88  derivative_kernel_to(precomputed_sincos, param_idx, ret);
89  return ret;
90 }
91 
92 Matrix_float CU::derivative_kernel(const Matrix_real_float& precomputed_sincos, int param_idx) {
93  Matrix_float ret;
94  derivative_kernel_to(precomputed_sincos, param_idx, ret);
95  return ret;
96 }
97 
98 void
99 CU::gate_kernel_to(const Matrix_real& precomputed_sincos, Matrix& output) {
100  double sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda, sin_gamma, cos_gamma;
101  read_cu_trig<Matrix_real, double>(
102  precomputed_sincos,
103  sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda, sin_gamma, cos_gamma
104  );
105  cu_gate_kernel_from_trig_to<Matrix, double>(
106  output, sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda, sin_gamma, cos_gamma
107  );
108 }
109 
110 void
112  float sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda, sin_gamma, cos_gamma;
113  read_cu_trig<Matrix_real_float, float>(
114  precomputed_sincos,
115  sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda, sin_gamma, cos_gamma
116  );
117  cu_gate_kernel_from_trig_to<Matrix_float, float>(
118  output, sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda, sin_gamma, cos_gamma
119  );
120 }
121 
122 void
123 CU::inverse_gate_kernel_to(const Matrix_real& precomputed_sincos, Matrix& output) {
124  double sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda, sin_gamma, cos_gamma;
125  read_cu_trig<Matrix_real, double>(
126  precomputed_sincos,
127  sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda, sin_gamma, cos_gamma
128  );
129  cu_inverse_gate_kernel_from_trig_to<Matrix, double>(
130  output, sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda, sin_gamma, cos_gamma
131  );
132 }
133 
134 void
136  float sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda, sin_gamma, cos_gamma;
137  read_cu_trig<Matrix_real_float, float>(
138  precomputed_sincos,
139  sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda, sin_gamma, cos_gamma
140  );
141  cu_inverse_gate_kernel_from_trig_to<Matrix_float, float>(
142  output, sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda, sin_gamma, cos_gamma
143  );
144 }
145 
146 void
147 CU::derivative_kernel_to(const Matrix_real& precomputed_sincos, int param_idx, Matrix& output) {
148  double sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda, sin_gamma, cos_gamma;
149  read_cu_trig<Matrix_real, double>(
150  precomputed_sincos,
151  sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda, sin_gamma, cos_gamma
152  );
153 
154  if (param_idx == 0) {
155  u3_derivative_kernel_theta_from_trig_to<Matrix, double>(
156  output, sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda
157  );
158  multiply_2x2_by_phase<Matrix, double>(output, sin_gamma, cos_gamma);
159  return;
160  }
161  if (param_idx == 1) {
162  u3_derivative_kernel_phi_from_trig_to<Matrix, double>(
163  output, sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda
164  );
165  multiply_2x2_by_phase<Matrix, double>(output, sin_gamma, cos_gamma);
166  return;
167  }
168  if (param_idx == 2) {
169  u3_derivative_kernel_lambda_from_trig_to<Matrix, double>(
170  output, sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda
171  );
172  multiply_2x2_by_phase<Matrix, double>(output, sin_gamma, cos_gamma);
173  return;
174  }
175  if (param_idx == 3) {
176  cu_derivative_kernel_gamma_from_trig_to<Matrix, double>(
177  output, sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda, sin_gamma, cos_gamma
178  );
179  return;
180  }
181 
182  output = Matrix();
183 }
184 
185 void
186 CU::derivative_kernel_to(const Matrix_real_float& precomputed_sincos, int param_idx, Matrix_float& output) {
187  float sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda, sin_gamma, cos_gamma;
188  read_cu_trig<Matrix_real_float, float>(
189  precomputed_sincos,
190  sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda, sin_gamma, cos_gamma
191  );
192 
193  if (param_idx == 0) {
194  u3_derivative_kernel_theta_from_trig_to<Matrix_float, float>(
195  output, sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda
196  );
197  multiply_2x2_by_phase<Matrix_float, float>(output, sin_gamma, cos_gamma);
198  return;
199  }
200  if (param_idx == 1) {
201  u3_derivative_kernel_phi_from_trig_to<Matrix_float, float>(
202  output, sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda
203  );
204  multiply_2x2_by_phase<Matrix_float, float>(output, sin_gamma, cos_gamma);
205  return;
206  }
207  if (param_idx == 2) {
208  u3_derivative_kernel_lambda_from_trig_to<Matrix_float, float>(
209  output, sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda
210  );
211  multiply_2x2_by_phase<Matrix_float, float>(output, sin_gamma, cos_gamma);
212  return;
213  }
214  if (param_idx == 3) {
215  cu_derivative_kernel_gamma_from_trig_to<Matrix_float, float>(
216  output, sin_theta, cos_theta, sin_phi, cos_phi, sin_lambda, cos_lambda, sin_gamma, cos_gamma
217  );
218  return;
219  }
220 
221  output = Matrix_float();
222 }
std::vector< Gate * > parents
list of parent gates to be applied in the circuit prior to this current gate
Definition: Gate.h:112
virtual void derivative_kernel_to(const Matrix_real &precomputed_sincos, int param_idx, Matrix &output) override
Definition: CU.cpp:147
Copyright (C) Miklos Maroti, 2021 SPDX-License-Identifier: Apache-2.0.
Definition: U3.h:19
static const double M_PIOver2
Definition: CU.cpp:4
Class to store single-precision real arrays and properties.
virtual Matrix derivative_kernel(const Matrix_real &precomputed_sincos, int param_idx) override
Definition: CU.cpp:86
int control_qbit
The index of the qubit which acts as a control qubit (control_qbit >= 0) in controlled operations...
Definition: Gate.h:100
void set_children(std::vector< Gate *> &children_)
Call to set the children of the current gate.
Definition: Gate.cpp:2523
virtual void gate_kernel_to(const Matrix_real &precomputed_sincos, Matrix &output) override
Definition: CU.cpp:99
int target_qbit
The index of the qubit on which the operation acts (target_qbit >= 0)
Definition: Gate.h:98
virtual std::vector< double > get_parameter_multipliers() const override
Returns the per-parameter multipliers relative to 2π used by extract_parameters. ...
Definition: CU.cpp:58
gate_type type
The type of the operation (see enumeration gate_type)
Definition: Gate.h:96
Definition: CU.h:11
#define M_PI
Definition: qgd_math.h:42
virtual Matrix inverse_gate_kernel(const Matrix_real &precomputed_sincos) override
Definition: CU.cpp:74
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:2500
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:2535
virtual void inverse_gate_kernel_to(const Matrix_real &precomputed_sincos, Matrix &output) override
Definition: CU.cpp:123
Double-precision complex matrix (float64).
Definition: matrix.h:38
CU()
Definition: CU.cpp:34
std::string name
A string labeling the gate operation.
Definition: Gate.h:92
Single-precision complex matrix (float32).
Definition: matrix_float.h:41
std::vector< Gate * > children
list of child gates to be applied after this current gate
Definition: Gate.h:114
int parameter_num
the number of free parameters of the operation
Definition: Gate.h:108
void set_parents(std::vector< Gate *> &parents_)
Call to set the parents of the current gate.
Definition: Gate.cpp:2511
int qbit_num
number of qubits spanning the matrix of the operation
Definition: Gate.h:94
virtual CU * clone() override
Call to create a clone of the present class.
Definition: CU.cpp:50
Class to store data of complex arrays and its properties.
Definition: matrix_real.h:41
~CU() override
Definition: CU.cpp:48
virtual Matrix gate_kernel(const Matrix_real &precomputed_sincos) override
Compute the gate kernel matrix from precomputed trigonometric values.
Definition: CU.cpp:62