Sequential Quantum Gate Decomposer  v1.9.3
Powerful decomposition of general unitarias into one- and two-qubit gates gates
test_Compression.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 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 """
23 
25 
26 
27 
28 # cerate unitary q-bit matrix
29 from scipy.stats import unitary_group
30 import numpy as np
31 from squander import utils
32 
33 
34 try:
35  from mpi4py import MPI
36  MPI_imported = True
37 except ModuleNotFoundError:
38  MPI_imported = False
39 
40 
41 
43  """This is a test class of the python iterface to the decompsition classes of the QGD package"""
44 
46  r"""
47  This method is called by pytest.
48  Test to decompose a 4-qubit unitary of the IBM chellenge
49 
50  """
51 
52  from squander import N_Qubit_Decomposition_adaptive
53  from scipy.io import loadmat
54 
55  # load the unitary from file
56  data = loadmat('data/Umtx.mat')
57  # The unitary to be decomposed
58  Umtx = data['Umtx']
59 
60  # generate config structure
61  config = { 'max_outer_iterations': 10,
62  'max_inner_iterations': 300000,
63  'max_inner_iterations_compression': 10000,
64  'max_inner_iterations_final': 1000,
65  'randomized_adaptive_layers': 1,
66  'export_circuit_2_binary': 1,
67  'optimization_tolerance': 1e-8 }
68 
69 
70 
71 
72  # creating a class to decompose the unitary
73  cDecompose = N_Qubit_Decomposition_adaptive( Umtx.conj().T, config=config )
74 
75 
76  # setting the verbosity of the decomposition
77  cDecompose.set_Verbose( 3 )
78 
79  # adding decomposing layers to the gate structure
80  levels = 2
81  for idx in range(levels):
82  cDecompose.add_Adaptive_Layers()
83 
84  cDecompose.add_Finalyzing_Layer_To_Gate_Structure()
85 
86 
87 
88  # starting the decomposition
89  cDecompose.get_Initial_Circuit()
90 
91  # compress the initial gate structure
92  cDecompose.Compress_Circuit()
93 
94  # finalize the gate structur (replace CRY gates with CNOT gates)
95  cDecompose.Finalize_Circuit()
96 
97  # list the decomposing operations
98  cDecompose.List_Gates()
99 
100  # get the decomposing operations
101  quantum_circuit = cDecompose.get_Qiskit_Circuit()
102 
103  # print the quantum circuit
104  print(quantum_circuit)
105 
106  import numpy.linalg as LA
107 
108  # the unitary matrix from the result object
109  decomposed_matrix = utils.get_unitary_from_qiskit_circuit( quantum_circuit )
110  product_matrix = np.dot(Umtx,decomposed_matrix.conj().T)
111  phase = np.angle(product_matrix[0,0])
112  product_matrix = product_matrix*np.exp(-1j*phase)
113 
114  product_matrix = np.eye(16)*2 - product_matrix - product_matrix.conj().T
115  # the error of the decomposition
116  decomposition_error = (np.real(np.trace(product_matrix)))/2
117 
118  print('The error of the decomposition is ' + str(decomposition_error))
119 
120  assert( decomposition_error < 1e-3 )
121 
122 
124  r"""
125  This method is called by pytest.
126  Test to decompose a 4-qubit unitary of the IBM chellenge
127 
128  """
129 
130  from squander import N_Qubit_Decomposition_adaptive
131  from scipy.io import loadmat
132 
133  # load the unitary from file
134  data = loadmat('data/Umtx.mat')
135  # The unitary to be decomposed
136  Umtx = data['Umtx']
137 
138  # generate config structure
139  config = { 'max_outer_iterations': 10,
140  'max_inner_iterations': 300000,
141  'max_inner_iterations_compression': 10000,
142  'max_inner_iterations_final': 1000,
143  'randomized_adaptive_layers': 1,
144  'export_circuit_2_binary': 1,
145  'optimization_tolerance': 1e-8 }
146 
147 
148  # creating a class to decompose the unitary
149  cDecompose = N_Qubit_Decomposition_adaptive( Umtx.conj().T, config=config )
150 
151 
152  # setting the verbosity of the decomposition
153  cDecompose.set_Verbose( 3 )
154 
155 
156  # adding decomposing layers to the gate structure
157  levels = 3
158  for idx in range(levels):
159  cDecompose.add_Adaptive_Layers()
160 
161  cDecompose.add_Finalyzing_Layer_To_Gate_Structure()
162 
163 
164  # starting the decomposition
165  cDecompose.get_Initial_Circuit()
166 
167  # finalize the gate structur (replace CRY gates with CNOT gates)
168  cDecompose.Finalize_Circuit()
169 
170  # list the decomposing operations
171  cDecompose.List_Gates()
172 
173  # get the decomposing operations
174  quantum_circuit = cDecompose.get_Qiskit_Circuit()
175 
176  # print the quantum circuit
177  print(quantum_circuit)
178 
179  import numpy.linalg as LA
180 
181  # the unitary matrix from the result object
182  decomposed_matrix = utils.get_unitary_from_qiskit_circuit( quantum_circuit )
183  product_matrix = np.dot(Umtx,decomposed_matrix.conj().T)
184  phase = np.angle(product_matrix[0,0])
185  product_matrix = product_matrix*np.exp(-1j*phase)
186 
187  product_matrix = np.eye(16)*2 - product_matrix - product_matrix.conj().T
188  # the error of the decomposition
189  decomposition_error = (np.real(np.trace(product_matrix)))/2
190 
191  print('The error of the decomposition is ' + str(decomposition_error))
192 
193  assert( decomposition_error < 1e-3 )
194 
195 
197  r"""
198  This method is called by pytest.
199  Test to decompose a 4-qubit unitary of the IBM chellenge
200 
201  """
202 
203  from squander import N_Qubit_Decomposition_adaptive
204  from scipy.io import loadmat
205 
206  # load the unitary from file
207  data = loadmat('data/Umtx.mat')
208  # The unitary to be decomposed
209  Umtx = data['Umtx']
210 
211 
212  # generate config structure
213  config = { 'max_outer_iterations': 10,
214  'max_inner_iterations': 300000,
215  'max_inner_iterations_compression': 10000,
216  'max_inner_iterations_final': 1000,
217  'randomized_adaptive_layers': 1,
218  'export_circuit_2_binary': 1,
219  'optimization_tolerance': 1e-8 }
220 
221 
222  # creating a class to decompose the unitary
223  cDecompose = N_Qubit_Decomposition_adaptive( Umtx.conj().T, config=config )
224 
225 
226  # setting the verbosity of the decomposition
227  cDecompose.set_Verbose( 3 )
228 
229 
230 
231  # importing circuit from a binary
232  cDecompose.set_Gate_Structure_From_Binary("circuit_squander.binary")
233 
234  # starting compression iterations
235  cDecompose.Compress_Circuit()
236 
237  # finalize the gate structur (replace CRY gates with CNOT gates)
238  cDecompose.Finalize_Circuit()
239 
240  # list the decomposing operations
241  cDecompose.List_Gates()
242 
243  # get the decomposing operations
244  quantum_circuit = cDecompose.get_Qiskit_Circuit()
245 
246  # print the quantum circuit
247  print(quantum_circuit)
248 
249  import numpy.linalg as LA
250 
251  # the unitary matrix from the result object
252  decomposed_matrix = utils.get_unitary_from_qiskit_circuit( quantum_circuit )
253  product_matrix = np.dot(Umtx,decomposed_matrix.conj().T)
254  phase = np.angle(product_matrix[0,0])
255  product_matrix = product_matrix*np.exp(-1j*phase)
256 
257  product_matrix = np.eye(16)*2 - product_matrix - product_matrix.conj().T
258  # the error of the decomposition
259  decomposition_error = (np.real(np.trace(product_matrix)))/2
260 
261  print('The error of the decomposition is ' + str(decomposition_error))
262 
263  assert( decomposition_error < 1e-3 )
264 
265 
267  r"""
268  This method is called by pytest.
269  Test to decompose a 4-qubit unitary of the IBM chellenge
270 
271  """
272 
273  from squander import N_Qubit_Decomposition_adaptive
274  from scipy.io import loadmat
275 
276  # load the unitary from file
277  data = loadmat('data/Umtx.mat')
278  # The unitary to be decomposed
279  Umtx = data['Umtx']
280  config = { 'max_outer_iterations': 1,
281  'max_inner_iterations_agent': 25000,
282  'max_inner_iterations_compression': 10000,
283  'max_inner_iterations' : 500,
284  'max_inner_iterations_final': 5000,
285  'Randomized_Radius': 0.3,
286  'randomized_adaptive_layers': 1,
287  'optimization_tolerance_agent': 1e-4,
288  'optimization_tolerance': 1e-5,
289 
290  'agent_num': 10}
291 
292  # creating a class to decompose the unitary
293  cDecompose = N_Qubit_Decomposition_adaptive( Umtx.conj().T, config=config )
294 
295 
296  # setting the verbosity of the decomposition
297  cDecompose.set_Verbose( 3 )
298 
299 
300  # adding decomposing layers to the gate structure
301  levels = 2
302  for idx in range(levels):
303  cDecompose.add_Adaptive_Layers()
304 
305  cDecompose.add_Finalyzing_Layer_To_Gate_Structure()
306 
307 
308 
309  # setting intial parameter set
310  parameter_num = cDecompose.get_Parameter_Num()
311  parameters = np.zeros( (parameter_num,1), dtype=np.float64 )
312  cDecompose.set_Optimized_Parameters( parameters )
313 
314  # setting optimizer
315  cDecompose.set_Optimizer("AGENTS")
316 
317  # starting the decomposition
318  cDecompose.get_Initial_Circuit()
319 
320  # setting optimizer
321  cDecompose.set_Optimizer("BFGS")
322 
323  # continue the decomposition with a second optimizer method
324  cDecompose.get_Initial_Circuit()
325 
326  # starting compression iterations
327  cDecompose.Compress_Circuit()
328 
329  # finalize the gate structur (replace CRY gates with CNOT gates)
330  cDecompose.Finalize_Circuit()
331 
332  # list the decomposing operations
333  cDecompose.List_Gates()
334 
335  # get the decomposing operations
336  quantum_circuit = cDecompose.get_Qiskit_Circuit()
337 
338  # print the quantum circuit
339  print(quantum_circuit)
340 
341  import numpy.linalg as LA
342 
343  # the unitary matrix from the result object
344  decomposed_matrix = utils.get_unitary_from_qiskit_circuit( quantum_circuit )
345  product_matrix = np.dot(Umtx,decomposed_matrix.conj().T)
346  phase = np.angle(product_matrix[0,0])
347  product_matrix = product_matrix*np.exp(-1j*phase)
348 
349  product_matrix = np.eye(16)*2 - product_matrix - product_matrix.conj().T
350  # the error of the decomposition
351  decomposition_error = (np.real(np.trace(product_matrix)))/2
352 
353  print('The error of the decomposition is ' + str(decomposition_error))
354 
355  assert( decomposition_error < 1e-3 )
356 
357 
358 
359 
A base class to determine the decomposition of an N-qubit unitary into a sequence of CNOT and U3 gate...