Sequential Quantum Gate Decomposer  v1.9.3
Powerful decomposition of general unitarias into one- and two-qubit gates gates
ON.cpp
Go to the documentation of this file.
1 /*
2 Created on Fri JON 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 "ON.h"
25 #include "common.h"
26 #include "Random_Orthogonal.h"
27 #include "dot.h"
28 
29 
30 
35 ON::ON() {
36 
37  // A string labeling the gate operation
38  name = "ON";
39 
40  // number of qubits spanning the matrix of the operation
41  qbit_num = -1;
42  // The size N of the NxN matrix associated with the operations.
43  matrix_size = -1;
44  // The type of the operation (see enumeration gate_type)
46  // The index of the qubit on which the operation acts (target_qbit >= 0)
47  target_qbit = -1;
48  // The index of the qubit which acts as a control qubit (control_qbit >= 0) in controlled operations
49  control_qbit = -1;
50  // the number of free parameters of the operation
51  parameter_num = 0;
52 }
53 
54 
55 
61 ON::ON(int qbit_num_in) {
62 
63  // A string labeling the gate operation
64  name = "ON";
65  // number of qubits spanning the matrix of the operation
66  qbit_num = qbit_num_in;
67  // the size of the matrix
69  // A string describing the type of the operation
71  // The index of the qubit on which the operation acts (target_qbit >= 0)
72  target_qbit = -1;
73  // The index of the qubit which acts as a control qubit (control_qbit >= 0) in controlled operations
74  control_qbit = -1;
75  // The number of parameters
76  parameter_num = 0;
77 }
78 
79 
84 }
85 
90 void ON::set_qbit_num( int qbit_num_in ) {
91  // setting the number of qubits
92  qbit_num = qbit_num_in;
93 
94  // update the size of the matrix
96 
97  // Update the number of the parameters
99 
100 
101 }
102 
103 
104 
110 Matrix
112 
113 
114 
115  return get_matrix( parameters, false );
116 }
117 
118 
119 
126 Matrix
128 
129 
130  Matrix ON_matrix = create_identity(matrix_size);
131  apply_to(parameters, ON_matrix, parallel);
132 
133 #ifdef DEBUG
134  if (ON_matrix.isnan()) {
135  std::stringstream sstream;
136  sstream << "U3::get_matrix: ON_matrix contains NaN." << std::endl;
137  print(sstream, 1);
138  }
139 #endif
140 
141  return ON_matrix;
142 }
143 
144 
150 void
151 ON::apply_to( Matrix_real& parameters, Matrix& input, int parallel ) {
152 
153  if (input.rows != matrix_size ) {
154  std::string err("ON::apply_to: Wrong input size in ON gate apply.");
155  throw err;
156  }
157 
158  if (parameters.size() < parameter_num) {
159  std::stringstream sstream;
160  sstream << "Not enough parameters given for the ON gate" << std::endl;
161  print(sstream, 1);
162  exit(-1);
163  }
164 
165 
166  Matrix &&Umtx = get_submatrix( parameters );
167 
168  // get horizontal strided blocks of the input matrix
169  Matrix Block0 = Matrix( input.get_data(), input.rows/2, input.cols, input.stride );
170  Matrix Block1 = Matrix( input.get_data()+input.rows/2*input.stride, input.rows/2, input.cols, input.stride );
171 
172  // get the transformation of the blocks
173  Matrix Transformed_Block0 = dot( Umtx, Block0 );
174  Matrix Transformed_Block1 = dot( Umtx, Block1 );
175 
176  // put back the transformed data into input
177  memcpy( input.get_data(), Transformed_Block0.get_data(), Transformed_Block0.size()*sizeof(QGD_Complex16) );
178  memcpy( input.get_data()+input.rows/2*input.stride, Transformed_Block1.get_data(), Transformed_Block0.size()*sizeof(QGD_Complex16) );
179 
180 
181 }
182 
183 
188 void
190 
191 
192  if (input.rows != matrix_size ) {
193  std::stringstream sstream;
194  sstream << "Wrong matrix size in ON gate apply" << std::endl;
195  print(sstream, 0);
196  exit(-1);
197  }
198 
199  if (parameters.size() < parameter_num) {
200  std::stringstream sstream;
201  sstream << "Not enough parameters given for the ON gate" << std::endl;
202  print(sstream, 0);
203  exit(-1);
204  }
205 
206  Matrix &&Umtx = get_submatrix( parameters );
207 
208 
209  // get vertical strided blocks of the input matrix
210  Matrix Block0 = Matrix( input.get_data(), input.rows, input.cols/2, input.stride );
211  Matrix Block1 = Matrix( input.get_data()+input.cols/2, input.rows, input.cols/2, input.stride );
212 
213  // get the transformation of the blocks
214  Matrix Transformed_Block0 = dot( Block0, Umtx );
215  Matrix Transformed_Block1 = dot( Block1, Umtx );
216 
217  // put back the transformed data into input
218  for (int row_idx=0; row_idx<input.rows; row_idx++) {
219  memcpy( input.get_data()+row_idx*input.stride, Transformed_Block0.get_data() + row_idx*Transformed_Block0.stride, Transformed_Block0.cols*sizeof(QGD_Complex16) );
220  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) );
221  }
222 }
223 
224 
225 
229 Matrix
231 
232  // create array of random parameters to construct random ONitary
233  int matrix_size_loc = matrix_size/2;
234 
235  Random_Orthogonal ro( matrix_size_loc );
236  Matrix Umtx = ro.Construct_Orthogonal_Matrix( parameters );
237 
238  return Umtx;
239 
240 }
241 
242 
247 void ON::reorder_qubits( std::vector<int> qbit_list ) {
248 
249 
250  // check the number of qubits
251  if ((int)qbit_list.size() != qbit_num ) {
252  std::stringstream sstream;
253  sstream << "Wrong number of qubits" << std::endl;
254  print(sstream, 0);
255  exit(-1);
256  }
257 
258 
259  int control_qbit_new = control_qbit;
260  int target_qbit_new = target_qbit;
261 
262  // setting the new value for the target qubit
263  for (int idx=0; idx<qbit_num; idx++) {
264  if (target_qbit == qbit_list[idx]) {
265  target_qbit_new = qbit_num-1-idx;
266  }
267  if (control_qbit == qbit_list[idx]) {
268  control_qbit_new = qbit_num-1-idx;
269  }
270  }
271 
272  control_qbit = control_qbit_new;
273  target_qbit = target_qbit_new;
274 }
275 
280 void
282 
283  parameters = parameters_.copy();
284 
285 }
286 
287 
292 
293  return parameters.copy();
294 
295 }
296 
301 int
303  return parameter_num;
304 }
305 
306 
312  return type;
313 }
314 
315 
321  return qbit_num;
322 }
323 
324 
330 
331  ON* ret = new ON( qbit_num );
332 
333  if ( parameters.size() > 0 ) {
335  }
336 
338  ret->set_parents( parents );
339  ret->set_children( children );
340 
341  return ret;
342 
343 }
344 
345 
346 
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
virtual void reorder_qubits(std::vector< int > qbit_list)
Call to reorder the qubits in the matrix of the operation.
Definition: ON.cpp:247
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
Matrix_real parameters
Parameters after the decomposition of the ONitary is done.
Definition: ON.h:41
virtual Matrix get_matrix()
Call to retrieve the operation matrix.
Definition: Gate.cpp:129
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
void apply_to(Matrix_real &parameters, Matrix &input, int parallel)
Call to apply the gate on the input array/matrix.
Definition: ON.cpp:151
int target_qbit
The index of the qubit on which the operation acts (target_qbit >= 0)
Definition: Gate.h:85
ON()
Default constructor of the class.
Definition: ON.cpp:35
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.
A class to cerate general random unitary matrix according to arXiv:1303:5904v1.
virtual void set_qbit_num(int qbit_num_in)
Set the number of qubits spanning the matrix of the operation.
Definition: ON.cpp:90
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
virtual ~ON()
Destructor of the class.
Definition: ON.cpp:83
Umtx
The unitary to be decomposed.
Definition: example.py:53
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
Matrix Construct_Orthogonal_Matrix()
Call to create a random unitary.
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
gate_type get_type()
Call to get the type of the operation.
Definition: ON.cpp:311
Structure type representing complex numbers in the SQUANDER package.
Definition: QGDTypes.h:38
Matrix get_submatrix(Matrix_real &parameters)
Call to retrieve the qbut_num-1 kernel of the operation.
Definition: ON.cpp:230
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 get_parameter_num()
Call to get the number of free parameters.
Definition: ON.cpp:302
int size() const
Call to get the number of the allocated elements.
std::string name
A string labeling the gate operation.
Definition: Gate.h:79
std::vector< Gate * > children
list of child gates to be applied after this current gate
Definition: Gate.h:97
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
Header file for commonly used functions and wrappers to CBLAS functions.
ON * clone()
Call to create a clone of the present class.
Definition: ON.cpp:329
void apply_from_right(Matrix_real &parameters, Matrix &input)
Call to apply the gate on the input array/matrix by input*Gate.
Definition: ON.cpp:189
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
Header file for a class for the representation of general gate operations on the first qbit_num-1 qub...
gate_type
Type definition of operation types (also generalized for decomposition classes derived from the class...
Definition: Gate.h:34
Base class for the representation of general gate operations.
Definition: ON.h:35
int get_qbit_num()
Call to get the number of qubits composing the ONitary.
Definition: ON.cpp:320
void set_optimized_parameters(Matrix_real parameters_)
Call to set the final optimized parameters of the gate.
Definition: ON.cpp:281
Class to store data of complex arrays and its properties.
Definition: matrix_real.h:39
Matrix_real get_optimized_parameters()
Call to get the final optimized parameters of the gate.
Definition: ON.cpp:291