def test_scheduling_pulse(instructions, method, expected_length, random_shuffle, gates_schedule): circuit = QubitCircuit(4) for instruction in instructions: circuit.add_gate( Gate(instruction.name, instruction.targets, instruction.controls)) if random_shuffle: repeat_num = 5 else: repeat_num = 0 result0 = gate_sequence_product(circuit.propagators()) # run the scheduler scheduler = Scheduler(method) gate_cycle_indices = scheduler.schedule(instructions, gates_schedule=gates_schedule, repeat_num=repeat_num) # check if the scheduled length is expected assert (max(gate_cycle_indices) == expected_length) scheduled_gate = [[] for i in range(max(gate_cycle_indices) + 1)] # check if the scheduled circuit is correct for i, cycles in enumerate(gate_cycle_indices): scheduled_gate[cycles].append(circuit.gates[i]) circuit.gates = sum(scheduled_gate, []) result1 = gate_sequence_product(circuit.propagators()) assert (tracedist(result0 * result1.dag(), qeye(result0.dims[0])) < 1.0e-7)
def single_crosstalk_simulation(num_gates): """ A single simulation, with num_gates representing the number of rotations. Args: num_gates (int): The number of random gates to add in the simulation. Returns: result (qutip.solver.Result): A qutip Result object obtained from any of the solver methods such as mesolve. """ num_qubits = 2 # Qubit-0 is the target qubit. Qubit-1 suffers from crosstalk. myprocessor = ModelProcessor(model=MyModel(num_qubits)) # Add qubit frequency detuning 1.852MHz for the second qubit. myprocessor.add_drift(2 * np.pi * (sigmaz() + 1) / 2 * 1.852, targets=1) myprocessor.native_gates = None # Remove the native gates mycompiler = MyCompiler(num_qubits, { "pulse_amplitude": 0.02, "duration": 25 }) myprocessor.add_noise(ClassicalCrossTalk(1.0)) # Define a randome circuit. gates_set = [ Gate("ROT", 0, arg_value=0), Gate("ROT", 0, arg_value=np.pi / 2), Gate("ROT", 0, arg_value=np.pi), Gate("ROT", 0, arg_value=np.pi / 2 * 3), ] circuit = QubitCircuit(num_qubits) for ind in np.random.randint(0, 4, num_gates): circuit.add_gate(gates_set[ind]) # Simulate the circuit. myprocessor.load_circuit(circuit, compiler=mycompiler) init_state = tensor( [Qobj([[init_fid, 0], [0, 0.025]]), Qobj([[init_fid, 0], [0, 0.025]])]) options = SolverOptions(nsteps=10000) # increase the maximal allowed steps e_ops = [tensor([qeye(2), fock_dm(2)])] # observable # compute results of the run using a solver of choice with custom options result = myprocessor.run_state(init_state, solver="mesolve", options=options, e_ops=e_ops) result = result.expect[0][-1] # measured expectation value at the end return result
def _ZXZ_rotation(input_gate): r"""An input 1-qubit gate is expressed as a product of rotation matrices :math:`\textrm{R}_z` and :math:`\textrm{R}_x`. Parameters ---------- input_gate : :class:`qutip.Qobj` The matrix that's supposed to be decomposed should be a Qobj. """ check_gate(input_gate, num_qubits=1) alpha, theta, beta, global_phase_angle = _angles_for_ZYZ(input_gate) alpha = alpha - np.pi / 2 beta = beta + np.pi / 2 # theta and global phase are same as ZYZ values Phase_gate = Gate( "GLOBALPHASE", targets=[0], arg_value=global_phase_angle, arg_label=r"{:0.2f} \times \pi".format(global_phase_angle / np.pi), ) Rz_alpha = Gate( "RZ", targets=[0], arg_value=alpha, arg_label=r"{:0.2f} \times \pi".format(alpha / np.pi), ) Rx_theta = Gate( "RX", targets=[0], arg_value=theta, arg_label=r"{:0.2f} \times \pi".format(theta / np.pi), ) Rz_beta = Gate( "RZ", targets=[0], arg_value=beta, arg_label=r"{:0.2f} \times \pi".format(beta / np.pi), ) return (Rz_alpha, Rx_theta, Rz_beta, Phase_gate)
def test_add_circuit(self): """ Addition of a circuit to a `QubitCircuit` """ qc = QubitCircuit(6) qc.add_gate("CNOT", targets=[1], controls=[0]) test_gate = Gate("SWAP", targets=[1, 4]) qc.add_gate(test_gate) qc.add_gate("TOFFOLI", controls=[0, 1], targets=[2]) qc.add_gate("SNOT", targets=[3]) qc.add_gate(test_gate, index=[3]) qc.add_measurement("M0", targets=[0], classical_store=[1]) qc.add_1q_gate("RY", start=4, end=5, arg_value=1.570796) qc1 = QubitCircuit(6) qc1.add_circuit(qc) # Test if all gates and measurements are added assert len(qc1.gates) == len(qc.gates) for i in range(len(qc1.gates)): assert (qc1.gates[i].name == qc.gates[i].name) assert (qc1.gates[i].targets == qc.gates[i].targets) if (isinstance(qc1.gates[i], Gate) and isinstance(qc.gates[i], Gate)): assert (qc1.gates[i].controls == qc.gates[i].controls) assert (qc1.gates[i].classical_controls == qc.gates[i].classical_controls) elif (isinstance(qc1.gates[i], Measurement) and isinstance(qc.gates[i], Measurement)): assert (qc1.gates[i].classical_store == qc.gates[i].classical_store) # Test exception when qubit out of range pytest.raises(NotImplementedError, qc1.add_circuit, qc, start=4) qc2 = QubitCircuit(8) qc2.add_circuit(qc, start=2) # Test if all gates are added assert len(qc2.gates) == len(qc.gates) # Test if the positions are correct for i in range(len(qc2.gates)): if qc.gates[i].targets is not None: assert (qc2.gates[i].targets[0] == qc.gates[i].targets[0] + 2) if (isinstance(qc.gates[i], Gate) and qc.gates[i].controls is not None): assert (qc2.gates[i].controls[0] == qc.gates[i].controls[0] + 2)
def _ZYZ_pauli_X(input_gate): """Returns a 1 qubit unitary as a product of ZYZ rotation matrices and Pauli X.""" check_gate(input_gate, num_qubits=1) alpha, theta, beta, global_phase_angle = _angles_for_ZYZ(input_gate) Phase_gate = Gate( "GLOBALPHASE", targets=[0], arg_value=global_phase_angle, arg_label=r"{:0.2f} \times \pi".format(global_phase_angle / np.pi), ) Rz_A = Gate( "RZ", targets=[0], arg_value=alpha, arg_label=r"{:0.2f} \times \pi".format(alpha / np.pi), ) Ry_A = Gate( "RY", targets=[0], arg_value=theta / 2, arg_label=r"{:0.2f} \times \pi".format(theta / np.pi), ) Pauli_X = Gate("X", targets=[0]) Ry_B = Gate( "RY", targets=[0], arg_value=-theta / 2, arg_label=r"{:0.2f} \times \pi".format(-theta / np.pi), ) Rz_B = Gate( "RZ", targets=[0], arg_value=-(alpha + beta) / 2, arg_label=r"{:0.2f} \times \pi".format(-(alpha + beta) / (2 * np.pi)), ) Rz_C = Gate( "RZ", targets=[0], arg_value=(-alpha + beta) / 2, arg_label=r"{:0.2f} \times \pi".format((-alpha + beta) / (2 * np.pi)), ) return (Rz_A, Ry_A, Pauli_X, Ry_B, Rz_B, Pauli_X, Rz_C, Phase_gate)
from functools import reduce from operator import mul import warnings import numpy as np import pytest import qutip from qutip_qip.circuit import Gate, QubitCircuit from qutip_qip.operations.gates import gate_sequence_product from qutip_qip.device import (DispersiveCavityQED, LinearSpinChain, CircularSpinChain, SCQubits) _tol = 2.e-2 _x = Gate("X", targets=[0]) _z = Gate("Z", targets=[0]) _y = Gate("Y", targets=[0]) _snot = Gate("SNOT", targets=[0]) _rz = Gate("RZ", targets=[0], arg_value=np.pi / 2, arg_label=r"\pi/2") _rx = Gate("RX", targets=[0], arg_value=np.pi / 2, arg_label=r"\pi/2") _ry = Gate("RY", targets=[0], arg_value=np.pi / 2, arg_label=r"\pi/2") _iswap = Gate("ISWAP", targets=[0, 1]) _cnot = Gate("CNOT", targets=[0], controls=[1]) _sqrt_iswap = Gate("SQRTISWAP", targets=[0, 1]) single_gate_tests = [ pytest.param(2, [_z], id="Z"), pytest.param(2, [_x], id="X"), pytest.param(2, [_y], id="Y"), pytest.param(2, [_snot], id="SNOT"),
def test_add_gate(self): """ Addition of a gate object directly to a `QubitCircuit` """ qc = QubitCircuit(6) qc.add_gate("CNOT", targets=[1], controls=[0]) test_gate = Gate("SWAP", targets=[1, 4]) qc.add_gate(test_gate) qc.add_gate("TOFFOLI", controls=[0, 1], targets=[2]) qc.add_gate("SNOT", targets=[3]) qc.add_gate(test_gate, index=[3]) qc.add_1q_gate("RY", start=4, end=5, arg_value=1.570796) # Test explicit gate addition assert qc.gates[0].name == "CNOT" assert qc.gates[0].targets == [1] assert qc.gates[0].controls == [0] # Test direct gate addition assert qc.gates[1].name == test_gate.name assert qc.gates[1].targets == test_gate.targets # Test specified position gate addition assert qc.gates[3].name == test_gate.name assert qc.gates[3].targets == test_gate.targets # Test adding 1 qubit gate on [start, end] qubits assert qc.gates[5].name == "RY" assert qc.gates[5].targets == [4] assert qc.gates[5].arg_value == 1.570796 assert qc.gates[6].name == "RY" assert qc.gates[6].targets == [5] assert qc.gates[5].arg_value == 1.570796 # Test Exceptions # Global phase is not included for gate in _single_qubit_gates: if gate not in _para_gates: # No target pytest.raises(ValueError, qc.add_gate, gate, None, None) # Multiple targets pytest.raises(ValueError, qc.add_gate, gate, [0, 1, 2], None) # With control pytest.raises(ValueError, qc.add_gate, gate, [0], [1]) else: # No target pytest.raises(ValueError, qc.add_gate, gate, None, None, 1) # Multiple targets pytest.raises(ValueError, qc.add_gate, gate, [0, 1, 2], None, 1) # With control pytest.raises(ValueError, qc.add_gate, gate, [0], [1], 1) for gate in _ctrl_gates: if gate not in _para_gates: # No target pytest.raises(ValueError, qc.add_gate, gate, None, [1]) # No control pytest.raises(ValueError, qc.add_gate, gate, [0], None) else: # No target pytest.raises(ValueError, qc.add_gate, gate, None, [1], 1) # No control pytest.raises(ValueError, qc.add_gate, gate, [0], None, 1) for gate in _swap_like: if gate not in _para_gates: # Single target pytest.raises(ValueError, qc.add_gate, gate, [0], None) # With control pytest.raises(ValueError, qc.add_gate, gate, [0, 1], [3]) else: # Single target pytest.raises(ValueError, qc.add_gate, gate, [0], None, 1) # With control pytest.raises(ValueError, qc.add_gate, gate, [0, 1], [3], 1) for gate in _fredkin_like: # Single target pytest.raises(ValueError, qc.add_gate, gate, [0], [2]) # No control pytest.raises(ValueError, qc.add_gate, gate, [0, 1], None) for gate in _toffoli_like: # No target pytest.raises(ValueError, qc.add_gate, gate, None, [1, 2]) # Single control pytest.raises(ValueError, qc.add_gate, gate, [0], [1])