From 268c39b2360225a164293c651fa823f643b19770 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Fri, 22 Jan 2021 13:41:42 -0500 Subject: [PATCH] Add unroll step to level2 passmanager optimization loop (#5671) This commit adds the basis translation step to the level 2 preset passmanager's optimization loop. The level 2 optimization loop runs the commutative cancellation pass which use Rx and U1 gates as part of it's optimization step which may not be in the target basis gates. This can result in a gate outside of the target basis ended up in the output. To avoid this in a general manner we need to rely on the basis translation step because we can't write a pass to do the simplified rotation in a manner compatible with any basis (especially since the target basis could be using custom gates). Fixes #5644 (cherry picked from commit 25eb58a29fe72ffe2cdd84fe254a906ba9931796) --- .../transpiler/preset_passmanagers/level2.py | 2 +- .../transpiler/test_preset_passmanagers.py | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/qiskit/transpiler/preset_passmanagers/level2.py b/qiskit/transpiler/preset_passmanagers/level2.py index 30ef2427e0b3..34293586bd53 100644 --- a/qiskit/transpiler/preset_passmanagers/level2.py +++ b/qiskit/transpiler/preset_passmanagers/level2.py @@ -201,7 +201,7 @@ def _opt_control(property_set): pm2.append(_direction_check) pm2.append(_direction, condition=_direction_condition) pm2.append(_reset) - pm2.append(_depth_check + _opt, do_while=_opt_control) + pm2.append(_depth_check + _opt + _unroll, do_while=_opt_control) if scheduling_method: pm2.append(_scheduling) diff --git a/test/python/transpiler/test_preset_passmanagers.py b/test/python/transpiler/test_preset_passmanagers.py index 61ecf9a8d709..195b6ca12c3f 100644 --- a/test/python/transpiler/test_preset_passmanagers.py +++ b/test/python/transpiler/test_preset_passmanagers.py @@ -14,6 +14,8 @@ from test import combine from ddt import ddt, data +import numpy as np + from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister from qiskit.circuit import Qubit from qiskit.compiler import transpile, assemble @@ -85,6 +87,23 @@ def test_level0_keeps_reset(self): result = transpile(circuit, basis_gates=None, optimization_level=0) self.assertEqual(result, circuit) + def test_level2_respects_basis(self): + """Test that level2 with commutative cancellation respects basis""" + qc = QuantumCircuit(3) + qc.h(0) + qc.h(1) + qc.cp(np.pi / 8, 0, 1) + qc.cp(np.pi / 4, 0, 2) + result = transpile(qc, basis_gates=['id', 'rz', 'sx', 'x', 'cx'], + optimization_level=2) + + dag = circuit_to_dag(result) + op_nodes = [node.name for node in dag.topological_op_nodes()] + # Assert no u1 or rx gates from commutative cancellation end up in + # end up in the output since they're not in the target basis gates + self.assertNotIn('u1', op_nodes) + self.assertNotIn('rx', op_nodes) + @ddt class TestTranspileLevels(QiskitTestCase):