diff --git a/qiskit/transpiler/preset_passmanagers/builtin_plugins.py b/qiskit/transpiler/preset_passmanagers/builtin_plugins.py index 7e3e2611546f..3ef95eedd5e1 100644 --- a/qiskit/transpiler/preset_passmanagers/builtin_plugins.py +++ b/qiskit/transpiler/preset_passmanagers/builtin_plugins.py @@ -150,7 +150,8 @@ def pass_manager(self, pass_manager_config, optimization_level=None) -> PassMana pass_manager_config.unitary_synthesis_plugin_config, pass_manager_config.hls_config, ) - init.append(ElidePermutations()) + if pass_manager_config.routing_method != "none": + init.append(ElidePermutations()) init.append(RemoveDiagonalGatesBeforeMeasure()) init.append( InverseCancellation( diff --git a/releasenotes/notes/no-elide-routing-none-7c1bebf1283d48c0.yaml b/releasenotes/notes/no-elide-routing-none-7c1bebf1283d48c0.yaml new file mode 100644 index 000000000000..cc749f62775c --- /dev/null +++ b/releasenotes/notes/no-elide-routing-none-7c1bebf1283d48c0.yaml @@ -0,0 +1,16 @@ +--- +fixes: + - | + Fixed an issue when running :func:`.transpile` or + :meth:`~.StagedPassManager.run` on a pass manager generated by + :func:`.generate_preset_pass_manager` using ``optimization_level`` 2 or 3 + when the ``routing_method`` argument is set to ``"none"`` to explicitly + disable routing. Previously under these conditions the transpiler would run + the :class:`.ElidePermutation` pass as part of the init stage as under normal + conditions this is a useful optimization to remove :class:`.SwapGate` + and :class:`.PermutationGate` instances from the circuit. But when + ``routing_method="none"`` this optimization wasn't expected as it permutes + the circuit in a similar manner to routing which shouldn't be performed + when ``routing_method="none"``. This has been fixed by no longer + running :class:`.ElidePermutation` if ``routing_method="none"`` is set. + Fixed `#13144 `__ diff --git a/test/python/compiler/test_transpiler.py b/test/python/compiler/test_transpiler.py index a29bfc21c8bb..5307d07428f1 100644 --- a/test/python/compiler/test_transpiler.py +++ b/test/python/compiler/test_transpiler.py @@ -863,6 +863,33 @@ def test_do_not_run_gatedirection_with_symmetric_cm(self): transpile(circ, coupling_map=coupling_map, initial_layout=layout) self.assertFalse(mock_pass.called) + def test_do_not_run_elide_permutations_no_routing(self): + """Test the ElidePermutations pass doesn't run if we disable routing + + See https://github.com/Qiskit/qiskit/issues/13144 for the details and + reproduce in this test + """ + circuit_routed = QuantumCircuit(4) + circuit_routed.cx(0, 1) + circuit_routed.h(1) + circuit_routed.swap(1, 2) + circuit_routed.cx(2, 3) + pm = generate_preset_pass_manager( + basis_gates=["cx", "sx", "rz"], routing_method="none", optimization_level=2 + ) + circuit_basis = pm.run(circuit_routed) + cx_gate_qubits = [] + for instruction in circuit_basis.data: + if instruction.name == "cx": + cx_gate_qubits.append(instruction.qubits) + # If we did not Elide the existing swaps then the swap should be + # decomposed into 3 cx between 1 and 2 and there are no gates between + # 1 and 3 + self.assertIn((circuit_basis.qubits[1], circuit_basis.qubits[2]), cx_gate_qubits) + self.assertIn((circuit_basis.qubits[2], circuit_basis.qubits[1]), cx_gate_qubits) + self.assertNotIn((circuit_basis.qubits[1], circuit_basis.qubits[3]), cx_gate_qubits) + self.assertNotIn((circuit_basis.qubits[3], circuit_basis.qubits[1]), cx_gate_qubits) + def test_optimize_to_nothing(self): """Optimize gates up to fixed point in the default pipeline See https://github.com/Qiskit/qiskit-terra/issues/2035