2 Copyright 2020 Peter Rakyta, Ph.D. 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 8 http://www.apache.org/licenses/LICENSE-2.0 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see http://www.gnu.org/licenses/. 24 from scipy.stats
import unitary_group
28 qiskit_version = qiskit.version.get_version_info()
30 from qiskit
import QuantumCircuit
33 This function is used to add a U2 gate to the circuit. 34 It is a workaround for the fact that Qiskit does not have a U2 gate. 36 self.u( np.pi/2.0, phi, lam, target_qbit )
37 QuantumCircuit.u2 = make_u2
38 import qiskit_aer
as Aer
40 if qiskit_version[0] ==
'1' or qiskit_version[0] ==
'2':
41 from qiskit
import transpile
43 from qiskit
import execute
49 """This is a test class of the python iterface to the gates of the QGD package""" 55 This method is called by pytest. 56 Test to create an instance of CH gate. 60 from squander
import SYC
73 SYC_gate =
SYC( qbit_num, target_qbit, control_qbit )
78 This method is called by pytest. 79 Test to create an instance of Operation_Block class. 83 from squander.gates.qgd_Circuit_Wrapper
import qgd_Circuit_Wrapper
96 This method is called by pytest. 97 Test to add operations to a block of gates 101 from squander.gates.qgd_Circuit_Wrapper
import qgd_Circuit_Wrapper
116 cCircuit.add_U3( target_qbit )
126 cCircuit.add_CNOT( target_qbit, control_qbit )
134 This method is called by pytest. 135 Test to add operations to a block of gates 139 from squander.gates.qgd_Circuit_Wrapper
import qgd_Circuit_Wrapper
152 layer.add_U3( target_qbit )
163 layer.add_CNOT( control_qbit, target_qbit )
167 layer.add_RX( target_qbit )
173 cCircuit.add_Circuit( layer )
179 This method is called to test the individual gates 180 Test by comparing the gate matrix of squander gate to Qiskit implementation 184 is_controlled_gate = (len(gate_obj.__name__) > 1)
and (gate_obj.__name__[0] ==
'C')
186 for qbit_num
in range(2,7):
189 target_qbit = qbit_num-2
192 if not is_controlled_gate:
194 squander_gate = gate_obj( qbit_num, target_qbit )
195 elif is_controlled_gate:
197 control_qbit = qbit_num-1
198 squander_gate = gate_obj( qbit_num, target_qbit, control_qbit )
208 parameter_num = squander_gate.get_Parameter_Num()
209 if parameter_num == 0:
210 gate_matrix_squander = squander_gate.get_Matrix( )
211 elif parameter_num > 0:
212 parameters = ( np.random.rand( parameter_num )*2-1.0 ) * np.pi
213 gate_matrix_squander = squander_gate.get_Matrix( parameters )
219 circuit = QuantumCircuit(qbit_num)
222 gate_name = gate_obj.__name__
225 if gate_name ==
"U3":
228 elif gate_name ==
"U1":
231 elif gate_name ==
"CNOT":
235 gate_name = gate_name.lower()
238 gate_adding_fnc = getattr(circuit, gate_name )
239 if not is_controlled_gate
and parameter_num == 0:
241 gate_adding_fnc(target_qbit)
243 elif not is_controlled_gate
and parameter_num > 0:
245 parameters_QISKIT = list(parameters)
248 if gate_name !=
"p" and gate_name !=
"u2":
249 parameters_QISKIT[0] = parameters_QISKIT[0]*2
250 gate_adding_fnc( *parameters_QISKIT, target_qbit)
252 elif is_controlled_gate
and parameter_num == 0:
254 control_qbit = qbit_num-1
255 gate_adding_fnc(control_qbit, target_qbit)
257 elif is_controlled_gate
and parameter_num > 0:
259 parameters_QISKIT = list(parameters)
262 parameters_QISKIT[0] = parameters_QISKIT[0]*2
263 gate_adding_fnc( *parameters_QISKIT, control_qbit, target_qbit)
269 gate_matrix_qiskit = np.asarray(gate_matrix_qiskit)
272 delta_matrix=gate_matrix_squander-gate_matrix_qiskit
275 error=np.linalg.norm(delta_matrix)
278 assert( error < 1e-3 )
283 This method is called to test the individual gates 284 Test by comparing the effect of a gate on an input state 285 by squander gate to Qiskit implementation 289 is_controlled_gate = (len(gate_obj.__name__) > 1)
and (gate_obj.__name__[0] ==
'C')
291 for qbit_num
in range(2,7):
294 target_qbit = qbit_num-2
297 if not is_controlled_gate:
299 squander_gate = gate_obj( qbit_num, target_qbit )
300 elif is_controlled_gate:
302 control_qbit = qbit_num-1
303 squander_gate = gate_obj( qbit_num, target_qbit, control_qbit )
307 matrix_size = 1 << qbit_num
309 initial_state_real = np.random.uniform(-1.0,1.0, (matrix_size,) )
310 initial_state_imag = np.random.uniform(-1.0,1.0, (matrix_size,) )
311 initial_state = initial_state_real + initial_state_imag*1j
312 initial_state = initial_state/np.linalg.norm(initial_state)
320 state_squander = initial_state.copy()
324 parameter_num = squander_gate.get_Parameter_Num()
325 if parameter_num == 0:
326 squander_gate.apply_to( state_squander )
327 elif parameter_num > 0:
328 parameters = ( np.random.rand( parameter_num )*2-1.0 ) * np.pi
329 squander_gate.apply_to( state_squander, parameters )
335 circuit_qiskit = QuantumCircuit(qbit_num)
336 circuit_qiskit.initialize( initial_state )
339 gate_name = gate_obj.__name__
342 if gate_name ==
"U3":
345 elif gate_name ==
"U1":
348 elif gate_name ==
"CNOT":
351 gate_name = gate_name.lower()
354 gate_adding_fnc = getattr(circuit_qiskit, gate_name )
355 if not is_controlled_gate
and parameter_num == 0:
357 gate_adding_fnc(target_qbit)
359 elif not is_controlled_gate
and parameter_num > 0:
361 parameters_QISKIT = list(parameters)
364 if gate_name !=
"p" and gate_name !=
"u2":
365 parameters_QISKIT[0] = parameters_QISKIT[0]*2
366 gate_adding_fnc( *parameters_QISKIT, target_qbit)
368 elif is_controlled_gate
and parameter_num == 0:
370 control_qbit = qbit_num-1
371 gate_adding_fnc(control_qbit, target_qbit)
373 elif is_controlled_gate
and parameter_num > 0:
375 parameters_QISKIT = list(parameters)
378 parameters_QISKIT[0] = parameters_QISKIT[0]*2
379 control_qbit = qbit_num-1
380 gate_adding_fnc( *parameters_QISKIT, control_qbit, target_qbit)
384 if qiskit_version[0] ==
'1' or qiskit_version[0] ==
'2':
386 circuit_qiskit.save_statevector()
388 backend = Aer.AerSimulator(method=
'statevector')
389 compiled_circuit = transpile(circuit_qiskit, backend)
390 result = backend.run(compiled_circuit).
result()
392 state_QISKIT = result.get_statevector(compiled_circuit)
395 elif qiskit_version[0] ==
'0':
398 simulator = Aer.get_backend(
'statevector_simulator')
400 backend = Aer.get_backend(
'aer_simulator')
401 result = execute(circuit_qiskit, simulator).
result()
403 state_QISKIT = result.get_statevector(circuit_qiskit)
405 state_QISKIT = np.array(state_QISKIT)
408 error=np.linalg.norm( state_squander-state_QISKIT )
410 assert( error < 1e-3 )
415 This method is called by pytest. 416 Test by comparing all of the squander gates to Qiskit implementation 420 import squander.gates.gates_Wrapper
as gates
422 for name
in dir(gates):
423 obj = getattr(gates, name)
425 if inspect.isclass(obj):
426 print(f
"testing gate: {name}")
428 if name ==
"SYC" or name ==
"Gate" or name==
"CR" or name==
"CROT":
def test_Operation_Block_add_block(self)
def test_SYC_creation(self)
def make_u2(self, phi, lam, target_qbit)
def test_Operation_Block_creation(self)
def get_unitary_from_qiskit_circuit
Call to retrieve the unitary from QISKIT circuit.
def perform_gate_apply_to_testing(self, gate_obj)
def test_Operation_Block_add_operations(self)
A class representing a SYC operation.
Type definition of the qgd_Circuit_Wrapper Python class of the qgd_Circuit_Wrapper module...
result
the result of the Qiskit job
def perform_gate_matrix_testing(self, gate_obj)