Skip to content

Commit be36b59

Browse files
committed
Add identity removal pass to presets
This commit adds the newly added RemoveIdentityEquivalent transpiler pass to the preset pass managers for optimization levels 2 and 3. The pass is added to the init and optimization stages. For the init stage the pass is run after 3 or more qubit decomposition. While the pass works fine with 3 qubit gates, the thinking behind this placement was it seems less likely for a multi qubit identity equivalent gate to be added while components of it's decomposition are more likely to be equivalent to an identity. For the optimization stage it is added to the optimization loop. One test needed to be updated because the additional pass changes the decomposition outcome in that test. Although the output circuit is different it is equivalent to the other decomposition and the original circuit. A unitary equivalence check is added to the test to verify that.
1 parent c5a8b1d commit be36b59

3 files changed

Lines changed: 44 additions & 10 deletions

File tree

qiskit/transpiler/preset_passmanagers/builtin_plugins.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
Collect2qBlocks,
4343
ConsolidateBlocks,
4444
InverseCancellation,
45+
RemoveIdentityEquivalent,
4546
)
4647
from qiskit.transpiler.passes import Depth, Size, FixedPoint, MinimumPoint
4748
from qiskit.transpiler.passes.utils.gates_basis import GatesInBasis
@@ -156,6 +157,13 @@ def pass_manager(self, pass_manager_config, optimization_level=None) -> PassMana
156157
if pass_manager_config.routing_method != "none":
157158
init.append(ElidePermutations())
158159
init.append(RemoveDiagonalGatesBeforeMeasure())
160+
# Target not set on RemoveIdentityEquivalent because we haven't applied a Layout
161+
# yet so doing anything relative to an error rate in the target is not valid.
162+
init.append(
163+
RemoveIdentityEquivalent(
164+
approximation_degree=pass_manager_config.approximation_degree
165+
)
166+
)
159167
init.append(
160168
InverseCancellation(
161169
[
@@ -581,6 +589,10 @@ def _opt_control(property_set):
581589

582590
elif optimization_level == 2:
583591
_opt = [
592+
RemoveIdentityEquivalent(
593+
approximation_degree=pass_manager_config.approximation_degree,
594+
target=pass_manager_config.target,
595+
),
584596
Optimize1qGatesDecomposition(
585597
basis=pass_manager_config.basis_gates, target=pass_manager_config.target
586598
),
@@ -604,6 +616,10 @@ def _opt_control(property_set):
604616
plugin_config=pass_manager_config.unitary_synthesis_plugin_config,
605617
target=pass_manager_config.target,
606618
),
619+
RemoveIdentityEquivalent(
620+
approximation_degree=pass_manager_config.approximation_degree,
621+
target=pass_manager_config.target,
622+
),
607623
Optimize1qGatesDecomposition(
608624
basis=pass_manager_config.basis_gates, target=pass_manager_config.target
609625
),
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
features_transpiler:
3+
- |
4+
The :class:`.RemoveIdentityEquivalent` transpiler pass is now run as part
5+
of the preset pass managers at optimization levels 2 and 3. The pass is
6+
run in the ``init`` stage and the ``optimization`` stage, because the
7+
optimizations it applies are valid in both stages and the pass is
8+
fast to execute.

test/python/compiler/test_transpiler.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1738,21 +1738,31 @@ def test_no_infinite_loop(self, optimization_level):
17381738
seed_transpiler=42,
17391739
)
17401740

1741-
# Expect a -pi/2 global phase for the U3 to RZ/SX conversion, and
1742-
# a -0.5 * theta phase for RZ to P twice, once at theta, and once at 3 pi
1743-
# for the second and third RZ gates in the U3 decomposition.
1744-
expected = QuantumCircuit(
1745-
1, global_phase=-np.pi / 2 - 0.5 * (-0.2 + np.pi) - 0.5 * 3 * np.pi
1746-
)
1747-
expected.p(-np.pi, 0)
1748-
expected.sx(0)
1749-
expected.p(np.pi - 0.2, 0)
1750-
expected.sx(0)
1741+
if optimization_level == 1:
1742+
# Expect a -pi/2 global phase for the U3 to RZ/SX conversion, and
1743+
# a -0.5 * theta phase for RZ to P twice, once at theta, and once at 3 pi
1744+
# for the second and third RZ gates in the U3 decomposition.
1745+
expected = QuantumCircuit(
1746+
1, global_phase=-np.pi / 2 - 0.5 * (-0.2 + np.pi) - 0.5 * 3 * np.pi
1747+
)
1748+
expected.p(-np.pi, 0)
1749+
expected.sx(0)
1750+
expected.p(np.pi - 0.2, 0)
1751+
expected.sx(0)
1752+
else:
1753+
expected = QuantumCircuit(
1754+
1, global_phase=(15 * np.pi - 1) / 10
1755+
)
1756+
expected.sx(0)
1757+
expected.p(1.0 / 5.0 + np.pi, 0)
1758+
expected.sx(0)
1759+
expected.p(3 * np.pi, 0)
17511760

17521761
error_message = (
17531762
f"\nOutput circuit:\n{out!s}\n{Operator(out).data}\n"
17541763
f"Expected circuit:\n{expected!s}\n{Operator(expected).data}"
17551764
)
1765+
self.assertEqual(Operator(qc), Operator(out))
17561766
self.assertEqual(out, expected, error_message)
17571767

17581768
@data(0, 1, 2, 3)

0 commit comments

Comments
 (0)