Sequential Quantum Gate Decomposer  v1.9.7
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  Layer.add_U3( 0 )
62  Layer.add_U3( disentangle_qbit )
63 
64  # add CNOT gate to the block
65  Layer.add_CNOT( 0, disentangle_qbit)
66 
67  elif qbit == 1:
68 
69 
71  Layer.add_U3( 0 )
72  Layer.add_U3( 1 )
73 
74  # add CNOT gate to the block
75  Layer.add_CNOT( 0, 1)
76 
77 
78 
79  elif qbit == 2:
80 
81  # add U3 gate to the block
82  Layer.add_U3( 2 )
83  Layer.add_U3( disentangle_qbit )
84 
85  # add CNOT gate to the block
86  Layer.add_CNOT( 2, disentangle_qbit )
87 
88 
89 
90  Circuit_ret.add_Circuit( Layer )
91 
92 
93 
94  return Circuit_ret
95 
96 
97 
98 from squander import N_Qubit_Decomposition
99 
100 
102 qbit_num = 4
103 
104 
105 
107 matrix_size = int(2**qbit_num)
108 
109 # creating a random unitary to be decomposed
110 Umtx = unitary_group.rvs(matrix_size)
111 
112 
113 
115 decomp = N_Qubit_Decomposition( Umtx.conj().T )
116 
117 
118 
120 reordered_qbits = (0,1,3,2)
121 
122 # adding custom gate structure to the decomposition
123 decomp.Reorder_Qubits( reordered_qbits )
124 
125 
126 
129 
130 
131 # adding custom gate structure to the decomposition
132 decomp.set_Gate_Structure( gate_structure )
133 
134 
135 
137 decomp.set_Max_Layer_Num( {4: 60, 3:16} )
138 
139 
140 
142 decomp.set_Optimization_Blocks( 20 )
143 
144 
145 
147 decomp.Start_Decomposition()
148 
149 
150 
152 revert_qbits = (1,0,2,3)
153 
154 # adding custom gate structure to the decomposition
155 decomp.Reorder_Qubits( revert_qbits )
156 
157 
158 
160 decomp.List_Gates()
161 
162 
163 
165 quantum_circuit = decomp.get_Qiskit_Circuit()
166 
167 
168 import numpy.linalg as LA
169 
170 # the unitary matrix from the result object
171 decomposed_matrix = utils.get_unitary_from_qiskit_circuit( quantum_circuit )
172 product_matrix = np.dot(Umtx,decomposed_matrix.conj().T)
173 phase = np.angle(product_matrix[0,0])
174 product_matrix = product_matrix*np.exp(-1j*phase)
175 
176 product_matrix = np.eye(matrix_size)*2 - product_matrix - product_matrix.conj().T
177 # the error of the decomposition
178 decomposition_error = (np.real(np.trace(product_matrix)))/2
179 
180 print('The error of the decomposition is ' + str(decomposition_error))
181 
182 
183 
184 
185 
186