Sequential Quantum Gate Decomposer  v1.9.3
Powerful decomposition of general unitarias into one- and two-qubit gates gates
example_QX2_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 
41  # creating an instance of the wrapper class Circuit
42  Circuit_ret = Circuit( qbit_num )
43 
44 
45 
46  disentangle_qbit = qbit_num - 1
47 
48 
49 
50 
51  for qbit in range(0, disentangle_qbit ):
52 
53 
55  Layer = Circuit( qbit_num )
56 
57 
58  if qbit == 0:
59 
60  # add U3 gate to the block
61  Theta = True
62  Phi = False
63  Lambda = True
64  Layer.add_U3( 0, Theta, Phi, Lambda )
65  Layer.add_U3( disentangle_qbit, Theta, Phi, Lambda )
66 
67  # add CNOT gate to the block
68  Layer.add_CNOT( 0, disentangle_qbit)
69 
70  elif qbit == 1:
71 
72 
74  Theta = True
75  Phi = False
76  Lambda = True
77  Layer.add_U3( 0, Theta, Phi, Lambda )
78  Layer.add_U3( 1, Theta, Phi, Lambda )
79 
80  # add CNOT gate to the block
81  Layer.add_CNOT( 0, 1)
82 
83 
84 
85  elif qbit == 2:
86 
87  # add U3 gate to the block
88  Theta = True
89  Phi = False
90  Lambda = True
91  Layer.add_U3( 2, Theta, Phi, Lambda )
92  Layer.add_U3( disentangle_qbit, Theta, Phi, Lambda )
93 
94  # add CNOT gate to the block
95  Layer.add_CNOT( 2, disentangle_qbit )
96 
97 
98 
99  Circuit_ret.add_Circuit( Layer )
100 
101 
102 
103  return Circuit_ret
104 
105 
106 
107 from squander import N_Qubit_Decomposition
108 
109 
111 qbit_num = 4
112 
113 
114 
116 matrix_size = int(2**qbit_num)
117 
118 # creating a random unitary to be decomposed
119 Umtx = unitary_group.rvs(matrix_size)
120 
121 
122 
124 decomp = N_Qubit_Decomposition( Umtx.conj().T )
125 
126 
127 
129 reordered_qbits = (0,1,3,2)
130 
131 # adding custom gate structure to the decomposition
132 decomp.Reorder_Qubits( reordered_qbits )
133 
134 
135 
138 
139 
140 # adding custom gate structure to the decomposition
141 decomp.set_Gate_Structure( gate_structure )
142 
143 
144 
146 decomp.set_Max_Layer_Num( {4: 60, 3:16} )
147 
148 
149 
151 decomp.set_Optimization_Blocks( 20 )
152 
153 
154 
156 decomp.Start_Decomposition()
157 
158 
159 
161 revert_qbits = (1,0,2,3)
162 
163 # adding custom gate structure to the decomposition
164 decomp.Reorder_Qubits( revert_qbits )
165 
166 
167 
169 decomp.List_Gates()
170 
171 
172 
174 quantum_circuit = decomp.get_Qiskit_Circuit()
175 
176 
177 import numpy.linalg as LA
178 
179 # the unitary matrix from the result object
180 decomposed_matrix = utils.get_unitary_from_qiskit_circuit( quantum_circuit )
181 product_matrix = np.dot(Umtx,decomposed_matrix.conj().T)
182 phase = np.angle(product_matrix[0,0])
183 product_matrix = product_matrix*np.exp(-1j*phase)
184 
185 product_matrix = np.eye(matrix_size)*2 - product_matrix - product_matrix.conj().T
186 # the error of the decomposition
187 decomposition_error = (np.real(np.trace(product_matrix)))/2
188 
189 print('The error of the decomposition is ' + str(decomposition_error))
190 
191 
192 
193 
194 
195