diff --git a/qiskit/compiler/transpiler.py b/qiskit/compiler/transpiler.py index 4d82214a5e03..d8a3be860321 100644 --- a/qiskit/compiler/transpiler.py +++ b/qiskit/compiler/transpiler.py @@ -645,6 +645,11 @@ def _parse_transpile_args( timing_constraints = target.timing_constraints() if backend_properties is None: backend_properties = target_to_backend_properties(target) + # If target is not specified and any hardware constraint object is + # manually specified then do not use the target from the backend as + # it is invalidated by a custom basis gate list or a custom coupling map + elif basis_gates is None and coupling_map is None: + target = _parse_target(backend, target) basis_gates = _parse_basis_gates(basis_gates, backend) initial_layout = _parse_initial_layout(initial_layout, circuits) @@ -658,7 +663,6 @@ def _parse_transpile_args( callback = _parse_callback(callback, num_circuits) durations = _parse_instruction_durations(backend, instruction_durations, dt, circuits) timing_constraints = _parse_timing_constraints(backend, timing_constraints, num_circuits) - target = _parse_target(backend, target) if scheduling_method and any(d is None for d in durations): raise TranspilerError( "Transpiling a circuit with a scheduling method" diff --git a/test/python/compiler/test_transpiler.py b/test/python/compiler/test_transpiler.py index 8ede5702ae60..400662f30256 100644 --- a/test/python/compiler/test_transpiler.py +++ b/test/python/compiler/test_transpiler.py @@ -51,6 +51,7 @@ FakeRueschlikon, FakeBoeblingen, FakeMumbaiV2, + FakeNairobiV2, ) from qiskit.transpiler import Layout, CouplingMap from qiskit.transpiler import PassManager, TransformationPass @@ -61,6 +62,7 @@ from qiskit.transpiler.passmanager_config import PassManagerConfig from qiskit.transpiler.preset_passmanagers import level_0_pass_manager from qiskit.tools import parallel +from qiskit.pulse import InstructionScheduleMap class CustomCX(Gate): @@ -1899,3 +1901,73 @@ def run(self, dag): for qc_test in qcs_cal_added: added_cal = qc_test.calibrations["sx"][((0,), tuple())] self.assertEqual(added_cal, ref_cal) + + @data(0, 1, 2, 3) + def test_backendv2_and_basis_gates(self, opt_level): + """Test transpile() with BackendV2 and basis_gates set.""" + backend = FakeNairobiV2() + qc = QuantumCircuit(5) + qc.h(0) + qc.cz(0, 1) + qc.cz(0, 2) + qc.cz(0, 3) + qc.cz(0, 4) + qc.measure_all() + tqc = transpile( + qc, + backend=backend, + basis_gates=["u", "cz"], + optimization_level=opt_level, + seed_transpiler=12345678942, + ) + op_count = set(tqc.count_ops()) + self.assertEqual({"u", "cz", "measure", "barrier"}, op_count) + for inst in tqc.data: + if inst.operation.name not in {"u", "cz"}: + continue + qubits = tuple(tqc.find_bit(x).index for x in inst.qubits) + self.assertIn(qubits, backend.target.qargs) + + @data(0, 1, 2, 3) + def test_backendv2_and_coupling_map(self, opt_level): + """Test transpile() with custom coupling map.""" + backend = FakeNairobiV2() + qc = QuantumCircuit(5) + qc.h(0) + qc.cz(0, 1) + qc.cz(0, 2) + qc.cz(0, 3) + qc.cz(0, 4) + qc.measure_all() + cmap = CouplingMap.from_line(5, bidirectional=False) + tqc = transpile( + qc, + backend=backend, + coupling_map=cmap, + optimization_level=opt_level, + seed_transpiler=12345678942, + ) + op_count = set(tqc.count_ops()) + self.assertTrue({"rz", "sx", "x", "cx", "measure", "barrier"}.issuperset(op_count)) + for inst in tqc.data: + if len(inst.qubits) == 2: + qubit_0 = tqc.find_bit(inst.qubits[0]).index + qubit_1 = tqc.find_bit(inst.qubits[1]).index + self.assertEqual(qubit_1, qubit_0 + 1) + + @data(0, 1, 2, 3) + def test_backend_and_custom_gate(self, opt_level): + """Test transpile() with BackendV2, custom basis pulse gate.""" + backend = FakeNairobiV2() + inst_map = InstructionScheduleMap() + inst_map.add("newgate", [0, 1], pulse.ScheduleBlock()) + newgate = Gate("newgate", 2, []) + circ = QuantumCircuit(2) + circ.append(newgate, [0, 1]) + tqc = transpile( + circ, backend, inst_map=inst_map, basis_gates=["newgate"], optimization_level=opt_level + ) + self.assertEqual(len(tqc.data), 1) + self.assertEqual(tqc.data[0].operation, newgate) + qubits = tuple(tqc.find_bit(x).index for x in tqc.data[0].qubits) + self.assertIn(qubits, backend.target.qargs)