Sequential Quantum Gate Decomposer  v1.9.7
Powerful decomposition of general unitarias into one- and two-qubit gates gates
example_heavy_hex_general_unitary.py
Go to the documentation of this file.
1 # -*- coding: utf-8 -*-
2 """
3 Created on Fri Jun 26 14:42:56 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 @author: Peter Rakyta, Ph.D.
19 """
20 
22 
23 
24 
25 # cerate unitary q-bit matrix
26 from scipy.stats import unitary_group
27 from squander import utils
28 import numpy as np
29 
30 
31 
33  r"""
34  This method is called to create custom gate structure for the decomposition on IBM QX2
35 
36  """
37 
38  from squander import Circuit
39 
40  # creating an instance of the wrapper class Circuit
41  Circuit_ret = Circuit( qbit_num )
42 
43  disentangle_qubit = qbit_num - 1
44 
45 
46 
47  for qbit in range(0, disentangle_qubit ):
48 
49  # creating an instance of the wrapper class Circuit
50  Layer = Circuit( qbit_num )
51 
52 
53  if qbit == 0:
54 
55  # add U3 fate to the block
56  Layer.add_U3( 0 )
57  Layer.add_U3( disentangle_qubit )
58 
59  # add CNOT gate to the block
60  Layer.add_CNOT( 0, disentangle_qubit)
61 
62  elif qbit == 1:
63 
64  # add U3 fate to the block
65  Layer.add_U3( 0 )
66  Layer.add_U3( 1 )
67 
68  # add CNOT gate to the block
69  Layer.add_CNOT( 0, 1)
70 
71 
72 
73  elif qbit == 2:
74 
75  # add U3 fate to the block
76  Layer.add_U3( 2 )
77  Layer.add_U3( disentangle_qubit )
78 
79  # add CNOT gate to the block
80  Layer.add_CNOT( disentangle_qubit, 2 )
81 
82 
83 
84  Circuit_ret.add_Circuit( Layer )
85 
86  return Circuit_ret
87 
88 
89 
90 
91 
93  r"""
94  This method is called to create custom gate structure for the decomposition on IBM QX2
95 
96  """
97 
98  from squander import Circuit
99 
100  # creating an instance of the wrapper class Circuit
101  Circuit_ret = Circuit( qbit_num )
102 
103  disentangle_qubit = qbit_num - 1
104 
105 
106 
107  for qbit in range(0, disentangle_qubit ):
108 
109  # creating an instance of the wrapper class Circuit
110  Layer = Circuit( qbit_num )
111 
112 
113  if qbit == 0:
114 
115  # add U3 fate to the block
116  Layer.add_U3( 0 )
117  Layer.add_U3( disentangle_qubit )
118 
119  # add CNOT gate to the block
120  Layer.add_CNOT( 0, disentangle_qubit)
121 
122  elif qbit == 1:
123 
124  # add U3 fate to the block
125  Layer.add_U3( 0 )
126  Layer.add_U3( 1 )
127 
128  # add CNOT gate to the block
129  Layer.add_CNOT( 0, 1)
130 
131 
132 
133  elif qbit == 2:
134 
135  # add U3 fate to the block
136  Layer.add_U3( 2 )
137  Layer.add_U3( 0 )
138 
139  # add CNOT gate to the block
140  Layer.add_CNOT( 0, 2)
141 
142 
143 
144  Circuit_ret.add_Circuit( Layer )
145 
146  return Circuit_ret
147 
148 
149 
150 from squander import N_Qubit_Decomposition
151 
152 # the number of qubits spanning the unitary
153 qbit_num = 4
154 
155 # determine the soze of the unitary to be decomposed
156 matrix_size = int(2**qbit_num)
157 
158 # creating a random unitary to be decomposed
159 Umtx = unitary_group.rvs(matrix_size)
160 
161 # creating an instance of the C++ class
162 decomp = N_Qubit_Decomposition( Umtx.conj().T )
163 
164 
165 # create custom gate structure
167 
168 
169 # adding custom gate structure to the decomposition
170 decomp.set_Gate_Structure( gate_structure )
171 
172 
173 # set the maximal number of layers in the decomposition
174 decomp.set_Max_Layer_Num( {4: 60, 3:16} )
175 
176 # set the number of block to be optimized in one shot
177 decomp.set_Optimization_Blocks( 20 )
178 
179 # starting the decomposition
180 decomp.Start_Decomposition()
181 
182 
183 # list the decomposing operations
184 decomp.List_Gates()
185 
186 # get the decomposing operations
187 quantum_circuit = decomp.get_Qiskit_Circuit()
188 
189 
190 import numpy.linalg as LA
191 
192 # the unitary matrix from the result object
193 decomposed_matrix = utils.get_unitary_from_qiskit_circuit( quantum_circuit )
194 product_matrix = np.dot(Umtx,decomposed_matrix.conj().T)
195 phase = np.angle(product_matrix[0,0])
196 product_matrix = product_matrix*np.exp(-1j*phase)
197 
198 product_matrix = np.eye(matrix_size)*2 - product_matrix - product_matrix.conj().T
199 # the error of the decomposition
200 decomposition_error = (np.real(np.trace(product_matrix)))/2
201 
202 print('The error of the decomposition is ' + str(decomposition_error))