Sequential Quantum Gate Decomposer  v1.9.6
Powerful decomposition of general unitarias into one- and two-qubit gates gates
custom_gate_structure_test.cpp
Go to the documentation of this file.
1 
2 /*
3 Created on Fri Jun 26 14:14:12 2020
4 Copyright 2020 Peter Rakyta, Ph.D.
5 
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9 
10  http://www.apache.org/licenses/LICENSE-2.0
11 
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see http://www.gnu.org/licenses/.
20 
21 @author: Peter Rakyta, Ph.D.
22 */
27 #include <iostream>
28 #include <stdio.h>
29 #include <map>
30 
31 
33 #include "common.h"
34 #include "N_Qubit_Decomposition.h"
35 #include "Random_Unitary.h"
36 #include "logging.h"
38 
39 using namespace std;
40 
41 
42 
49 
51  // creating an instance of the wrapper class Gates_block
52  Gates_block* gates_block = new Gates_block( qbit_num );
54 
56  int disentangle_qubit = qbit_num - 1;
58 
59 
61  for ( int qbit=0; qbit< disentangle_qubit; qbit++ ) {
62 
63  // creating an instance of the wrapper class Gates_block
64  Gates_block* layer = new Gates_block( qbit_num );
65 
66  if (qbit == 1) {
67 
68  int target_qbit = 0;
69  int control_qbit = 1;
70 
71  // add U3 gate to the block
72  layer->add_u3( 0 );
73  layer->add_u3( 1 );
74 
75  // add CNOT gate to the block
76  layer->add_cnot( target_qbit, control_qbit );
77 
78 
79  }
80  else {
81 
82  int target_qbit = qbit;
83  int control_qbit = disentangle_qubit;
84 
85  // add U3 gate to the block
86  layer->add_u3( qbit );
87  layer->add_u3( disentangle_qubit );
88 
89  // add CNOT gate to the block
90  layer->add_cnot( target_qbit, control_qbit );
91  }
92 
93  gates_block->add_gate( (Gate*)layer );
94 
95  }
97 
98  return gates_block;
99 
100 
101 }
102 
106 int main() {
107 
108 
109 
111  std::stringstream sstream;
112 
114  logging output;
115 
117  int verbose_level;
118 
119  //Setting the verbosity level of the Test of N qubit decomposition with custom gate structure
120  verbose_level=1;
121  sstream << std::endl << std::endl << "****************************************" << std::endl;
122  sstream << "Test of N qubit decomposition with custom gate structure" << std::endl;
123  sstream << "****************************************"<< std::endl << std::endl << std::endl;
124  output.print(sstream,verbose_level);
125 
127  // The number of qubits spanning the random unitary
128  int qbit_num = 3;
129  // the number of rows of the random unitary
130  int matrix_size = Power_of_2(qbit_num);
131  // creating class to generate general random unitary
132  Random_Unitary ru = Random_Unitary(matrix_size);
133  // create general random unitary
135 
136 
137 
138 
139  // construct the complex transpose of the random unitary
140  Matrix Umtx_adj = Matrix(matrix_size, matrix_size);
141  for (int element_idx=0; element_idx<matrix_size*matrix_size; element_idx++) {
142  // determine the row and column index of the element to be filled.
143  int col_idx = element_idx % matrix_size;
144  int row_idx = int((element_idx-col_idx)/matrix_size);
145 
146  // setting the complex conjugate of the element in the adjungate matrix
147  QGD_Complex16 element = Umtx[col_idx*matrix_size + row_idx];
148  Umtx_adj[element_idx].real = element.real;
149  Umtx_adj[element_idx].imag = -element.imag;
150  }
152 
154  // create empty configuration map
155  std::map<std::string, Config_Element> config;
156 
157  // creating the class for the decomposition. Here Umtx_adj is the complex transposition of unitary Umtx
158  N_Qubit_Decomposition cDecomposition(
159  Umtx_adj,
160  qbit_num,
161  /* optimize_layer_num= */ false,
162  config,
163  /* initial_guess= */ RANDOM
164  );
166 
167 
168 
170  // creating custom gate structure for the decomposition
171  std::map<int, Gates_block*> gate_structure;
172  gate_structure.insert( pair<int, Gates_block*>(qbit_num, create_custom_gate_structure( qbit_num ) ) );
173  gate_structure.insert( pair<int, Gates_block*>(qbit_num-1, create_custom_gate_structure( qbit_num-1 ) ) );
174 
175  // setting the custom gate structure in the decomposition class
176  cDecomposition.set_custom_gate_structure( gate_structure);
177 
178  // release the custom gate structure since it was cloned by cDecomposition
179  delete gate_structure[qbit_num];
180  delete gate_structure[qbit_num-1];
182 
183 
184  // setting the verbosity level of the decomposition
185  verbose_level=1;
186  sstream << "Starting the decompsition" << std::endl;
187  output.print(sstream,verbose_level);
188 
190  // starting the decomposition
191  cDecomposition.start_decomposition(/* finalize_decomposition = */ true /*, prepare_export? = true*/ );
192 
193  cDecomposition.list_gates(1);
195 
196 
197 
198 
199  return 0;
200 
201 };
202 
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
void add_gate(Gate *gate)
Append a general gate to the list of gates.
Gates_block * create_custom_gate_structure(int qbit_num)
Function to create custom gate structure for the decomposition.
void add_cnot(int target_qbit, int control_qbit)
Append a CNOT gate gate to the list of gates.
Header file for a class containing basic methods for setting up the verbosity level.
A class containing basic methods for setting up the verbosity level.
Definition: logging.h:43
matrix_size
[load Umtx]
Definition: example.py:58
Umtx
The unitary to be decomposed.
Definition: example.py:53
void add_u3(int target_qbit)
Append a U3 gate to the list of gates.
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:136
Double-precision complex matrix (float64).
Definition: matrix.h:38
dictionary config
int main()
Decomposition of general random unitary matrix into a custom structure of U3 and CNOT gates...
A class responsible for grouping two-qubit (CNOT,CZ,CH) and one-qubit gates into layers.
Definition: Gates_block.h:44
A class to create general random unitary matrices according to arXiv:1303.5904v1. ...
Header file for commonly used functions and wrappers to CBLAS functions.
double real
the real part of a complex number
Definition: QGDTypes.h:40
Matrix Construct_Unitary_Matrix()
Construct a random unitary with internally generated float64 parameters.
Header file for a class to determine the decomposition of an N-qubit unitary into a sequence of CNOT ...
double imag
the imaginary part of a complex number
Definition: QGDTypes.h:42