Sequential Quantum Gate Decomposer  v1.9.3
Powerful decomposition of general unitarias into one- and two-qubit gates gates
utils.py
Go to the documentation of this file.
1 
3 """
4 Created on Tue Jun 30 15:44:26 2020
5 Copyright 2020 Peter Rakyta, Ph.D.
6 
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
10 
11  http://www.apache.org/licenses/LICENSE-2.0
12 
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see http://www.gnu.org/licenses/.
21 
22 @author: Peter Rakyta, Ph.D.
23 """
24 
25 
27 
28 
29 
30 import numpy as np
31 from squander.IO_interfaces import Qiskit_IO
32 from squander.gates.qgd_Circuit import qgd_Circuit as Circuit
33 from qiskit import QuantumCircuit
34 
35 import qiskit
36 qiskit_version = qiskit.version.get_version_info()
37 
38 if qiskit_version[0] == '0':
39  from qiskit import Aer
40  from qiskit import execute
41  if int(qiskit_version[2])>3:
42  from qiskit.quantum_info import Operator
43 else:
44  import qiskit_aer as Aer
45  from qiskit import transpile
46  from qiskit.quantum_info import Operator
47 
48 
49 
50 
52 def get_unitary_from_qiskit_circuit( circuit: QuantumCircuit ):
53  """
54  Call to extract a unitary from Qiskit circuit
55 
56  Args:
57 
58  circuit (QuantumCircuit) A Qiskit circuit
59 
60  Return:
61 
62  Returns with the generated unitary
63 
64  """
65 
66 
67  if qiskit_version[0] == '0':
68  backend = Aer.get_backend('aer_simulator')
69  circuit.save_unitary()
70 
71  # job execution and getting the result as an object
72  job = execute(circuit, backend)
73 
74  # the result of the Qiskit job
75  result=job.result()
76 
77  else :
78 
79  circuit.save_unitary()
80  backend = Aer.AerSimulator(method='unitary')
81 
82  compiled_circuit = transpile(circuit, backend)
83  result = backend.run(compiled_circuit).result()
84 
85 
86 
87  return np.asarray( result.get_unitary(circuit) )
88 
89 
90 
91 
92 
93 def get_unitary_from_qiskit_circuit_operator( circuit: QuantumCircuit ):
94  """
95  Call to extract a unitary from Qiskit circuit using qiskit.quantum_info.Operator support
96 
97  Args:
98 
99  circuit (QuantumCircuit) A Qiskit circuit
100 
101  Return:
102 
103  Returns with the generated unitary
104 
105  """
106 
107 
108  if qiskit_version[0] == '0' and int(qiskit_version[2])<4:
109 
110  print("Currently installed version of qiskit does not support extracting the unitary of a circuit via Operator. Using get_unitary_from_qiskit_circuit function instead.")
111  return get_unitary_from_qiskit_circuit(circuit)
112 
113  return Operator(circuit).to_matrix()
114 
115 
116 
117 def qasm_to_squander_circuit( filename: str, return_transpiled=False):
118  """
119  Converts a QASM file to a SQUANDER circuit
120 
121  Args:
122 
123  filename (str) The path to the QASM file
124 
125  Return:
126 
127  Returns with the SQUANDER circuit and the array of the corresponding parameters
128 
129  """
130 
131  qc = qiskit.QuantumCircuit.from_qasm_file(filename)
132 
133  allowed_gates = {'u', 'u3', 'cx', 'cry', 'cz', 'ch', 'rx', 'ry', 'rz', 'h', 'x', 'y', 'z', 'sx'}
134 
135  if any(gate.operation.name not in allowed_gates for gate in qc.data):
136  qc_transpiled = qiskit.transpile(qc, basis_gates=allowed_gates, optimization_level=0)
137  else:
138  qc_transpiled = qc
139 
140  circuit_squander, circut_parameters = Qiskit_IO.convert_Qiskit_to_Squander(qc_transpiled)
141 
142  if return_transpiled: return circuit_squander, circut_parameters, qc_transpiled
143  return circuit_squander, circut_parameters
144 
145 
146 
147 
148 def CompareCircuits( circ1: Circuit, parameters1: np.ndarray, circ2: Circuit, parameters2: np.ndarray, parallel : int = 1, tolerance: float = 1e-5) :
149  """
150  Call to test if the two circuits give the same state transformation upon a random input state
151 
152 
153  Args:
154 
155  circ1 ( Circuit ) A circuit
156 
157  parameters1 ( np.ndarray ) A parameter array associated with the input circuit
158 
159  circ2 ( Circuit ) A circuit
160 
161  parameters2 ( np.ndarray ) A parameter array associated with the input circuit
162 
163  parallel (int, optional) Set 0 for sequential evaluation, 1 for using TBB parallelism or 2 for using openMP
164 
165  tolerance ( float, optional) The tolerance of the comparision when the inner product of the resulting states is matched to unity.
166 
167 
168  Return:
169 
170  Returns with True if the two circuits give identical results.
171  """
172 
173 
174  qbit_num1 = circ1.get_Qbit_Num()
175  qbit_num2 = circ2.get_Qbit_Num()
176 
177  if qbit_num1 != qbit_num2:
178  raise Exception( "The two compared circuits should have the same number of qubits." )
179 
180  matrix_size = 1 << qbit_num1
181  initial_state_real = np.random.uniform(-1.0,1.0, (matrix_size,) )
182  initial_state_imag = np.random.uniform(-1.0,1.0, (matrix_size,) )
183  initial_state = initial_state_real + initial_state_imag*1j
184  norm = np.sum(initial_state_real * initial_state_real + initial_state_imag*initial_state_imag)
185  initial_state = initial_state/np.sqrt(norm)
186 
187 
188 
189  transformed_state_1 = initial_state.copy()
190  transformed_state_2 = initial_state
191 
192  circ1.apply_to( parameters1, transformed_state_1, parallel=parallel )
193  circ2.apply_to( parameters2, transformed_state_2, parallel=parallel)
194 
195  overlap = np.sum( transformed_state_1.conj() * transformed_state_2 )
196  #print( "overlap: ", np.abs(overlap) )
197 
198  assert( (np.abs(overlap)-1) < tolerance )
199 
200 
201 
202 
def qasm_to_squander_circuit
Definition: utils.py:117
def get_unitary_from_qiskit_circuit_operator
Definition: utils.py:93
def get_unitary_from_qiskit_circuit
Call to retrieve the unitary from QISKIT circuit.
Definition: utils.py:52
def CompareCircuits
Definition: utils.py:148
result
the result of the Qiskit job