Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix basis_gates and coupling_map backend override in transpile() (backport #9789) #9792

Merged
merged 1 commit into from
Mar 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion qiskit/compiler/transpiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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"
Expand Down
72 changes: 72 additions & 0 deletions test/python/compiler/test_transpiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
FakeRueschlikon,
FakeBoeblingen,
FakeMumbaiV2,
FakeNairobiV2,
)
from qiskit.transpiler import Layout, CouplingMap
from qiskit.transpiler import PassManager, TransformationPass
Expand All @@ -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):
Expand Down Expand Up @@ -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)