def test_raise_if_gate_entry_shape_mismatch(self): """Verify we raise if adding a circuit and gate with different shapes.""" # This could be relaxed in the future to e.g. support ancilla management. eq_lib = EquivalenceLibrary() gate = OneQubitZeroParamGate() equiv = QuantumCircuit(2) equiv.h(0) with self.assertRaises(CircuitError): eq_lib.add_equivalence(gate, equiv)
def test_raise_if_target_basis_unreachable(self): """Verify we raise if the circuit cannot be transformed to the target.""" eq_lib = EquivalenceLibrary() qc = QuantumCircuit(1) qc.append(OneQubitZeroParamGate(), [0]) dag = circuit_to_dag(qc) pass_ = BasisTranslator(eq_lib, ['1q1p']) with self.assertRaises(TranspilerError): pass_.run(dag)
def test_add_equivalence(self): """Verify we find all equivalences if a gate is added to top and base.""" base = EquivalenceLibrary() gate = OneQubitZeroParamGate() first_equiv = QuantumCircuit(1) first_equiv.h(0) base.add_equivalence(gate, first_equiv) eq_lib = EquivalenceLibrary(base=base) second_equiv = QuantumCircuit(1) second_equiv.u2(0, np.pi, 0) eq_lib.add_equivalence(gate, second_equiv) entry = eq_lib.get_entry(gate) self.assertEqual(len(entry), 2) self.assertEqual(entry[0], second_equiv) self.assertEqual(entry[1], first_equiv)
def test_has_entry(self): """Verify we find an entry defined in the library.""" eq_lib = EquivalenceLibrary() gate = OneQubitZeroParamGate() equiv = QuantumCircuit(1) equiv.h(0) eq_lib.add_equivalence(gate, equiv) self.assertTrue(eq_lib.has_entry(gate)) self.assertTrue(eq_lib.has_entry(OneQubitZeroParamGate()))
def test_circ_in_basis_no_op(self): """Verify we don't change a circuit already in the target basis.""" eq_lib = EquivalenceLibrary() qc = QuantumCircuit(1) qc.append(OneQubitZeroParamGate(), [0]) dag = circuit_to_dag(qc) expected = circuit_to_dag(qc) pass_ = BasisTranslator(eq_lib, ['1q0p']) actual = pass_.run(dag) self.assertEqual(actual, expected)
def test_has_entry_in_base(self): """Verify we find an entry defined in the base library.""" base_eq_lib = EquivalenceLibrary() gate = OneQubitZeroParamGate() equiv = QuantumCircuit(1) equiv.h(0) base_eq_lib.add_equivalence(gate, equiv) eq_lib = EquivalenceLibrary(base=base_eq_lib) self.assertTrue(eq_lib.has_entry(gate)) self.assertTrue(eq_lib.has_entry(OneQubitZeroParamGate())) gate = OneQubitZeroParamGate() equiv2 = QuantumCircuit(1) equiv.append(U2Gate(0, np.pi), [0]) eq_lib.add_equivalence(gate, equiv2) self.assertTrue(eq_lib.has_entry(gate)) self.assertTrue(eq_lib.has_entry(OneQubitZeroParamGate()))
def test_dont_unroll_a_gate_in_basis_gates(self): """Verify we don't unroll a gate in basis_gates.""" eq_lib = EquivalenceLibrary() gate = TestGate() qc = QuantumCircuit(1) qc.append(gate, [0]) dag = circuit_to_dag(qc) out = UnrollCustomDefinitions(eq_lib, ['u3', 'cx', 'tg']).run(dag) expected = qc.copy() expected_dag = circuit_to_dag(expected) self.assertEqual(out, expected_dag)
def test_add_single_entry(self): """Verify an equivalence added to the library can be retrieved.""" eq_lib = EquivalenceLibrary() gate = OneQubitZeroParamGate() equiv = QuantumCircuit(1) equiv.h(0) eq_lib.add_equivalence(gate, equiv) entry = eq_lib.get_entry(gate) self.assertEqual(len(entry), 1) self.assertIsNot(entry[0], equiv) self.assertEqual(entry[0], equiv)
def test_raise_if_gate_equiv_parameter_mismatch(self): """Verify we raise if adding a circuit and gate with different sets of parameters.""" eq_lib = EquivalenceLibrary() theta = Parameter('theta') phi = Parameter('phi') gate = OneQubitOneParamGate(theta) equiv = QuantumCircuit(1) equiv.p(phi, 0) with self.assertRaises(CircuitError): eq_lib.add_equivalence(gate, equiv) with self.assertRaises(CircuitError): eq_lib.set_entry(gate, [equiv])
def test_diamond_path(self): """Verify we find a path when there are multiple paths to the target basis.""" eq_lib = EquivalenceLibrary() # Path 1: 1q0p -> 1q1p(pi) -> 1q2p(pi, pi/2) gate = OneQubitZeroParamGate() equiv = QuantumCircuit(1) equiv.append(OneQubitOneParamGate(pi), [0]) eq_lib.add_equivalence(gate, equiv) theta = Parameter('theta') gate = OneQubitOneParamGate(theta) equiv = QuantumCircuit(1) equiv.append(OneQubitTwoParamGate(theta, pi / 2), [0]) eq_lib.add_equivalence(gate, equiv) # Path 2: 1q0p -> 1q1p_prime(pi/2) -> 1q2p(2 * pi/2, pi/2) gate = OneQubitZeroParamGate() equiv = QuantumCircuit(1) equiv.append(OneQubitOneParamPrimeGate(pi / 2), [0]) eq_lib.add_equivalence(gate, equiv) alpha = Parameter('alpha') gate = OneQubitOneParamPrimeGate(alpha) equiv = QuantumCircuit(1) equiv.append(OneQubitTwoParamGate(2 * alpha, pi / 2), [0]) eq_lib.add_equivalence(gate, equiv) qc = QuantumCircuit(1) qc.append(OneQubitZeroParamGate(), [0]) dag = circuit_to_dag(qc) expected = QuantumCircuit(1) expected.append(OneQubitTwoParamGate(pi, pi / 2), [0]) expected_dag = circuit_to_dag(expected) pass_ = BasisTranslator(eq_lib, ['1q2p']) actual = pass_.run(dag) self.assertEqual(actual, expected_dag)
def test_set_entry(self): """Verify setting an entry overrides any previously added.""" eq_lib = EquivalenceLibrary() gate = OneQubitZeroParamGate() first_equiv = QuantumCircuit(1) first_equiv.h(0) eq_lib.add_equivalence(gate, first_equiv) second_equiv = QuantumCircuit(1) second_equiv.append(U2Gate(0, np.pi), [0]) eq_lib.set_entry(gate, [second_equiv]) entry = eq_lib.get_entry(gate) self.assertEqual(len(entry), 1) self.assertEqual(entry[0], second_equiv)
def test_unroll_gate_until_reach_basis_gates(self): """Verify we unroll gates until we hit basis_gates.""" eq_lib = EquivalenceLibrary() gate = TestCompositeGate() q = QuantumRegister(1, 'q') gate.definition = QuantumCircuit(q) gate.definition.data = [(TestGate(), [q[0]], [])] qc = QuantumCircuit(q) qc.append(gate, [0]) dag = circuit_to_dag(qc) out = UnrollCustomDefinitions(eq_lib, ['u3', 'cx', 'tg']).run(dag) expected = QuantumCircuit(1) expected.append(TestGate(), [0]) expected_dag = circuit_to_dag(expected) self.assertEqual(out, expected_dag)
def test_dont_unroll_a_gate_in_eq_lib(self): """Verify we don't unroll a gate found in equivalence_library.""" eq_lib = EquivalenceLibrary() gate = TestGate() equiv = QuantumCircuit(1) equiv.h(0) eq_lib.add_equivalence(gate, equiv) qc = QuantumCircuit(1) qc.append(gate, [0]) dag = circuit_to_dag(qc) out = UnrollCustomDefinitions(eq_lib, ['u3', 'cx']).run(dag) expected = qc.copy() expected_dag = circuit_to_dag(expected) self.assertEqual(out, expected_dag)
def test_add_double_entry(self): """Verify separately added equivalences can be retrieved.""" eq_lib = EquivalenceLibrary() gate = OneQubitZeroParamGate() first_equiv = QuantumCircuit(1) first_equiv.h(0) eq_lib.add_equivalence(gate, first_equiv) second_equiv = QuantumCircuit(1) second_equiv.append(U2Gate(0, np.pi), [0]) eq_lib.add_equivalence(gate, second_equiv) entry = eq_lib.get_entry(gate) self.assertEqual(len(entry), 2) self.assertEqual(entry[0], first_equiv) self.assertEqual(entry[1], second_equiv)
def test_if_else(self): """Test a simple if-else with parameters.""" qubits = [Qubit(), Qubit()] clbits = [Clbit(), Clbit()] alpha = Parameter("alpha") beta = Parameter("beta") gate = OneQubitOneParamGate(alpha) equiv = QuantumCircuit([qubits[0]]) equiv.append(OneQubitZeroParamGate(name="1q0p_2"), [qubits[0]]) equiv.append(OneQubitOneParamGate(alpha, name="1q1p_2"), [qubits[0]]) eq_lib = EquivalenceLibrary() eq_lib.add_equivalence(gate, equiv) circ = QuantumCircuit(qubits, clbits) circ.append(OneQubitOneParamGate(beta), [qubits[0]]) circ.measure(qubits[0], clbits[1]) with circ.if_test((clbits[1], 0)) as else_: circ.append(OneQubitOneParamGate(alpha), [qubits[0]]) circ.append(TwoQubitZeroParamGate(), qubits) with else_: circ.append(TwoQubitZeroParamGate(), [qubits[1], qubits[0]]) dag = circuit_to_dag(circ) dag_translated = BasisTranslator( eq_lib, ["if_else", "1q0p_2", "1q1p_2", "2q0p"]).run(dag) expected = QuantumCircuit(qubits, clbits) expected.append(OneQubitZeroParamGate(name="1q0p_2"), [qubits[0]]) expected.append(OneQubitOneParamGate(beta, name="1q1p_2"), [qubits[0]]) expected.measure(qubits[0], clbits[1]) with expected.if_test((clbits[1], 0)) as else_: expected.append(OneQubitZeroParamGate(name="1q0p_2"), [qubits[0]]) expected.append(OneQubitOneParamGate(alpha, name="1q1p_2"), [qubits[0]]) expected.append(TwoQubitZeroParamGate(), qubits) with else_: expected.append(TwoQubitZeroParamGate(), [qubits[1], qubits[0]]) dag_expected = circuit_to_dag(expected) self.assertEqual(dag_translated, dag_expected)
def test_parameter_in_parameter_out(self): """Verify query parameters will be included in returned entry.""" eq_lib = EquivalenceLibrary() theta = Parameter('theta') gate = OneQubitOneParamGate(theta) equiv = QuantumCircuit(1) equiv.p(theta, 0) eq_lib.add_equivalence(gate, equiv) phi = Parameter('phi') gate_phi = OneQubitOneParamGate(phi) entry = eq_lib.get_entry(gate_phi) expected = QuantumCircuit(1) expected.p(phi, 0) self.assertEqual(len(entry), 1) self.assertEqual(entry[0], expected)
def test_single_substitution(self): """Verify we correctly unroll gates through a single equivalence.""" eq_lib = EquivalenceLibrary() gate = OneQubitZeroParamGate() equiv = QuantumCircuit(1) equiv.append(OneQubitOneParamGate(pi), [0]) eq_lib.add_equivalence(gate, equiv) qc = QuantumCircuit(1) qc.append(OneQubitZeroParamGate(), [0]) dag = circuit_to_dag(qc) expected = QuantumCircuit(1) expected.append(OneQubitOneParamGate(pi), [0]) expected_dag = circuit_to_dag(expected) pass_ = BasisTranslator(eq_lib, ['1q1p']) actual = pass_.run(dag) self.assertEqual(actual, expected_dag)
def test_partial_parameter_in_parameter_out(self): """Verify numeric query parameters will be included in returned entry.""" eq_lib = EquivalenceLibrary() theta = Parameter('theta') phi = Parameter('phi') gate = OneQubitTwoParamGate(theta, phi) equiv = QuantumCircuit(1) equiv.u(theta, phi, 0, 0) eq_lib.add_equivalence(gate, equiv) lam = Parameter('lam') gate_partial = OneQubitTwoParamGate(lam, 1.59) entry = eq_lib.get_entry(gate_partial) expected = QuantumCircuit(1) expected.u(lam, 1.59, 0, 0) self.assertEqual(len(entry), 1) self.assertEqual(entry[0], expected)
def test_unrolling_parameterized_composite_gates(self): """Verify unrolling circuits with parameterized composite gates.""" mock_sel = EquivalenceLibrary(base=std_eqlib) qr1 = QuantumRegister(2) subqc = QuantumCircuit(qr1) theta = Parameter('theta') subqc.rz(theta, qr1[0]) subqc.cx(qr1[0], qr1[1]) subqc.rz(theta, qr1[1]) # Expanding across register with shared parameter qr2 = QuantumRegister(4) qc = QuantumCircuit(qr2) sub_instr = circuit_to_instruction(subqc, equivalence_library=mock_sel) qc.append(sub_instr, [qr2[0], qr2[1]]) qc.append(sub_instr, [qr2[2], qr2[3]]) dag = circuit_to_dag(qc) pass_ = UnrollCustomDefinitions(mock_sel, ['p', 'cx']) dag = pass_.run(dag) out_dag = BasisTranslator(mock_sel, ['p', 'cx']).run(dag) # Pick up -1 * theta / 2 global phase four twice (once for each RZ -> P # in each of the two sub_instr instructions). expected = QuantumCircuit(qr2, global_phase=-1 * 4 * theta / 2.0) expected.p(theta, qr2[0]) expected.p(theta, qr2[2]) expected.cx(qr2[0], qr2[1]) expected.cx(qr2[2], qr2[3]) expected.p(theta, qr2[1]) expected.p(theta, qr2[3]) self.assertEqual(circuit_to_dag(expected), out_dag) # Expanding across register with shared parameter qc = QuantumCircuit(qr2) phi = Parameter('phi') gamma = Parameter('gamma') sub_instr = circuit_to_instruction(subqc, {theta: phi}, mock_sel) qc.append(sub_instr, [qr2[0], qr2[1]]) sub_instr = circuit_to_instruction(subqc, {theta: gamma}, mock_sel) qc.append(sub_instr, [qr2[2], qr2[3]]) dag = circuit_to_dag(qc) pass_ = UnrollCustomDefinitions(mock_sel, ['p', 'cx']) dag = pass_.run(dag) out_dag = BasisTranslator(mock_sel, ['p', 'cx']).run(dag) expected = QuantumCircuit(qr2, global_phase=-1 * (2 * phi + 2 * gamma) / 2.0) expected.p(phi, qr2[0]) expected.p(gamma, qr2[2]) expected.cx(qr2[0], qr2[1]) expected.cx(qr2[2], qr2[3]) expected.p(phi, qr2[1]) expected.p(gamma, qr2[3]) self.assertEqual(circuit_to_dag(expected), out_dag)
def test_unrolling_parameterized_composite_gates(self): """Verify unrolling circuits with parameterized composite gates.""" mock_sel = EquivalenceLibrary(base=std_eqlib) qr1 = QuantumRegister(2) subqc = QuantumCircuit(qr1) theta = Parameter('theta') subqc.rz(theta, qr1[0]) subqc.cx(qr1[0], qr1[1]) subqc.rz(theta, qr1[1]) # Expanding across register with shared parameter qr2 = QuantumRegister(4) qc = QuantumCircuit(qr2) sub_instr = circuit_to_instruction(subqc, equivalence_library=mock_sel) qc.append(sub_instr, [qr2[0], qr2[1]]) qc.append(sub_instr, [qr2[2], qr2[3]]) dag = circuit_to_dag(qc) pass_ = UnrollCustomDefinitions(mock_sel, ['u1', 'cx']) dag = pass_.run(dag) out_dag = BasisTranslator(mock_sel, ['u1', 'cx']).run(dag) expected = QuantumCircuit(qr2) expected.u1(theta, qr2[0]) expected.u1(theta, qr2[2]) expected.cx(qr2[0], qr2[1]) expected.cx(qr2[2], qr2[3]) expected.u1(theta, qr2[1]) expected.u1(theta, qr2[3]) self.assertEqual(circuit_to_dag(expected), out_dag) # Expanding across register with shared parameter qc = QuantumCircuit(qr2) phi = Parameter('phi') gamma = Parameter('gamma') sub_instr = circuit_to_instruction(subqc, {theta: phi}, mock_sel) qc.append(sub_instr, [qr2[0], qr2[1]]) sub_instr = circuit_to_instruction(subqc, {theta: gamma}, mock_sel) qc.append(sub_instr, [qr2[2], qr2[3]]) dag = circuit_to_dag(qc) pass_ = UnrollCustomDefinitions(mock_sel, ['u1', 'cx']) dag = pass_.run(dag) out_dag = BasisTranslator(mock_sel, ['u1', 'cx']).run(dag) expected = QuantumCircuit(qr2) expected.u1(phi, qr2[0]) expected.u1(gamma, qr2[2]) expected.cx(qr2[0], qr2[1]) expected.cx(qr2[2], qr2[3]) expected.u1(phi, qr2[1]) expected.u1(gamma, qr2[3]) self.assertEqual(circuit_to_dag(expected), out_dag)
def test_has_not_entry(self): """Verify we don't find an entry not defined in the library.""" eq_lib = EquivalenceLibrary() self.assertFalse(eq_lib.has_entry(OneQubitZeroParamGate()))
U2Gate, U3Gate, CU3Gate, XGate, CXGate, CCXGate, YGate, CYGate, RYYGate, ECRGate, ZGate, CZGate, ) _sel = StandardEquivalenceLibrary = EquivalenceLibrary() # Import existing gate definitions # HGate q = QuantumRegister(1, "q") def_h = QuantumCircuit(q) def_h.append(U2Gate(0, pi), [q[0]], []) _sel.add_equivalence(HGate(), def_h) # CHGate q = QuantumRegister(2, "q") def_ch = QuantumCircuit(q)
from qiskit.circuit import EquivalenceLibrary, Parameter, QuantumCircuit, QuantumRegister from qiskit.circuit.library.standard_gates import U2Gate, U3Gate, HGate, U1Gate, CCXGate, TdgGate, TGate, RZGate, CXGate from qiskit.qasm import pi eq_lib = EquivalenceLibrary() theta = Parameter('theta') phi = Parameter('phi') lamda = Parameter('lamda') u3 = U3Gate(theta, phi, lamda) u2 = U2Gate(theta, phi) u1 = U1Gate(theta) ccx = CCXGate() q = QuantumRegister(1, 'q') equiv_u3 = QuantumCircuit(q) equiv_u3.append(RZGate(phi+(pi/2)), [q[0]], []) equiv_u3.append(HGate(),[q[0]], [] ) equiv_u3.append(RZGate(theta),[q[0]], []) equiv_u3.append(HGate(), [q[0]], []) equiv_u3.append(RZGate(lamda-(pi/2)),[q[0]], 0) eq_lib.add_equivalence(u3, equiv_u3) q = QuantumRegister(1, 'q') equiv_u2 = QuantumCircuit(q) equiv_u2.append(RZGate(theta+(pi/2)), [q[0]], []) equiv_u2.append(HGate(),[q[0]], [] ) equiv_u2.append(RZGate(pi/2),[q[0]], []) equiv_u2.append(HGate(), [q[0]], [])