def test_measure(self): """Check commutativity involving measures.""" comm_checker = CommutationChecker() # Measure is over qubit 0, while gate is over a disjoint subset of qubits # We should be able to swap these. res = comm_checker.commute(Measure(), [0], [0], CXGate(), [1, 2], []) self.assertTrue(res) # Measure and gate have intersecting set of qubits # We should not be able to swap these. res = comm_checker.commute(Measure(), [0], [0], CXGate(), [0, 2], []) self.assertFalse(res) # Measures over different qubits and clbits res = comm_checker.commute(Measure(), [0], [0], Measure(), [1], [1]) self.assertTrue(res) # Measures over different qubits but same classical bit # We should not be able to swap these. res = comm_checker.commute(Measure(), [0], [0], Measure(), [1], [0]) self.assertFalse(res) # Measures over same qubits but different classical bit # ToDo: can we swap these? # Currently checker takes the safe approach and returns False. res = comm_checker.commute(Measure(), [0], [0], Measure(), [0], [1]) self.assertFalse(res)
def test_slice(self): """Verify circuit.data can be sliced.""" qr = QuantumRegister(2) qc = QuantumCircuit(qr) qc.h(0) qc.cx(0, 1) qc.h(1) qc.cx(1, 0) qc.h(1) qc.cx(0, 1) qc.h(0) h_slice = qc.data[::2] cx_slice = qc.data[1:-1:2] self.assertEqual( h_slice, [ CircuitInstruction(HGate(), [qr[0]], []), CircuitInstruction(HGate(), [qr[1]], []), CircuitInstruction(HGate(), [qr[1]], []), CircuitInstruction(HGate(), [qr[0]], []), ], ) self.assertEqual( cx_slice, [ CircuitInstruction(CXGate(), [qr[0], qr[1]], []), CircuitInstruction(CXGate(), [qr[1], qr[0]], []), CircuitInstruction(CXGate(), [qr[0], qr[1]], []), ], )
def test_conditional_gates(self): """Check commutativity involving conditional gates.""" comm_checker = CommutationChecker() qr = QuantumRegister(3) cr = ClassicalRegister(2) # Currently, in all cases commutativity checker should returns False. # This is definitely suboptimal. res = comm_checker.commute(CXGate().c_if(cr[0], 0), [qr[0], qr[1]], [], XGate(), [qr[2]], []) self.assertFalse(res) res = comm_checker.commute(CXGate().c_if(cr[0], 0), [qr[0], qr[1]], [], XGate(), [qr[1]], []) self.assertFalse(res) res = comm_checker.commute(CXGate().c_if(cr[0], 0), [qr[0], qr[1]], [], CXGate().c_if(cr[0], 0), [qr[0], qr[1]], []) self.assertFalse(res) res = comm_checker.commute(XGate().c_if(cr[0], 0), [qr[0]], [], XGate().c_if(cr[0], 1), [qr[0]], []) self.assertFalse(res) res = comm_checker.commute(XGate().c_if(cr[0], 0), [qr[0]], [], XGate(), [qr[0]], []) self.assertFalse(res)
def test_get_instructions_for_qargs(self): with self.assertRaises(KeyError): self.empty_target.operations_for_qargs((0, )) expected = [RZGate(self.theta), IGate(), SXGate(), XGate(), Measure()] res = self.ibm_target.operations_for_qargs((0, )) for gate in expected: self.assertIn(gate, res) expected = [ECRGate()] res = self.fake_backend_target.operations_for_qargs((1, 0)) for gate in expected: self.assertIn(gate, res) expected = [CXGate()] res = self.fake_backend_target.operations_for_qargs((0, 1)) self.assertEqual(expected, res) ideal_sim_expected = [ UGate(self.theta, self.phi, self.lam), RXGate(self.theta), RYGate(self.theta), RZGate(self.theta), CXGate(), ECRGate(), CCXGate(), Measure(), ] for gate in ideal_sim_expected: self.assertIn(gate, self.ideal_sim_target.operations_for_qargs(None))
def test_parameterized_gates(self): """Check commutativity between parameterized gates, both with free and with bound parameters.""" comm_checker = CommutationChecker() # gate that has parameters but is not considered parameterized rz_gate = RZGate(np.pi / 2) self.assertEqual(len(rz_gate.params), 1) self.assertFalse(rz_gate.is_parameterized()) # gate that has parameters and is considered parameterized rz_gate_theta = RZGate(Parameter("Theta")) rz_gate_phi = RZGate(Parameter("Phi")) self.assertEqual(len(rz_gate_theta.params), 1) self.assertTrue(rz_gate_theta.is_parameterized()) # gate that has no parameters and is not considered parameterized cx_gate = CXGate() self.assertEqual(len(cx_gate.params), 0) self.assertFalse(cx_gate.is_parameterized()) # We should detect that these gates commute res = comm_checker.commute(rz_gate, [0], [], cx_gate, [0, 1], []) self.assertTrue(res) # We should detect that these gates commute res = comm_checker.commute(rz_gate, [0], [], rz_gate, [0], []) self.assertTrue(res) # We should detect that parameterized gates over disjoint qubit subsets commute res = comm_checker.commute(rz_gate_theta, [0], [], rz_gate_theta, [1], []) self.assertTrue(res) # We should detect that parameterized gates over disjoint qubit subsets commute res = comm_checker.commute(rz_gate_theta, [0], [], rz_gate_phi, [1], []) self.assertTrue(res) # We should detect that parameterized gates over disjoint qubit subsets commute res = comm_checker.commute(rz_gate_theta, [2], [], cx_gate, [1, 3], []) self.assertTrue(res) # However, for now commutativity checker should return False when checking # commutativity between a parameterized gate and some other gate, when # the two gates are over intersecting qubit subsets. # This check should be changed if commutativity checker is extended to # handle parameterized gates better. res = comm_checker.commute(rz_gate_theta, [0], [], cx_gate, [0, 1], []) self.assertFalse(res) res = comm_checker.commute(rz_gate_theta, [0], [], rz_gate, [0], []) self.assertFalse(res)
def test_reset(self): """Check commutativity involving resets.""" comm_checker = CommutationChecker() # A gate should not commute with reset when the qubits intersect. res = comm_checker.commute(Reset(), [0], [], CXGate(), [0, 2], []) self.assertFalse(res) # A gate should commute with reset when the qubits are disjoint. res = comm_checker.commute(Reset(), [0], [], CXGate(), [1, 2], []) self.assertTrue(res)
def test_cx_do_not_wrongly_cancel(self): """Test that CX(0,1) and CX(1, 0) do not cancel out, when (CX, CX) is passed as an inverse pair.""" qc = QuantumCircuit(2, 0) qc.cx(0, 1) qc.cx(1, 0) pass_ = InverseCancellation([(CXGate(), CXGate())]) pm = PassManager(pass_) new_circ = pm.run(qc) gates_after = new_circ.count_ops() self.assertIn("cx", gates_after) self.assertEqual(gates_after["cx"], 2)
def test_caching_different_qubit_sets(self): """Check that hashing same commutativity results over different qubit sets works as expected.""" comm_checker = CommutationChecker() # All the following should be cached in the same way # though each relation gets cached twice: (A, B) and (B, A) comm_checker.commute(XGate(), [0], [], CXGate(), [0, 1], []) comm_checker.commute(XGate(), [10], [], CXGate(), [10, 20], []) comm_checker.commute(XGate(), [10], [], CXGate(), [10, 5], []) comm_checker.commute(XGate(), [5], [], CXGate(), [5, 7], []) self.assertEqual(len(comm_checker.cache), 2)
def test_standard_2Q_one(self): """Test standard 2Q gate.repeat(1) method. """ qr = QuantumRegister(2, 'qr') expected_circ = QuantumCircuit(qr) expected_circ.append(CXGate(), [qr[0], qr[1]]) expected = expected_circ.to_instruction() result = CXGate().repeat(1) self.assertEqual(result.name, 'cx*1') self.assertEqual(result.definition, expected.definition) self.assertIsInstance(result, Gate)
def test_instruction_init(self): """Test initialization from a circuit.""" gate = CXGate() op = Operator(gate).data target = gate.to_matrix() global_phase_equivalent = matrix_equal(op, target, ignore_phase=True) self.assertTrue(global_phase_equivalent) gate = CHGate() op = Operator(gate).data had = HGate().to_matrix() target = np.kron(had, np.diag([0, 1])) + np.kron(np.eye(2), np.diag([1, 0])) global_phase_equivalent = matrix_equal(op, target, ignore_phase=True) self.assertTrue(global_phase_equivalent)
def test_passing_quantum_registers(self): """Check that passing QuantumRegisters works correctly.""" comm_checker = CommutationChecker() qr = QuantumRegister(4) # should commute res = comm_checker.commute(CXGate(), [qr[1], qr[0]], [], CXGate(), [qr[1], qr[2]], []) self.assertTrue(res) # should not commute res = comm_checker.commute(CXGate(), [qr[0], qr[1]], [], CXGate(), [qr[1], qr[2]], []) self.assertFalse(res)
def _load_rb_data(self, rb_exp_data_file_name: str): """ loader for the experiment data and configuration setup. Args: rb_exp_data_file_name(str): The file name that contain the experiment data. Returns: list: containing dict of the experiment setup configuration and list of dictionaries containing the experiment results. ExperimentData: ExperimentData object that was creates by the analysis function. """ interleaved_gates = {"x": XGate(), "cx": CXGate()} data, exp_attributes, expdata1 = self._load_json_data( rb_exp_data_file_name) rb_exp = InterleavedRB( interleaved_gates[exp_attributes["interleaved_element"]], exp_attributes["physical_qubits"], exp_attributes["lengths"], num_samples=exp_attributes["num_samples"], seed=exp_attributes["seed"], ) gate_error_ratio = { ((0, ), "id"): 1, ((0, ), "rz"): 0, ((0, ), "sx"): 1, ((0, ), "x"): 1, ((0, 1), "cx"): 1, } rb_exp.analysis.set_options(gate_error_ratio=gate_error_ratio) analysis_results = rb_exp.analysis.run(expdata1).block_for_results() return data, analysis_results
def test_compose_gate(self): """Composing with a gate. ┌───┐ ┌───┐ ┌───┐ lqr_1_0: ───┤ H ├─── lqr_1_0: ───┤ H ├────┤ X ├ ├───┤ ├───┤ └─┬─┘ lqr_1_1: ───┤ X ├─── lqr_1_1: ───┤ X ├──────┼─── ┌──┴───┴──┐ ───■─── ┌──┴───┴──┐ │ lqr_1_2: ┤ U1(0.1) ├ + ┌─┴─┐ = lqr_1_2: ┤ U1(0.1) ├───┼─── └─────────┘ ─┤ X ├─ └─────────┘ │ lqr_2_0: ─────■───── └───┘ lqr_2_0: ─────■────────┼── ┌─┴─┐ ┌─┴─┐ │ lqr_2_1: ───┤ X ├─── lqr_2_1: ───┤ X ├──────■─── └───┘ └───┘ lcr_0: 0 ═══════════ lcr_0: 0 ═══════════ lcr_1: 0 ═══════════ lcr_1: 0 ═══════════ """ circuit_composed = self.circuit_left.compose(CXGate(), qubits=[4, 0]) circuit_expected = self.circuit_left.copy() circuit_expected.cx(self.left_qubit4, self.left_qubit0) self.assertEqual(circuit_composed, circuit_expected)
def test_extend_is_validated(self): """Verify extending circuit.data is broadcast and validated.""" qr = QuantumRegister(2) qc = QuantumCircuit(qr) qc.data.extend( [ CircuitInstruction(HGate(), [qr[0]], []), CircuitInstruction(CXGate(), [0, 1], []), CircuitInstruction(HGate(), [qr[1]], []), ] ) expected_qc = QuantumCircuit(qr) expected_qc.h(0) expected_qc.cx(0, 1) expected_qc.h(1) self.assertEqual(qc, expected_qc) self.assertRaises( CircuitError, qc.data.extend, [CircuitInstruction(HGate(), [qr[0], qr[1]], [])] ) self.assertRaises(CircuitError, qc.data.extend, [CircuitInstruction(HGate(), [], [qr[0]])])
def test_initial_state_as_circuit_object(self): """Test setting `initial_state` to `QuantumCircuit` object""" # ┌───┐ ┌───┐ # q_0: ──■──┤ X ├───────■──┤ X ├ # ┌─┴─┐├───┤┌───┐┌─┴─┐├───┤ # q_1: ┤ X ├┤ H ├┤ X ├┤ X ├┤ X ├ # └───┘└───┘└───┘└───┘└───┘ ref = QuantumCircuit(2) ref.cx(0, 1) ref.x(0) ref.h(1) ref.x(1) ref.cx(0, 1) ref.x(0) ref.x(1) qc = QuantumCircuit(2) qc.cx(0, 1) qc.h(1) expected = NLocal( num_qubits=2, rotation_blocks=XGate(), entanglement_blocks=CXGate(), initial_state=qc, reps=1, ) self.assertCircuitEqual(ref, expected)
def test_euler_basis_selection(self): """Verify decomposition uses euler_basis for 1q gates.""" euler_bases = [ ('U3', ['u3']), ('U1X', ['u1', 'rx']), ('RR', ['r']), ('ZYZ', ['rz', 'ry']), ('ZXZ', ['rz', 'rx']), ('XYX', ['rx', 'ry']), ] kak_gates = [ (CXGate(), 'cx'), (CZGate(), 'cz'), (iSwapGate(), 'iswap'), (RXXGate(np.pi / 2), 'rxx'), ] for basis in product(euler_bases, kak_gates): (euler_basis, oneq_gates), (kak_gate, kak_gate_name) = basis with self.subTest(euler_basis=euler_basis, kak_gate=kak_gate): decomposer = TwoQubitBasisDecomposer(kak_gate, euler_basis=euler_basis) unitary = random_unitary(4) self.check_exact_decomposition(unitary.data, decomposer) decomposition_basis = set(decomposer(unitary).count_ops()) requested_basis = set(oneq_gates + [kak_gate_name]) self.assertTrue(decomposition_basis.issubset(requested_basis))
def test_extra_props_str(self): target = Target(description="Extra Properties") class ExtraProperties(InstructionProperties): """An example properties subclass.""" def __init__( self, duration=None, error=None, calibration=None, tuned=None, diamond_norm_error=None, ): super().__init__(duration=duration, error=error, calibration=calibration) self.tuned = tuned self.diamond_norm_error = diamond_norm_error cx_props = { (3, 4): ExtraProperties( duration=270.22e-9, error=0.00713, tuned=False, diamond_norm_error=2.12e-6 ), } target.add_instruction(CXGate(), cx_props) expected = """Target: Extra Properties Number of qubits: 5 Instructions: cx (3, 4): Duration: 2.7022e-07 sec. Error Rate: 0.00713 """ self.assertEqual(expected, str(target))
def test_can_append_to_quantum_circuit(self): """Test that we can add various objects with Operation interface to a Quantum Circuit.""" qc = QuantumCircuit(6, 1) qc.append(XGate(), [2]) qc.append(Barrier(3), [1, 2, 4]) qc.append(CXGate(), [0, 1]) qc.append(Measure(), [1], [0]) qc.append(Reset(), [0]) qc.cx(3, 4) qc.append(Gate("some_gate", 3, []), [1, 2, 3]) qc.append(Initialize([0.5, 0.5, 0.5, 0.5]), [4, 5]) qc.append(Isometry(np.eye(4, 4), 0, 0), [3, 4]) qc.append(Pauli("II"), [0, 1]) # Appending Clifford circ1 = QuantumCircuit(2) circ1.h(1) circ1.cx(0, 1) qc.append(Clifford(circ1), [0, 1]) # Appending CNOTDihedral circ2 = QuantumCircuit(2) circ2.t(0) circ2.x(0) circ2.t(1) qc.append(CNOTDihedral(circ2), [2, 3]) # If we got to here, we have successfully appended everything to qc self.assertIsInstance(qc, QuantumCircuit)
def test_barrier(self): """Check commutativity involving barriers.""" comm_checker = CommutationChecker() # A gate should not commute with a barrier # (at least if these are over intersecting qubit sets). res = comm_checker.commute(Barrier(4), [0, 1, 2, 3], [], CXGate(), [1, 2], []) self.assertFalse(res) # Does it even make sense to have a barrier over a subset of qubits? # Though in this case, it probably makes sense to say that barrier and gate can be swapped. res = comm_checker.commute(Barrier(4), [0, 1, 2, 3], [], CXGate(), [5, 6], []) self.assertTrue(res)
def test_caching_negative_results(self): """Check that hashing negative results in commutativity checker works as expected.""" comm_checker = CommutationChecker() res = comm_checker.commute(XGate(), [0], [], CXGate(), [0, 1], []) self.assertFalse(res) self.assertGreater(len(comm_checker.cache), 0)
def test_experiment_config(self): """Test converting to and from config works""" exp = InterleavedRB(CXGate(), [0, 1], lengths=[10, 20, 30, 40], num_samples=10) loaded_exp = InterleavedRB.from_config(exp.config()) self.assertNotEqual(exp, loaded_exp) self.assertTrue(self.json_equiv(exp, loaded_exp))
def test_pairwise_entanglement(self): """Test pairwise entanglement.""" nlocal = NLocal(5, rotation_blocks=XGate(), entanglement_blocks=CXGate(), entanglement='pairwise', reps=1) entangler_map = nlocal.get_entangler_map(0, 0, 2) pairwise = [(0, 1), (2, 3), (1, 2), (3, 4)] self.assertEqual(pairwise, entangler_map)
def test_instructions(self): self.assertEqual(self.empty_target.instructions, []) ibm_expected = [ (IGate(), (0, )), (IGate(), (1, )), (IGate(), (2, )), (IGate(), (3, )), (IGate(), (4, )), (RZGate(self.theta), (0, )), (RZGate(self.theta), (1, )), (RZGate(self.theta), (2, )), (RZGate(self.theta), (3, )), (RZGate(self.theta), (4, )), (SXGate(), (0, )), (SXGate(), (1, )), (SXGate(), (2, )), (SXGate(), (3, )), (SXGate(), (4, )), (XGate(), (0, )), (XGate(), (1, )), (XGate(), (2, )), (XGate(), (3, )), (XGate(), (4, )), (CXGate(), (3, 4)), (CXGate(), (4, 3)), (CXGate(), (3, 1)), (CXGate(), (1, 3)), (CXGate(), (1, 2)), (CXGate(), (2, 1)), (CXGate(), (0, 1)), (CXGate(), (1, 0)), (Measure(), (0, )), (Measure(), (1, )), (Measure(), (2, )), (Measure(), (3, )), (Measure(), (4, )), ] self.assertEqual(ibm_expected, self.ibm_target.instructions) ideal_sim_expected = [ (UGate(self.theta, self.phi, self.lam), None), (RXGate(self.theta), None), (RYGate(self.theta), None), (RZGate(self.theta), None), (CXGate(), None), (ECRGate(), None), (CCXGate(), None), (Measure(), None), ] self.assertEqual(ideal_sim_expected, self.ideal_sim_target.instructions)
def test_cxgate_as_operation(self): """Test that we can instantiate an object of class :class:`~qiskit.circuit.library.CXGate` and that it has the expected name, num_qubits and num_clbits. """ op = CXGate() self.assertTrue(op.name == "cx") self.assertTrue(op.num_qubits == 2) self.assertTrue(op.num_clbits == 0)
def test_circuit_append(self): """Test appending a controlled gate to a quantum circuit.""" circ = QuantumCircuit(5) inst = CXGate() circ.append(inst.control(), qargs=[0, 2, 1]) circ.append(inst.control(2), qargs=[0, 3, 1, 2]) circ.append(inst.control().control(), qargs=[0, 3, 1, 2]) # should be same as above self.assertEqual(circ[1][0], circ[2][0]) self.assertEqual(circ.depth(), 3) self.assertEqual(circ[0][0].num_ctrl_qubits, 2) self.assertEqual(circ[1][0].num_ctrl_qubits, 3) self.assertEqual(circ[2][0].num_ctrl_qubits, 3) self.assertEqual(circ[0][0].num_qubits, 3) self.assertEqual(circ[1][0].num_qubits, 4) self.assertEqual(circ[2][0].num_qubits, 4) for instr in circ: gate = instr[0] self.assertTrue(isinstance(gate, ControlledGate))
def test_operations(self): self.assertEqual(self.empty_target.operations, []) ibm_expected = [ RZGate(self.theta), IGate(), SXGate(), XGate(), CXGate(), Measure() ] for gate in ibm_expected: self.assertIn(gate, self.ibm_target.operations) aqt_expected = [ RZGate(self.theta), RXGate(self.theta), RYGate(self.theta), RGate(self.theta, self.phi), RXXGate(self.theta), ] for gate in aqt_expected: self.assertIn(gate, self.aqt_target.operations) fake_expected = [ UGate(self.fake_backend._theta, self.fake_backend._phi, self.fake_backend._lam), CXGate(), Measure(), ECRGate(), RXGate(math.pi / 6), RXGate(self.fake_backend._theta), ] for gate in fake_expected: self.assertIn(gate, self.fake_backend_target.operations) ideal_sim_expected = [ UGate(self.theta, self.phi, self.lam), RXGate(self.theta), RYGate(self.theta), RZGate(self.theta), CXGate(), ECRGate(), CCXGate(), Measure(), ] for gate in ideal_sim_expected: self.assertIn(gate, self.ideal_sim_target.operations)
def test_basic_cx_self_inverse(self): """Test that a single self-inverse cx gate as input can be cancelled.""" qc = QuantumCircuit(2, 2) qc.cx(0, 1) qc.cx(0, 1) pass_ = InverseCancellation([CXGate()]) pm = PassManager(pass_) new_circ = pm.run(qc) gates_after = new_circ.count_ops() self.assertNotIn("cx", gates_after)
def test_cnot_rxx_decompose(self): """Verify CNOT decomposition into RXX gate is correct""" cnot = Operator(CXGate()) decomps = [cnot_rxx_decompose(), cnot_rxx_decompose(plus_ry=True, plus_rxx=True), cnot_rxx_decompose(plus_ry=True, plus_rxx=False), cnot_rxx_decompose(plus_ry=False, plus_rxx=True), cnot_rxx_decompose(plus_ry=False, plus_rxx=False)] for decomp in decomps: self.assertTrue(cnot.equiv(decomp))
def test_target_too_small_for_circuit(self): """Test error is raised when target is too small for circuit.""" target = Target() target.add_instruction( CXGate(), {edge: None for edge in CouplingMap.from_line(3).get_edges()}) dag = circuit_to_dag(QuantumCircuit(5)) layout_pass = DenseLayout(target=target) with self.assertRaises(TranspilerError): layout_pass.run(dag)
def setUp(self): super().setUp() self.cmap20 = FakeTokyo().configuration().coupling_map self.target_19 = Target() rng = np.random.default_rng(12345) instruction_props = { edge: InstructionProperties(duration=rng.uniform(1e-7, 1e-6), error=rng.uniform(1e-4, 1e-3)) for edge in CouplingMap.from_heavy_hex(3).get_edges() } self.target_19.add_instruction(CXGate(), instruction_props)