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":
234 gate_name = gate_name.lower()
237 gate_adding_fnc = getattr(circuit, gate_name )
238 if not is_controlled_gate
and parameter_num == 0:
240 gate_adding_fnc(target_qbit)
242 elif not is_controlled_gate
and parameter_num > 0:
244 parameters_QISKIT = list(parameters)
247 if gate_name !=
"p" and gate_name !=
"u2":
248 parameters_QISKIT[0] = parameters_QISKIT[0]*2
249 gate_adding_fnc( *parameters_QISKIT, target_qbit)
251 elif is_controlled_gate
and parameter_num == 0:
253 control_qbit = qbit_num-1
254 gate_adding_fnc(control_qbit, target_qbit)
256 elif is_controlled_gate
and parameter_num > 0:
258 parameters_QISKIT = list(parameters)
261 parameters_QISKIT[0] = parameters_QISKIT[0]*2
262 gate_adding_fnc( *parameters_QISKIT, control_qbit, target_qbit)
268 gate_matrix_qiskit = np.asarray(gate_matrix_qiskit)
271 delta_matrix=gate_matrix_squander-gate_matrix_qiskit
274 error=np.linalg.norm(delta_matrix)
277 assert( error < 1e-3 )
282 This method is called to test the individual gates 283 Test by comparing the effect of a gate on an input state 284 by squander gate to Qiskit implementation 288 is_controlled_gate = (len(gate_obj.__name__) > 1)
and (gate_obj.__name__[0] ==
'C')
290 for qbit_num
in range(2,7):
293 target_qbit = qbit_num-2
296 if not is_controlled_gate:
298 squander_gate = gate_obj( qbit_num, target_qbit )
299 elif is_controlled_gate:
301 control_qbit = qbit_num-1
302 squander_gate = gate_obj( qbit_num, target_qbit, control_qbit )
306 matrix_size = 1 << qbit_num
308 initial_state_real = np.random.uniform(-1.0,1.0, (matrix_size,) )
309 initial_state_imag = np.random.uniform(-1.0,1.0, (matrix_size,) )
310 initial_state = initial_state_real + initial_state_imag*1j
311 initial_state = initial_state/np.linalg.norm(initial_state)
319 state_squander = initial_state.copy()
323 parameter_num = squander_gate.get_Parameter_Num()
324 if parameter_num == 0:
325 squander_gate.apply_to( state_squander )
326 elif parameter_num > 0:
327 parameters = ( np.random.rand( parameter_num )*2-1.0 ) * np.pi
328 squander_gate.apply_to( state_squander, parameters )
334 circuit_qiskit = QuantumCircuit(qbit_num)
335 circuit_qiskit.initialize( initial_state )
338 gate_name = gate_obj.__name__
341 if gate_name ==
"U3":
344 elif gate_name ==
"U1":
347 elif gate_name ==
"CNOT":
350 gate_name = gate_name.lower()
353 gate_adding_fnc = getattr(circuit_qiskit, gate_name )
354 if not is_controlled_gate
and parameter_num == 0:
356 gate_adding_fnc(target_qbit)
358 elif not is_controlled_gate
and parameter_num > 0:
360 parameters_QISKIT = list(parameters)
363 if gate_name !=
"p" and gate_name !=
"u2":
364 parameters_QISKIT[0] = parameters_QISKIT[0]*2
365 gate_adding_fnc( *parameters_QISKIT, target_qbit)
367 elif is_controlled_gate
and parameter_num == 0:
369 control_qbit = qbit_num-1
370 gate_adding_fnc(control_qbit, target_qbit)
372 elif is_controlled_gate
and parameter_num > 0:
374 parameters_QISKIT = list(parameters)
377 parameters_QISKIT[0] = parameters_QISKIT[0]*2
378 control_qbit = qbit_num-1
379 gate_adding_fnc( *parameters_QISKIT, control_qbit, target_qbit)
383 if qiskit_version[0] ==
'1' or qiskit_version[0] ==
'2':
385 circuit_qiskit.save_statevector()
387 backend = Aer.AerSimulator(method=
'statevector')
388 compiled_circuit = transpile(circuit_qiskit, backend)
389 result = backend.run(compiled_circuit).
result()
391 state_QISKIT = result.get_statevector(compiled_circuit)
394 elif qiskit_version[0] ==
'0':
397 simulator = Aer.get_backend(
'statevector_simulator')
399 backend = Aer.get_backend(
'aer_simulator')
400 result = execute(circuit_qiskit, simulator).
result()
402 state_QISKIT = result.get_statevector(circuit_qiskit)
404 state_QISKIT = np.array(state_QISKIT)
407 error=np.linalg.norm( state_squander-state_QISKIT )
409 assert( error < 1e-3 )
414 This method is called by pytest. 415 Test by comparing all of the squander gates to Qiskit implementation 419 import squander.gates.gates_Wrapper
as gates
421 for name
in dir(gates):
422 obj = getattr(gates, name)
424 if inspect.isclass(obj):
425 print(f
"testing gate: {name}")
427 if name ==
"SYC" or name ==
"Gate":
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)