Sequential Quantum Gate Decomposer  v1.9.6
Powerful decomposition of general unitarias into one- and two-qubit gates gates
Random_Orthogonal.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 You should have received a copy of the GNU General Public License
18 along with this program. If not, see http://www.gnu.org/licenses/.
19 
20 @author: Peter Rakyta, Ph.D.
21 */
27 #include "Random_Orthogonal.h"
28 #include "qgd_math.h"
29 #include "logging.h"
30 
31 
32 
39 
40  if (dim_in < 2) {
41  throw "wrong dimension";
42  }
43 
44  // number of qubits
45  dim = dim_in;
46 
47 }
48 
49 
54 Matrix
56 
57  // create array of random parameters to construct random unitary
58  Matrix_real vargamma(1, dim*(dim-1)/2 );
59 
60 
61  // initialize random seed:
62  srand (static_cast<unsigned int>(time(NULL)));
63 
64  for (int idx=0; idx<dim*(dim-1)/2; idx++) {
65  vargamma[idx] = (2*double(rand())/double(RAND_MAX)-1)*2*M_PI;
66  }
67  //vargamma[dim*(dim-1)/2-1] = 3.14159265359/2;
68 
70 
71 
72  return Umtx;
73 
74 }
75 
76 
84 Matrix
86 
87 //The stringstream input to store the output messages.
88 std::stringstream sstream;
89 
90 //Integer value to set the verbosity level of the output messages.
91 int verbose_level;
92 
93  if (vargamma.size() != dim*(dim-1)/2) {
94  sstream << "Wring number of parameters in Random_Orthogonal::Construct_Orthogonal_Matrix" << std::endl;
95  verbose_level=1;
96  print(sstream, verbose_level);
97  exit(-1);
98  }
99 
100  // construct vargamma matrix elements
101  Matrix_real vargamma_mtx(dim, dim);
102  memset( vargamma_mtx.get_data(), 0, vargamma_mtx.size()*sizeof(double) );
103  int gamma_index = 0;
104  for (int idx=0; idx<dim; idx++) {
105  for (int jdx=idx+1; jdx<dim; jdx++) {
106  vargamma_mtx[idx*vargamma_mtx.stride + jdx] = vargamma[gamma_index];
107  gamma_index++;
108  }
109  //vargamma_mtx[ idx*dim + idx ] = 3.14159265358979323846/2;
110  }
111 /*
112 //vargamma_mtx[0*vargamma_mtx.stride + dim-7] = 0.0;
113 //vargamma_mtx[0*vargamma_mtx.stride + dim-6] = 0.0;
114 //vargamma_mtx[0*vargamma_mtx.stride + dim-5] = 0.0;
115 vargamma_mtx[0*vargamma_mtx.stride + dim-4] = 0.0;
116 vargamma_mtx[0*vargamma_mtx.stride + dim-3] = 0.0;
117 vargamma_mtx[0*vargamma_mtx.stride + dim-2] = 0.0;
118 vargamma_mtx[0*vargamma_mtx.stride + dim-1] = 0.0;
119 
120 //vargamma_mtx[1*vargamma_mtx.stride + dim-6] = 0.0;
121 //vargamma_mtx[1*vargamma_mtx.stride + dim-5] = 0.0;
122 vargamma_mtx[1*vargamma_mtx.stride + dim-4] = 0.0;
123 vargamma_mtx[1*vargamma_mtx.stride + dim-3] = 0.0;
124 vargamma_mtx[1*vargamma_mtx.stride + dim-2] = 0.0;
125 vargamma_mtx[1*vargamma_mtx.stride + dim-1] = 0.0;
126 
127 
128 //vargamma_mtx[2*vargamma_mtx.stride + dim-5] = 0.0;
129 vargamma_mtx[2*vargamma_mtx.stride + dim-4] = 0.0;
130 vargamma_mtx[2*vargamma_mtx.stride + dim-3] = 0.0;
131 vargamma_mtx[2*vargamma_mtx.stride + dim-2] = 0.0;
132 vargamma_mtx[2*vargamma_mtx.stride + dim-1] = 0.0;
133 
134 vargamma_mtx[3*vargamma_mtx.stride + dim-4] = 0.0;
135 vargamma_mtx[3*vargamma_mtx.stride + dim-3] = 0.0;
136 vargamma_mtx[3*vargamma_mtx.stride + dim-2] = 0.0;
137 vargamma_mtx[3*vargamma_mtx.stride + dim-1] = 0.0;
138 
139 //vargamma_mtx[4*vargamma_mtx.stride + dim-3] = 0.0;
140 //vargamma_mtx[4*vargamma_mtx.stride + dim-2] = 0.0;
141 //vargamma_mtx[4*vargamma_mtx.stride + dim-1] = 0.0;
142 
143 //vargamma_mtx[5*vargamma_mtx.stride + dim-2] = 0.0;
144 //vargamma_mtx[5*vargamma_mtx.stride + dim-1] = 0.0;
145 
146 //vargamma_mtx[6*vargamma_mtx.stride + dim-1] = 0.0;
147 */
148 
149  Matrix_real T2(1,1);
150  T2[0] = 1.0;
151 
152  // spawn iterations to construct dim x dim orthogonal matrix
153  Matrix_real Tn = T2;
154  for (int ndx=2; ndx<=dim; ndx++) {
155 
156  // preallocate matrix for the new T
157  Matrix_real Tn_new(ndx, ndx);
158 
159  // construct matrix tn from Eq (6) of https://doi.org/10.1002/qua.560040725
160  Matrix_real tn(ndx, ndx);
161  memset( tn.get_data(), 0, tn.size()*sizeof(double) );
162  for ( int row_idx=0; row_idx<ndx-1; row_idx++) {
163  memcpy( tn.get_data()+row_idx*tn.stride, Tn.get_data() + row_idx*Tn.stride, (ndx-1)*sizeof(double) );
164  }
165  tn[ndx*tn.stride -1] = 1.0;
166 
167  // construct matrix Tn from Eq (14) in https://doi.org/10.1002/qua.560040725
168  for ( int col_idx=0; col_idx<ndx; col_idx++) {
169 
170  // allocate a column in matrix s defined by Eq (15)
171  Matrix_real sl(ndx, 1);
172 
173  // k = 0 case of Eq (16)
174  sl[0] = -tn[col_idx*tn.stride + ndx-1]; // Eq (16)
175 
176  // k = 0 case in Eq (14)
177  Tn_new[col_idx] = tn[col_idx]*cos(vargamma_mtx[ndx-1]) - sl[0]*sin(vargamma_mtx[ndx-1]);
178 
179  // k > 0 case in Eq (14), (15)
180  for ( int row_idx=1; row_idx<ndx; row_idx++) {
181 
182  int kdx = row_idx-1;
183  sl[row_idx] = tn[kdx*tn.stride+col_idx] * sin(vargamma_mtx[kdx*dim+ndx-1]) + sl[kdx] * cos(vargamma_mtx[kdx*dim+ndx-1]);
184 
185  if ( row_idx == ndx-1 ) {
186  Tn_new[row_idx*Tn_new.stride + col_idx] = - sl[row_idx];
187  }
188  else {
189  Tn_new[row_idx*Tn_new.stride + col_idx] = tn[row_idx*tn.stride + col_idx] * cos(vargamma_mtx[row_idx*dim+ndx-1]) - sl[row_idx] * sin(vargamma_mtx[row_idx*dim+ndx-1]);
190  }
191 
192  }
193 /*
194 std::cout << "sl" << std::endl;
195 sl.print_matrix();
196 */
197  }
198 
199  Tn = Tn_new;
200 
201  }
202 
203 //Tn.print_matrix();
204  Matrix ret(Tn.rows, Tn.cols);
205  for ( int idx=0; idx<ret.size(); idx++) {
206  ret[idx].real = Tn[idx];
207  ret[idx].imag = 0.0;
208  }
209 
210  return ret;
211 
212 
213 
214 }
215 
216 
224 
225  if (vargamma.size() != dim*(dim-1)/2) {
226  throw std::string("Wrong number of parameters in Random_Orthogonal::Construct_Orthogonal_Matrix(float32)");
227  }
228 
229  // construct vargamma matrix elements
230  Matrix_real_float vargamma_mtx(dim, dim);
231  memset( vargamma_mtx.get_data(), 0, vargamma_mtx.size()*sizeof(float) );
232  int gamma_index = 0;
233  for (int idx=0; idx<dim; idx++) {
234  for (int jdx=idx+1; jdx<dim; jdx++) {
235  vargamma_mtx[idx*vargamma_mtx.stride + jdx] = vargamma[gamma_index];
236  gamma_index++;
237  }
238  }
239 
240  Matrix_real_float T2(1,1);
241  T2[0] = 1.0f;
242 
243  // spawn iterations to construct dim x dim orthogonal matrix
244  Matrix_real_float Tn = T2;
245  for (int ndx=2; ndx<=dim; ndx++) {
246 
247  // preallocate matrix for the new T
248  Matrix_real_float Tn_new(ndx, ndx);
249 
250  // construct matrix tn from Eq (6) of https://doi.org/10.1002/qua.560040725
251  Matrix_real_float tn(ndx, ndx);
252  memset( tn.get_data(), 0, tn.size()*sizeof(float) );
253  for ( int row_idx=0; row_idx<ndx-1; row_idx++) {
254  memcpy( tn.get_data()+row_idx*tn.stride, Tn.get_data() + row_idx*Tn.stride, (ndx-1)*sizeof(float) );
255  }
256  tn[ndx*tn.stride -1] = 1.0f;
257 
258  // construct matrix Tn from Eq (14) in https://doi.org/10.1002/qua.560040725
259  // Pre-compute sincos for the k=0 angle (constant across all col_idx)
260  float c0_gamma, s0_gamma;
261  qgd_sincos<float>(vargamma_mtx[ndx-1], &s0_gamma, &c0_gamma);
262  for ( int col_idx=0; col_idx<ndx; col_idx++) {
263 
264  // allocate a column in matrix s defined by Eq (15)
265  Matrix_real_float sl(ndx, 1);
266 
267  // k = 0 case of Eq (16)
268  sl[0] = -tn[col_idx*tn.stride + ndx-1];
269 
270  // k = 0 case in Eq (14)
271  Tn_new[col_idx] = tn[col_idx]*c0_gamma - sl[0]*s0_gamma;
272 
273  // k > 0 case in Eq (14), (15)
274  for ( int row_idx=1; row_idx<ndx; row_idx++) {
275 
276  int kdx = row_idx-1;
277  float c_k, s_k;
278  qgd_sincos<float>(vargamma_mtx[kdx*dim+ndx-1], &s_k, &c_k);
279  sl[row_idx] = tn[kdx*tn.stride+col_idx] * s_k + sl[kdx] * c_k;
280 
281  if ( row_idx == ndx-1 ) {
282  Tn_new[row_idx*Tn_new.stride + col_idx] = -sl[row_idx];
283  }
284  else {
285  float c_r, s_r;
286  qgd_sincos<float>(vargamma_mtx[row_idx*dim+ndx-1], &s_r, &c_r);
287  Tn_new[row_idx*Tn_new.stride + col_idx] = tn[row_idx*tn.stride + col_idx] * c_r - sl[row_idx] * s_r;
288  }
289 
290  }
291  }
292 
293  Tn = Tn_new;
294 
295  }
296 
297  Matrix_float ret(Tn.rows, Tn.cols);
298  memset( ret.get_data(), 0, ret.size()*sizeof(QGD_Complex8) );
299  for ( int idx=0; idx<ret.size(); idx++) {
300  ret[idx].real = Tn[idx];
301  }
302 
303  return ret;
304 
305 }
306 
void qgd_sincos< float >(float x, float *s, float *c)
Definition: qgd_math.h:106
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
Class to store single-precision real arrays and properties.
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)
Definition: matrix_base.hpp:46
Random_Orthogonal(int dim_in)
Constructor of the class.
Structure type representing single-precision complex numbers.
Definition: QGDTypes.h:46
Header file for a class containing basic methods for setting up the verbosity level.
scalar * get_data() const
Call to get the pointer to the stored data.
int rows
The number of rows.
Definition: matrix_base.hpp:42
int cols
The number of columns.
Definition: matrix_base.hpp:44
#define M_PI
Definition: qgd_math.h:42
Umtx
The unitary to be decomposed.
Definition: example.py:53
Matrix Construct_Orthogonal_Matrix()
Call to create a random unitary.
Double-precision complex matrix (float64).
Definition: matrix.h:38
int size() const
Call to get the number of the allocated elements.
int dim
The number of rows in the created unitary.
Single-precision complex matrix (float32).
Definition: matrix_float.h:41
Class to store data of complex arrays and its properties.
Definition: matrix_real.h:41