Sequential Quantum Gate Decomposer  v1.9.7
Powerful decomposition of general unitarias into one- and two-qubit gates gates
example_CH_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 from squander import N_Qubit_Decomposition
24 from squander import Circuit
25 
26 # cerate unitary q-bit matrix
27 from scipy.stats import unitary_group
28 from squander import utils
29 import numpy as np
30 
31 
32 
33 
35  # creating an instance of the wrapper class Circuit
36  Circuit_ret = Circuit( qbit_num )
37 
38  disentangle_qbit = qbit_num - 1
39 
40  for qbit in range(0, disentangle_qbit ):
41 
42  # creating an instance of the wrapper class Circuit
43  layer = Circuit( qbit_num )
44 
45 
46  # add U3 fate to the block
47  layer.add_U3( qbit )
48  layer.add_U3( disentangle_qbit )
49 
50 
51  # Connecting every second target qubit with CNOT gate, and use CH gate otherwise
52  if ( qbit % 2 == 0 ):
53  # add CH gate to the block
54  layer.add_CH( qbit, disentangle_qbit )
55  else:
56  # add CNOT gate to the block
57  layer.add_CNOT( qbit, disentangle_qbit )
58 
59 
60 
61  Circuit_ret.add_Circuit( layer )
62 
63  return Circuit_ret
64 
65 
66 
67 
68 
69 # the number of qubits spanning the unitary
70 qbit_num = 2
71 
72 # determine the soze of the unitary to be decomposed
73 matrix_size = int(2**qbit_num)
74 
75 # creating a random unitary to be decomposed
76 Umtx = unitary_group.rvs(matrix_size)
77 
78 # creating an instance of the C++ class
79 decomp = N_Qubit_Decomposition( Umtx.conj().T )
80 
81 
82 # create custom gate structure
84 
85 
86 # adding custom gate structure to the decomposition
87 decomp.set_Gate_Structure( gate_structure )
88 
89 # set the number of block to be optimized in one shot
90 decomp.set_Optimization_Blocks( 20 )
91 
92 # starting the decomposition
93 decomp.Start_Decomposition()
94 
95 # get the decomposing operations
96 quantum_circuit = decomp.get_Qiskit_Circuit()
97 
98 
99 # print the quantum circuit
100 print(quantum_circuit)
101 
102 import numpy.linalg as LA
103 
104 # the unitary matrix from the result object
105 decomposed_matrix = utils.get_unitary_from_qiskit_circuit( quantum_circuit )
106 product_matrix = np.dot(Umtx,decomposed_matrix.conj().T)
107 phase = np.angle(product_matrix[0,0])
108 product_matrix = product_matrix*np.exp(-1j*phase)
109 
110 product_matrix = np.eye(matrix_size)*2 - product_matrix - product_matrix.conj().T
111 # the error of the decomposition
112 decomposition_error = (np.real(np.trace(product_matrix)))/2
113 
114 print('The error of the decomposition is ' + str(decomposition_error))
115 
116 from qiskit import visualization
117 visualization.circuit_drawer(quantum_circuit, output="latex_source", interactive=True, filename="cirquit_export", fold=10)
118 
119