Sequential Quantum Gate Decomposer  v1.9.3
Powerful decomposition of general unitarias into one- and two-qubit gates gates
UN.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 */
24 #include "UN.h"
25 #include "common.h"
26 #include "Random_Unitary.h"
27 #include "dot.h"
28 
29 
30 
31 
36 UN::UN() {
37 
38  // A string labeling the gate operation
39  name = "UN";
40 
41  // number of qubits spanning the matrix of the operation
42  qbit_num = -1;
43  // The size N of the NxN matrix associated with the operations.
44  matrix_size = -1;
45  // The type of the operation (see enumeration gate_type)
47  // The index of the qubit on which the operation acts (target_qbit >= 0)
48  target_qbit = -1;
49  // The index of the qubit which acts as a control qubit (control_qbit >= 0) in controlled operations
50  control_qbit = -1;
51  // the number of free parameters of the operation
52  parameter_num = 0;
53 }
54 
55 
56 
62 UN::UN(int qbit_num_in) {
63 
64  // A string labeling the gate operation
65  name = "UN";
66  // number of qubits spanning the matrix of the operation
67  qbit_num = qbit_num_in;
68  // the size of the matrix
70  // A string describing the type of the operation
72  // The index of the qubit on which the operation acts (target_qbit >= 0)
73  target_qbit = -1;
74  // The index of the qubit which acts as a control qubit (control_qbit >= 0) in controlled operations
75  control_qbit = -1;
76  // The number of parameters
77  parameter_num = 0;
78 }
79 
80 
85 }
86 
91 void UN::set_qbit_num( int qbit_num_in ) {
92  // setting the number of qubits
93  qbit_num = qbit_num_in;
94 
95  // update the size of the matrix
97 
98  // Update the number of the parameters
100 
101 
102 }
103 
104 
110 Matrix
112 
113 
114  return get_matrix( parameters, false );
115 }
116 
117 
124 Matrix
126 
127  Matrix UN_matrix = create_identity(matrix_size);
128  apply_to(parameters, UN_matrix, parallel);
129 
130 #ifdef DEBUG
131  if (UN_matrix.isnan()) {
132  std::stringstream sstream;
133  sstream << "U3::get_matrix: UN_matrix contains NaN." << std::endl;
134  print(sstream, 1);
135  }
136 #endif
137 
138  return UN_matrix;
139 }
140 
141 
147 void
148 UN::apply_to( Matrix_real& parameters, Matrix& input, int parallel ) {
149 
150  if (input.rows != matrix_size ) {
151  std::string err("UN::apply_to: Wrong input size in UN gate apply");
152  throw(err);
153  }
154 
155  if (parameters.size() < parameter_num) {
156  std::stringstream sstream;
157  sstream << "Not enough parameters given for the UN gate" << std::endl;
158  print(sstream, 0);
159  exit(-1);
160  }
161 
162 
163  Matrix &&Umtx = get_submatrix( parameters );
164 
165  // get horizontal strided blocks of the input matrix
166  Matrix Block0 = Matrix( input.get_data(), input.rows/2, input.cols, input.stride );
167  Matrix Block1 = Matrix( input.get_data()+input.rows/2*input.stride, input.rows/2, input.cols, input.stride );
168 
169  // get the transformation of the blocks
170  Matrix Transformed_Block0 = dot( Umtx, Block0 );
171  Matrix Transformed_Block1 = dot( Umtx, Block1 );
172 
173  // put back the transformed data into input
174  memcpy( input.get_data(), Transformed_Block0.get_data(), Transformed_Block0.size()*sizeof(QGD_Complex16) );
175  memcpy( input.get_data()+input.rows/2*input.stride, Transformed_Block1.get_data(), Transformed_Block0.size()*sizeof(QGD_Complex16) );
176 
177 
178 }
179 
180 
185 void
187 
188  if (input.rows != matrix_size ) {
189  std::stringstream sstream;
190  sstream << "Wrong matrix size in UN gate apply" << std::endl;
191  print(sstream, 0);
192  exit(-1);
193  }
194 
195  if (parameters.size() < parameter_num) {
196  std::stringstream sstream;
197  sstream << "Not enough parameters given for the UN gate" << std::endl;
198  print(sstream, 0);
199  exit(-1);
200  }
201 
202  Matrix &&Umtx = get_submatrix( parameters );
203 
204 
205  // get vertical strided blocks of the input matrix
206  Matrix Block0 = Matrix( input.get_data(), input.rows, input.cols/2, input.stride );
207  Matrix Block1 = Matrix( input.get_data()+input.cols/2, input.rows, input.cols/2, input.stride );
208 
209  // get the transformation of the blocks
210  Matrix Transformed_Block0 = dot( Block0, Umtx );
211  Matrix Transformed_Block1 = dot( Block1, Umtx );
212 
213  // put back the transformed data into input
214  for (int row_idx=0; row_idx<input.rows; row_idx++) {
215  memcpy( input.get_data()+row_idx*input.stride, Transformed_Block0.get_data() + row_idx*Transformed_Block0.stride, Transformed_Block0.cols*sizeof(QGD_Complex16) );
216  memcpy( input.get_data()+row_idx*input.stride + input.cols/2, Transformed_Block1.get_data() + row_idx*Transformed_Block1.stride, Transformed_Block1.cols*sizeof(QGD_Complex16) );
217  }
218 }
219 
220 
221 
225 Matrix
227 
228  // create array of random parameters to construct random unitary
229  int matrix_size_loc = matrix_size/2;
230  double* vartheta = parameters.get_data();
231  double* varphi = parameters.get_data() + matrix_size_loc*(matrix_size_loc-1)/2;
232  double* varkappa = parameters.get_data() + matrix_size_loc*(matrix_size_loc-1);
233 
234  Random_Unitary ru( matrix_size_loc );
235  Matrix Umtx = ru.Construct_Unitary_Matrix( vartheta, varphi, varkappa );
236 
237  return Umtx;
238 
239 }
240 
241 
246 void UN::reorder_qubits( std::vector<int> qbit_list ) {
247 
248  // check the number of qubits
249  if ((int)qbit_list.size() != qbit_num ) {
250  std::stringstream sstream;
251  sstream << "Wrong number of qubits" << std::endl;
252  print(sstream, 0);
253  }
254 
255 
256  int control_qbit_new = control_qbit;
257  int target_qbit_new = target_qbit;
258 
259  // setting the new value for the target qubit
260  for (int idx=0; idx<qbit_num; idx++) {
261  if (target_qbit == qbit_list[idx]) {
262  target_qbit_new = qbit_num-1-idx;
263  }
264  if (control_qbit == qbit_list[idx]) {
265  control_qbit_new = qbit_num-1-idx;
266  }
267  }
268 
269  control_qbit = control_qbit_new;
270  target_qbit = target_qbit_new;
271 }
272 
277 void
279 
280  parameters = parameters_.copy();
281 
282 }
283 
284 
289 
290  return parameters.copy();
291 
292 }
293 
298 int
300  return parameter_num;
301 }
302 
303 
309  return type;
310 }
311 
312 
318  return qbit_num;
319 }
320 
321 
327 
328  UN* ret = new UN( qbit_num );
329 
330  if ( parameters.size() > 0 ) {
332  }
333 
335  ret->set_parents( parents );
336  ret->set_children( children );
337 
338  return ret;
339 
340 }
341 
342 
343 
std::vector< Gate * > parents
list of parent gates to be applied in the circuit prior to this current gate
Definition: Gate.h:95
bool isnan()
Call to check the array for NaN entries.
Definition: matrix.cpp:128
Matrix dot(Matrix &A, Matrix &B)
Call to calculate the product of two complex matrices by calling method zgemm3m from the CBLAS librar...
Definition: dot.cpp:38
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
virtual ~UN()
Destructor of the class.
Definition: UN.cpp:84
Matrix_real get_optimized_parameters()
Call to get the final optimized parameters of the gate.
Definition: UN.cpp:288
virtual Matrix get_matrix()
Call to retrieve the operation matrix.
Definition: Gate.cpp:129
Matrix_real parameters
Parameters theta, phi, lambda of the U3 gate after the decomposition of the unitary is done...
Definition: UN.h:41
UN()
Default constructor of the class.
Definition: UN.cpp:36
Matrix_real copy() const
Call to create a copy of the matrix.
int control_qbit
The index of the qubit which acts as a control qubit (control_qbit >= 0) in controlled operations...
Definition: Gate.h:87
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
void set_children(std::vector< Gate *> &children_)
Call to set the children of the current gate.
Definition: Gate.cpp:802
virtual void set_qbit_num(int qbit_num_in)
Set the number of qubits spanning the matrix of the operation.
Definition: UN.cpp:91
virtual void reorder_qubits(std::vector< int > qbit_list)
Call to reorder the qubits in the matrix of the operation.
Definition: UN.cpp:246
int target_qbit
The index of the qubit on which the operation acts (target_qbit >= 0)
Definition: Gate.h:85
void apply_from_right(Matrix_real &parameters, Matrix &input)
Call to apply the gate on the input array/matrix by input*Gate.
Definition: UN.cpp:186
UN * clone()
Call to create a clone of the present class.
Definition: UN.cpp:326
int matrix_size
The size N of the NxN matrix associated with the operations.
Definition: Gate.h:89
scalar * get_data() const
Call to get the pointer to the stored data.
int get_parameter_num()
Call to get the number of free parameters.
Definition: UN.cpp:299
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
Umtx
The unitary to be decomposed.
Definition: example.py:53
Header file for a class for the representation of general gate operations on the first qbit_num-1 qub...
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
Structure type representing complex numbers in the SQUANDER package.
Definition: QGDTypes.h:38
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
int size() const
Call to get the number of the allocated elements.
A class to cerate general random unitary matrix according to arXiv:1303:5904v1.
std::string name
A string labeling the gate operation.
Definition: Gate.h:79
void apply_to(Matrix_real &parameters, Matrix &input, int parallel)
Call to apply the gate on the input array/matrix.
Definition: UN.cpp:148
std::vector< Gate * > children
list of child gates to be applied after this current gate
Definition: Gate.h:97
void set_optimized_parameters(Matrix_real parameters_)
Call to set the final optimized parameters of the gate.
Definition: UN.cpp:278
Base class for the representation of general gate operations.
Definition: UN.h:35
Matrix create_identity(int matrix_size)
Call to create an identity matrix.
Definition: common.cpp:164
int parameter_num
the number of free parameters of the operation
Definition: Gate.h:91
Matrix get_submatrix(Matrix_real &parameters)
Call to retrieve the qbit_num-1 kernel of the UN gate.
Definition: UN.cpp:226
Header file for commonly used functions and wrappers to CBLAS functions.
gate_type get_type()
Call to get the type of the operation.
Definition: UN.cpp:308
void set_parents(std::vector< Gate *> &parents_)
Call to set the parents of the current gate.
Definition: Gate.cpp:790
int qbit_num
number of qubits spanning the matrix of the operation
Definition: Gate.h:81
int get_qbit_num()
Call to get the number of qubits composing the unitary.
Definition: UN.cpp:317
gate_type
Type definition of operation types (also generalized for decomposition classes derived from the class...
Definition: Gate.h:34
Class to store data of complex arrays and its properties.
Definition: matrix_real.h:39