42 int cnot_num_curr = 0;
52 int cnot_or_u3 = rand() % 5 + 1;
59 if (cnot_or_u3 <= 4) {
62 parameters[0] = double(rand())/RAND_MAX*4*
M_PI;
63 parameters[1] = double(rand())/RAND_MAX*2*
M_PI;
64 parameters[2] = double(rand())/RAND_MAX*2*
M_PI;
71 u3_op =
new U3(qbit_num, target_qbit);
77 else if ( cnot_or_u3 == 5 ) {
84 if (target_qbit == control_qbit) {
90 cnot_op =
new CNOT(qbit_num, control_qbit, target_qbit);
95 cnot_num_curr = cnot_num_curr + 1;
114 if (cnot_num_curr >= cnot_num) {
134 template<
typename scalar>
struct RunTraits;
136 template<>
struct RunTraits<double> {
142 template<>
struct RunTraits<float> {
149 template<
typename scalar>
150 inline scalar gamma_impl(
int dim) {
151 return static_cast<scalar>(
152 std::pow(-1.0, 0.25*(2*dim - 1 + std::pow(-1.0, dim)))
157 inline int convert_index_impl(
int varalpha,
int varbeta) {
158 return varbeta + (varalpha - 1)*(varalpha - 2)/2;
162 template<
typename scalar>
163 typename RunTraits<scalar>::matrix
164 Q_tmpl(
typename RunTraits<scalar>::complex u1,
165 typename RunTraits<scalar>::complex u2 )
167 using MatrixT =
typename RunTraits<scalar>::matrix;
171 ret[2].real = -u1.real;
172 ret[2].imag = u1.imag;
173 ret[3].real = u2.real;
174 ret[3].imag = -u2.imag;
179 template<
typename scalar>
180 typename RunTraits<scalar>::matrix
181 E_alpha_beta_tmpl(
int varalpha,
int varbeta,
int dim)
183 using ComplexT =
typename RunTraits<scalar>::complex;
184 using MatrixT =
typename RunTraits<scalar>::matrix;
185 MatrixT ret(dim, dim);
186 memset(ret.get_data(), 0, dim*dim*
sizeof(ComplexT));
187 ret[varalpha*dim + varbeta].real =
scalar(1);
192 template<
typename scalar>
193 typename RunTraits<scalar>::matrix
194 I_alpha_beta_tmpl(
int varalpha,
int varbeta,
int dim)
196 typename RunTraits<scalar>::matrix ret = RunTraits<scalar>::identity(dim);
197 ret[varalpha*dim + varalpha].real =
scalar(0);
198 ret[varbeta*dim + varbeta ].real =
scalar(0);
203 template<
typename scalar>
204 typename RunTraits<scalar>::matrix
205 M_tmpl(
int varalpha,
int varbeta,
206 typename RunTraits<scalar>::complex s,
207 typename RunTraits<scalar>::complex t,
210 using MatrixT =
typename RunTraits<scalar>::matrix;
211 MatrixT Qloc = Q_tmpl<scalar>(s, t);
212 MatrixT ret1 = E_alpha_beta_tmpl<scalar>(varbeta, varbeta, dim);
213 MatrixT ret2 = E_alpha_beta_tmpl<scalar>(varbeta, varalpha, dim);
214 MatrixT ret3 = E_alpha_beta_tmpl<scalar>(varalpha, varbeta, dim);
215 MatrixT ret4 = E_alpha_beta_tmpl<scalar>(varalpha, varalpha, dim);
220 MatrixT ret(dim, dim);
221 for (
int idx = 0; idx < dim*dim; ++idx) {
222 ret[idx].real = ret1[idx].real + ret2[idx].real + ret3[idx].real + ret4[idx].real;
223 ret[idx].imag = ret1[idx].imag + ret2[idx].imag + ret3[idx].imag + ret4[idx].imag;
229 template<
typename scalar>
230 typename RunTraits<scalar>::matrix
231 Omega_tmpl(
int varalpha,
int varbeta,
232 typename RunTraits<scalar>::complex
x,
233 typename RunTraits<scalar>::complex y,
236 using MatrixT =
typename RunTraits<scalar>::matrix;
237 MatrixT ret = I_alpha_beta_tmpl<scalar>(varalpha, varbeta, dim);
239 const int threshold = 3 + (dim == 2 ? 1 : 0);
241 if (varalpha + varbeta != threshold) {
242 Mloc = M_tmpl<scalar>(varalpha, varbeta,
x, y, dim);
245 Mloc = M_tmpl<scalar>(varalpha, varbeta,
x,
246 mult(gamma_impl<scalar>(dim), y), dim);
248 for (
int idx = 0; idx < dim*dim; ++idx) {
249 ret[idx].real += Mloc[idx].real;
250 ret[idx].imag += Mloc[idx].imag;
256 template<
typename scalar>
257 typename RunTraits<scalar>::matrix
260 using ComplexT =
typename RunTraits<scalar>::complex;
261 using MatrixT =
typename RunTraits<scalar>::matrix;
263 MatrixT ret = RunTraits<scalar>::identity(dim);
265 for (
int varalpha = 1; varalpha < dim; ++varalpha) {
266 for (
int varbeta = 0; varbeta < varalpha; ++varbeta) {
267 const int param_idx = convert_index_impl(varalpha, varbeta);
268 const scalar theta_loc = vartheta[param_idx];
269 const scalar phi_loc = varphi[param_idx];
272 scalar cos_theta, sin_theta, cos_phi_loc, sin_phi_loc;
273 qgd_sincos<scalar>(theta_loc, &sin_theta, &cos_theta);
274 qgd_sincos<scalar>(phi_loc, &sin_phi_loc, &cos_phi_loc);
276 a.real =
scalar(cos_theta * cos_phi_loc);
277 a.imag =
scalar(cos_theta * sin_phi_loc);
280 const scalar varepsilon = (varalpha - 1 == varbeta)
281 ? varkappa[varalpha - 1] :
scalar(0);
282 scalar cos_epsilon, sin_epsilon;
283 qgd_sincos<scalar>(varepsilon, &sin_epsilon, &cos_epsilon);
285 b.real =
scalar(sin_theta * cos_epsilon);
286 b.imag =
scalar(sin_theta * sin_epsilon);
291 MatrixT Omega_loc = Omega_tmpl<scalar>(varalpha, varbeta, a, b, dim);
292 ret =
dot(ret, Omega_loc);
298 gamma_loc.real = gamma_impl<scalar>(dim);
299 gamma_loc.imag =
scalar(0);
300 for (
int idx = 0; idx < dim*dim; ++idx) {
301 ret[idx] =
mult(ret[idx], gamma_loc);
318 throw "wrong dimension";
334 const int n =
int(dim*(dim-1)/2);
336 double* vartheta = (
double*)
qgd_calloc( n,
sizeof(
double), 64 );
337 double* varphi = (
double*)
qgd_calloc( n,
sizeof(
double), 64 );
338 double* varkappa = (
double*)
qgd_calloc( dim - 1,
sizeof(
double), 64 );
340 srand( static_cast<unsigned int>(time(NULL)) );
342 for (
int idx = 0; idx <
n; ++idx) vartheta[idx] = (2*
double(rand())/RAND_MAX - 1)*2*
M_PI;
343 for (
int idx = 0; idx <
n; ++idx) varphi[idx] = (2*
double(rand())/RAND_MAX - 1)*2*
M_PI;
344 for (
int idx = 0; idx < dim - 1; ++idx) varkappa[idx] = (2*
double(rand())/RAND_MAX - 1)*2*
M_PI;
346 Matrix Umtx = construct_unitary_tmpl<double>(vartheta, varphi, varkappa, dim);
365 return construct_unitary_tmpl<double>(vartheta, varphi, varkappa, dim);
379 return construct_unitary_tmpl<float>(vartheta, varphi, varkappa, dim);
390 return construct_unitary_tmpl<double>(
392 parameters +
int(dim*(dim-1)/2),
393 parameters +
int(dim*(dim-1)),
Matrix dot(Matrix &A, Matrix &B)
Call to calculate the product of two complex matrices by calling method zgemm3m from the CBLAS librar...
Copyright (C) Miklos Maroti, 2021 SPDX-License-Identifier: Apache-2.0.
Matrix few_CNOT_unitary(int qbit_num, int cnot_num)
Call to create a random unitary constructed by CNOT operation between randomly chosen qubits and by r...
void * qgd_calloc(int element_num, int size, int alignment)
custom defined memory allocation function.
void qgd_free(void *ptr)
custom defined memory release function.
Structure type representing single-precision complex numbers.
QGD_Complex16 mult(QGD_Complex16 &a, QGD_Complex16 &b)
Call to calculate the product of two complex scalars.
virtual Matrix get_matrix(Matrix_real ¶meters, int parallel)
Call to retrieve the gate matrix.
Umtx
The unitary to be decomposed.
Structure type representing complex numbers in the SQUANDER package.
A class representing a CNOT operation.
int Power_of_2(int n)
Calculates the n-th power of 2.
Double-precision complex matrix (float64).
Random_Unitary(int dim_in)
Constructor.
Single-precision complex matrix (float32).
Matrix create_identity(int matrix_size)
Call to create an identity matrix.
Matrix Construct_Unitary_Matrix()
Construct a random unitary with internally generated float64 parameters.
Class to store data of complex arrays and its properties.
Matrix_float create_identity_float(int matrix_size)
Call to create a single-precision complex identity matrix.