Sequential Quantum Gate Decomposer  v1.9.3
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 "logging.h"
29 
30 
31 
38 
39  if (dim_in < 2) {
40  throw "wrong dimension";
41  }
42 
43  // number of qubits
44  dim = dim_in;
45 
46 }
47 
48 
53 Matrix
55 
56  // create array of random parameters to construct random unitary
57  Matrix_real vargamma(1, dim*(dim-1)/2 );
58 
59 
60  // initialize random seed:
61  srand (time(NULL));
62 
63  for (int idx=0; idx<dim*(dim-1)/2; idx++) {
64  vargamma[idx] = (2*double(rand())/double(RAND_MAX)-1)*2*M_PI;
65  }
66  //vargamma[dim*(dim-1)/2-1] = 3.14159265359/2;
67 
69 
70 
71  return Umtx;
72 
73 }
74 
75 
83 Matrix
85 
86 //The stringstream input to store the output messages.
87 std::stringstream sstream;
88 
89 //Integer value to set the verbosity level of the output messages.
90 int verbose_level;
91 
92  if (vargamma.size() != dim*(dim-1)/2) {
93  sstream << "Wring number of parameters in Random_Orthogonal::Construct_Orthogonal_Matrix" << std::endl;
94  verbose_level=1;
95  print(sstream, verbose_level);
96  exit(-1);
97  }
98 
99  // construct vargamma matrix elements
100  Matrix_real vargamma_mtx(dim, dim);
101  memset( vargamma_mtx.get_data(), 0.0, vargamma_mtx.size()*sizeof(double) );
102  int gamma_index = 0;
103  for (int idx=0; idx<dim; idx++) {
104  for (int jdx=idx+1; jdx<dim; jdx++) {
105  vargamma_mtx[idx*vargamma_mtx.stride + jdx] = vargamma[gamma_index];
106  gamma_index++;
107  }
108  //vargamma_mtx[ idx*dim + idx ] = 3.14159265358979323846/2;
109  }
110 /*
111 //vargamma_mtx[0*vargamma_mtx.stride + dim-7] = 0.0;
112 //vargamma_mtx[0*vargamma_mtx.stride + dim-6] = 0.0;
113 //vargamma_mtx[0*vargamma_mtx.stride + dim-5] = 0.0;
114 vargamma_mtx[0*vargamma_mtx.stride + dim-4] = 0.0;
115 vargamma_mtx[0*vargamma_mtx.stride + dim-3] = 0.0;
116 vargamma_mtx[0*vargamma_mtx.stride + dim-2] = 0.0;
117 vargamma_mtx[0*vargamma_mtx.stride + dim-1] = 0.0;
118 
119 //vargamma_mtx[1*vargamma_mtx.stride + dim-6] = 0.0;
120 //vargamma_mtx[1*vargamma_mtx.stride + dim-5] = 0.0;
121 vargamma_mtx[1*vargamma_mtx.stride + dim-4] = 0.0;
122 vargamma_mtx[1*vargamma_mtx.stride + dim-3] = 0.0;
123 vargamma_mtx[1*vargamma_mtx.stride + dim-2] = 0.0;
124 vargamma_mtx[1*vargamma_mtx.stride + dim-1] = 0.0;
125 
126 
127 //vargamma_mtx[2*vargamma_mtx.stride + dim-5] = 0.0;
128 vargamma_mtx[2*vargamma_mtx.stride + dim-4] = 0.0;
129 vargamma_mtx[2*vargamma_mtx.stride + dim-3] = 0.0;
130 vargamma_mtx[2*vargamma_mtx.stride + dim-2] = 0.0;
131 vargamma_mtx[2*vargamma_mtx.stride + dim-1] = 0.0;
132 
133 vargamma_mtx[3*vargamma_mtx.stride + dim-4] = 0.0;
134 vargamma_mtx[3*vargamma_mtx.stride + dim-3] = 0.0;
135 vargamma_mtx[3*vargamma_mtx.stride + dim-2] = 0.0;
136 vargamma_mtx[3*vargamma_mtx.stride + dim-1] = 0.0;
137 
138 //vargamma_mtx[4*vargamma_mtx.stride + dim-3] = 0.0;
139 //vargamma_mtx[4*vargamma_mtx.stride + dim-2] = 0.0;
140 //vargamma_mtx[4*vargamma_mtx.stride + dim-1] = 0.0;
141 
142 //vargamma_mtx[5*vargamma_mtx.stride + dim-2] = 0.0;
143 //vargamma_mtx[5*vargamma_mtx.stride + dim-1] = 0.0;
144 
145 //vargamma_mtx[6*vargamma_mtx.stride + dim-1] = 0.0;
146 */
147 
148  Matrix_real T2(1,1);
149  T2[0] = 1.0;
150 
151  // spawn iterations to construct dim x dim orthogonal matrix
152  Matrix_real Tn = T2;
153  for (int ndx=2; ndx<=dim; ndx++) {
154 
155  // preallocate matrix for the new T
156  Matrix_real Tn_new(ndx, ndx);
157 
158  // construct matrix tn from Eq (6) of https://doi.org/10.1002/qua.560040725
159  Matrix_real tn(ndx, ndx);
160  memset( tn.get_data(), 0.0, tn.size()*sizeof(double) );
161  for ( int row_idx=0; row_idx<ndx-1; row_idx++) {
162  memcpy( tn.get_data()+row_idx*tn.stride, Tn.get_data() + row_idx*Tn.stride, (ndx-1)*sizeof(double) );
163  }
164  tn[ndx*tn.stride -1] = 1.0;
165 
166  // construct matrix Tn from Eq (14) in https://doi.org/10.1002/qua.560040725
167  for ( int col_idx=0; col_idx<ndx; col_idx++) {
168 
169  // allocate a column in matrix s defined by Eq (15)
170  Matrix_real sl(ndx, 1);
171 
172  // k = 0 case of Eq (16)
173  sl[0] = -tn[col_idx*tn.stride + ndx-1]; // Eq (16)
174 
175  // k = 0 case in Eq (14)
176  Tn_new[col_idx] = tn[col_idx]*cos(vargamma_mtx[ndx-1]) - sl[0]*sin(vargamma_mtx[ndx-1]);
177 
178  // k > 0 case in Eq (14), (15)
179  for ( int row_idx=1; row_idx<ndx; row_idx++) {
180 
181  int kdx = row_idx-1;
182  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]);
183 
184  if ( row_idx == ndx-1 ) {
185  Tn_new[row_idx*Tn_new.stride + col_idx] = - sl[row_idx];
186  }
187  else {
188  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]);
189  }
190 
191  }
192 /*
193 std::cout << "sl" << std::endl;
194 sl.print_matrix();
195 */
196  }
197 
198  Tn = Tn_new;
199 
200  }
201 
202 //Tn.print_matrix();
203  Matrix ret(Tn.rows, Tn.cols);
204  for ( int idx=0; idx<ret.size(); idx++) {
205  ret[idx].real = Tn[idx];
206  ret[idx].imag = 0.0;
207  }
208 
209  return ret;
210 
211 
212 
213 }
214 
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
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.
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
Umtx
The unitary to be decomposed.
Definition: example.py:53
Matrix Construct_Orthogonal_Matrix()
Call to create a random unitary.
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 dim
The number of rows in the created unitary.
Class to store data of complex arrays and its properties.
Definition: matrix_real.h:39