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

Deprecate the BIPMapping transpiler pass in favor of external plugin #9924

Merged
merged 3 commits into from
Apr 12, 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
7 changes: 7 additions & 0 deletions qiskit/transpiler/passes/routing/algorithms/bip_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
trace_to_fid,
)
from qiskit.utils import optionals as _optionals
from qiskit.utils.deprecation import deprecate_func

logger = logging.getLogger(__name__)

Expand All @@ -41,6 +42,12 @@ class BIPMappingModel:
the solution will be stored in :attr:`solution`). None if it's not yet set.
"""

@deprecate_func(
since="0.24.0",
additional_msg="This has been replaced by a new transpiler plugin package: "
"qiskit-bip-mapper. More details can be found here: "
"https://github.com/qiskit-community/qiskit-bip-mapper",
) # pylint: disable=bad-docstring-quotes
def __init__(self, dag, coupling_map, qubit_subset, dummy_timesteps=None):
"""
Args:
Expand Down
7 changes: 7 additions & 0 deletions qiskit/transpiler/passes/routing/bip_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from qiskit.transpiler.exceptions import TranspilerError
from qiskit.transpiler.passes.routing.algorithms.bip_model import BIPMappingModel
from qiskit.transpiler.target import target_to_backend_properties, Target
from qiskit.utils.deprecation import deprecate_func

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -63,6 +64,12 @@ class BIPMapping(TransformationPass):
`arXiv:2106.06446 <https://arxiv.org/abs/2106.06446>`_
"""

@deprecate_func(
since="0.24.0",
additional_msg="This has been replaced by a new transpiler plugin package: "
"qiskit-bip-mapper. More details can be found here: "
"https://github.com/qiskit-community/qiskit-bip-mapper",
) # pylint: disable=bad-docstring-quotes
def __init__(
self,
coupling_map,
Expand Down
14 changes: 14 additions & 0 deletions releasenotes/notes/deprecate-bip-mapping-f0025c4c724e1ec8.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
deprecations:
- |
The transpiler routing pass, :class:`~.BIPMapping` has been deprecated
and will be removed in a future release. It has been replaced by an external
plugin package: ``qiskit-bip-mapper``. Details for this new package can
be found at the package's github repository:

https://github.com/qiskit-community/qiskit-bip-mapper

The pass was made into a separate plugin package for two reasons, first
the dependency on CPLEX makes it harder to use and secondly the plugin
packge more cleanly integrates with :func:`~.transpile`.

64 changes: 40 additions & 24 deletions test/python/transpiler/test_bip_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ def test_empty(self):
"""Returns the original circuit if the circuit is empty."""
coupling = CouplingMap([[0, 1]])
circuit = QuantumCircuit(2)
actual = BIPMapping(coupling)(circuit)
with self.assertWarnsRegex(DeprecationWarning, r"^The class.*is deprecated"):
actual = BIPMapping(coupling)(circuit)
self.assertEqual(circuit, actual)

def test_no_two_qubit_gates(self):
Expand All @@ -49,8 +50,8 @@ def test_no_two_qubit_gates(self):

circuit = QuantumCircuit(2)
circuit.h(0)

actual = BIPMapping(coupling)(circuit)
with self.assertWarnsRegex(DeprecationWarning, r"^The class.*is deprecated"):
actual = BIPMapping(coupling)(circuit)

self.assertEqual(circuit, actual)

Expand All @@ -70,7 +71,8 @@ def test_trivial_case(self):
circuit.h(0)
circuit.cx(2, 0)

actual = BIPMapping(coupling)(circuit)
with self.assertWarnsRegex(DeprecationWarning, r"^The class.*is deprecated"):
actual = BIPMapping(coupling)(circuit)
self.assertEqual(3, len(actual))
for inst, _, _ in actual.data: # there are no swaps
self.assertFalse(isinstance(inst, SwapGate))
Expand All @@ -82,7 +84,8 @@ def test_no_swap(self):
circuit = QuantumCircuit(3)
circuit.cx(1, 2)

actual = BIPMapping(coupling)(circuit)
with self.assertWarnsRegex(DeprecationWarning, r"^The class.*is deprecated"):
actual = BIPMapping(coupling)(circuit)

q = QuantumRegister(3, name="q")
expected = QuantumCircuit(q)
Expand All @@ -98,7 +101,8 @@ def test_ignore_initial_layout(self):
circuit.cx(1, 2)

property_set = {"layout": Layout.generate_trivial_layout(*circuit.qubits)}
actual = BIPMapping(coupling)(circuit, property_set)
with self.assertWarnsRegex(DeprecationWarning, r"^The class.*is deprecated"):
actual = BIPMapping(coupling)(circuit, property_set)

q = QuantumRegister(3, name="q")
expected = QuantumCircuit(q)
Expand All @@ -117,7 +121,8 @@ def test_can_map_measurements_correctly(self):
circuit.measure(qr[1], cr[0])
circuit.measure(qr[2], cr[1])

actual = BIPMapping(coupling)(circuit)
with self.assertWarnsRegex(DeprecationWarning, r"^The class.*is deprecated"):
actual = BIPMapping(coupling)(circuit)

q = QuantumRegister(3, "q")
expected = QuantumCircuit(q, cr)
Expand All @@ -139,7 +144,8 @@ def test_can_map_measurements_correctly_with_target(self):
circuit.measure(qr[1], cr[0])
circuit.measure(qr[2], cr[1])

actual = BIPMapping(target)(circuit)
with self.assertWarnsRegex(DeprecationWarning, r"^The class.*is deprecated"):
actual = BIPMapping(target)(circuit)

q = QuantumRegister(3, "q")
expected = QuantumCircuit(q, cr)
Expand All @@ -162,8 +168,9 @@ def test_never_modify_mapped_circuit(self):
circuit.measure(2, 1)
dag = circuit_to_dag(circuit)

mapped_dag = BIPMapping(coupling).run(dag)
remapped_dag = BIPMapping(coupling).run(mapped_dag)
with self.assertWarnsRegex(DeprecationWarning, r"^The class.*is deprecated"):
mapped_dag = BIPMapping(coupling).run(dag)
remapped_dag = BIPMapping(coupling).run(mapped_dag)

self.assertEqual(mapped_dag, remapped_dag)

Expand All @@ -177,7 +184,8 @@ def test_no_swap_multi_layer(self):
circuit.cx(qr[0], qr[3])

property_set = {}
actual = BIPMapping(coupling, objective="depth")(circuit, property_set)
with self.assertWarnsRegex(DeprecationWarning, r"^The class.*is deprecated"):
actual = BIPMapping(coupling, objective="depth")(circuit, property_set)
self.assertEqual(2, actual.depth())

CheckMap(coupling)(actual, property_set)
Expand All @@ -194,7 +202,8 @@ def test_unmappable_cnots_in_a_layer(self):
circuit.measure(qr, cr)

coupling = CouplingMap([[0, 1], [1, 2], [1, 3]]) # {0: [1], 1: [2, 3]}
actual = BIPMapping(coupling)(circuit)
with self.assertWarnsRegex(DeprecationWarning, r"^The class.*is deprecated"):
actual = BIPMapping(coupling)(circuit)

# Fails to map and returns the original circuit
self.assertEqual(circuit, actual)
Expand Down Expand Up @@ -233,7 +242,8 @@ def test_multi_cregs(self):

coupling = CouplingMap([[0, 1], [0, 2], [2, 3]]) # linear [1, 0, 2, 3]
property_set = {}
actual = BIPMapping(coupling, objective="depth")(circuit, property_set)
with self.assertWarnsRegex(DeprecationWarning, r"^The class.*is deprecated"):
actual = BIPMapping(coupling, objective="depth")(circuit, property_set)
self.assertEqual(5, actual.depth())

CheckMap(coupling)(actual, property_set)
Expand Down Expand Up @@ -264,7 +274,8 @@ def test_swaps_in_dummy_steps(self):

coupling = CouplingMap.from_line(4)
property_set = {}
actual = BIPMapping(coupling, objective="depth")(circuit, property_set)
with self.assertWarnsRegex(DeprecationWarning, r"^The class.*is deprecated"):
actual = BIPMapping(coupling, objective="depth")(circuit, property_set)
self.assertEqual(7, actual.depth())

CheckMap(coupling)(actual, property_set)
Expand Down Expand Up @@ -295,7 +306,8 @@ def test_different_number_of_virtual_and_physical_qubits(self):

coupling = CouplingMap.from_line(5)
with self.assertRaises(TranspilerError):
BIPMapping(coupling)(circuit)
with self.assertWarnsRegex(DeprecationWarning, r"^The class.*is deprecated"):
BIPMapping(coupling)(circuit)

def test_qubit_subset(self):
"""Test if `qubit_subset` option works as expected."""
Expand All @@ -306,7 +318,8 @@ def test_qubit_subset(self):

coupling = CouplingMap([(0, 1), (1, 3), (3, 2)])
qubit_subset = [0, 1, 3]
actual = BIPMapping(coupling, qubit_subset=qubit_subset)(circuit)
with self.assertWarnsRegex(DeprecationWarning, r"^The class.*is deprecated"):
actual = BIPMapping(coupling, qubit_subset=qubit_subset)(circuit)
# all used qubits are in qubit_subset
bit_indices = {bit: index for index, bit in enumerate(actual.qubits)}
for _, qargs, _ in actual.data:
Expand All @@ -323,7 +336,8 @@ def test_unconnected_qubit_subset(self):

coupling = CouplingMap([(0, 1), (1, 3), (3, 2)])
with self.assertRaises(TranspilerError):
BIPMapping(coupling, qubit_subset=[0, 1, 2])(circuit)
with self.assertWarnsRegex(DeprecationWarning, r"^The class.*is deprecated"):
BIPMapping(coupling, qubit_subset=[0, 1, 2])(circuit)

def test_objective_function(self):
"""Test if ``objective`` functions prioritize metrics correctly."""
Expand All @@ -345,13 +359,15 @@ def test_objective_function(self):
qc.dcx(0, 1)
qc.cx(2, 3)
coupling = CouplingMap(FakeLima().configuration().coupling_map)
dep_opt = BIPMapping(coupling, objective="depth", qubit_subset=[0, 1, 3, 4])(qc)
err_opt = BIPMapping(
coupling,
objective="gate_error",
qubit_subset=[0, 1, 3, 4],
backend_prop=FakeLima().properties(),
)(qc)
with self.assertWarnsRegex(DeprecationWarning, r"^The class.*is deprecated"):
dep_opt = BIPMapping(coupling, objective="depth", qubit_subset=[0, 1, 3, 4])(qc)
with self.assertWarnsRegex(DeprecationWarning, r"^The class.*is deprecated"):
err_opt = BIPMapping(
coupling,
objective="gate_error",
qubit_subset=[0, 1, 3, 4],
backend_prop=FakeLima().properties(),
)(qc)
# depth = number of su4 layers (mirrored gates have to be consolidated as single su4 gates)
pm_ = PassManager([Collect2qBlocks(), ConsolidateBlocks(basis_gates=["cx", "u"])])
dep_opt = pm_.run(dep_opt)
Expand Down