Skip to content

Commit

Permalink
Keep resets at beginning of circuits (#10591)
Browse files Browse the repository at this point in the history
* Keep resets at beginning of circuits

* Add reno and black

* Revert "Add reno and black"

This reverts commit ea7c1e6.

* Add note back

* Add test over all transpile levels

* black

* Update releasenotes/notes/keep-initial-resets-a5f75cb16c8edb57.yaml

Co-authored-by: Julien Gacon <[email protected]>

* fix imports

* remove unused import

* damn variable names

* remove unused import

* conflict

* consolidate tests

* unrelated change

* Change release note to "upgrade"

Co-authored-by: Luciano Bello <[email protected]>

---------

Co-authored-by: Julien Gacon <[email protected]>
Co-authored-by: Luciano Bello <[email protected]>
Co-authored-by: Jake Lishman <[email protected]>
  • Loading branch information
4 people authored Aug 24, 2023
1 parent 57137ff commit 676b329
Show file tree
Hide file tree
Showing 7 changed files with 33 additions and 19 deletions.
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@
# Custom extensions
# ---------------------------------------------------------------------------------------


def add_versions_to_config(_app, config):
"""Add a list of old documentation versions that should have links generated to them into the
context, so the theme can use them to generate a sidebar."""
Expand Down
2 changes: 0 additions & 2 deletions qiskit/transpiler/preset_passmanagers/builtin_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
from qiskit.transpiler.passes import NoiseAdaptiveLayout
from qiskit.transpiler.passes import CheckMap
from qiskit.transpiler.passes import BarrierBeforeFinalMeasurements
from qiskit.transpiler.passes import RemoveResetInZeroState
from qiskit.transpiler.passes import OptimizeSwapBeforeMeasure
from qiskit.transpiler.passes import RemoveDiagonalGatesBeforeMeasure
from qiskit.transpiler.preset_passmanagers import common
Expand Down Expand Up @@ -81,7 +80,6 @@ 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(RemoveResetInZeroState())
init.append(OptimizeSwapBeforeMeasure())
init.append(RemoveDiagonalGatesBeforeMeasure())
else:
Expand Down
4 changes: 2 additions & 2 deletions qiskit/transpiler/preset_passmanagers/level1.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ def level_1_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa
target is not None and target.get_non_global_operation_names(strict_direction=True)
):
pre_optimization = common.generate_pre_op_passmanager(
target, coupling_map, remove_reset_in_zero=True
target, coupling_map, remove_reset_in_zero=False
)
else:
pre_optimization = common.generate_pre_op_passmanager(remove_reset_in_zero=True)
pre_optimization = common.generate_pre_op_passmanager(remove_reset_in_zero=False)

optimization = plugin_manager.get_passmanager_stage(
"optimization", optimization_method, pass_manager_config, optimization_level=1
Expand Down
6 changes: 4 additions & 2 deletions qiskit/transpiler/preset_passmanagers/level2.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,11 @@ def level_2_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa
if (coupling_map and not coupling_map.is_symmetric) or (
target is not None and target.get_non_global_operation_names(strict_direction=True)
):
pre_optimization = common.generate_pre_op_passmanager(target, coupling_map, True)
pre_optimization = common.generate_pre_op_passmanager(
target, coupling_map, remove_reset_in_zero=False
)
else:
pre_optimization = common.generate_pre_op_passmanager(remove_reset_in_zero=True)
pre_optimization = common.generate_pre_op_passmanager(remove_reset_in_zero=False)

optimization = plugin_manager.get_passmanager_stage(
"optimization", optimization_method, pass_manager_config, optimization_level=2
Expand Down
6 changes: 4 additions & 2 deletions qiskit/transpiler/preset_passmanagers/level3.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,11 @@ def level_3_pass_manager(pass_manager_config: PassManagerConfig) -> StagedPassMa
if (coupling_map and not coupling_map.is_symmetric) or (
target is not None and target.get_non_global_operation_names(strict_direction=True)
):
pre_optimization = common.generate_pre_op_passmanager(target, coupling_map, True)
pre_optimization = common.generate_pre_op_passmanager(
target, coupling_map, remove_reset_in_zero=False
)
else:
pre_optimization = common.generate_pre_op_passmanager(remove_reset_in_zero=True)
pre_optimization = common.generate_pre_op_passmanager(remove_reset_in_zero=False)

sched = plugin_manager.get_passmanager_stage(
"scheduling", scheduling_method, pass_manager_config, optimization_level=3
Expand Down
6 changes: 6 additions & 0 deletions releasenotes/notes/keep-initial-resets-a5f75cb16c8edb57.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
upgrade:
- |
Disables the use of :class:`.RemoveResetInZeroState` in the preset passmanagers.
This better aligns circuits to the notion of arbitrary initial states
unless explicitly set to zeros with resets.
27 changes: 16 additions & 11 deletions test/python/compiler/test_transpiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
SXGate,
U1Gate,
U2Gate,
U3Gate,
UGate,
XGate,
)
Expand Down Expand Up @@ -802,20 +801,26 @@ def test_move_measurements(self):
)
self.assertTrue(is_last_measure)

def test_initialize_reset_should_be_removed(self):
"""The reset in front of initializer should be removed when zero state"""
@data(0, 1, 2, 3)
def test_init_resets_kept_preset_passmanagers(self, optimization_level):
"""Test initial resets kept at all preset transpilation levels"""
num_qubits = 5
qc = QuantumCircuit(num_qubits)
qc.reset(range(num_qubits))

num_resets = transpile(qc, optimization_level=optimization_level).count_ops()["reset"]
self.assertEqual(num_resets, num_qubits)

@data(0, 1, 2, 3)
def test_initialize_reset_is_not_removed(self, optimization_level):
"""The reset in front of initializer should NOT be removed at beginning"""
qr = QuantumRegister(1, "qr")
qc = QuantumCircuit(qr)
qc.initialize([1.0 / math.sqrt(2), 1.0 / math.sqrt(2)], [qr[0]])
qc.initialize([1.0 / math.sqrt(2), -1.0 / math.sqrt(2)], [qr[0]])

expected = QuantumCircuit(qr)
expected.append(U3Gate(np.pi / 2, 0, 0), [qr[0]])
expected.reset(qr[0])
expected.append(U3Gate(np.pi / 2, -np.pi, 0), [qr[0]])

after = transpile(qc, basis_gates=["reset", "u3"], optimization_level=1)
self.assertEqual(after, expected, msg=f"after:\n{after}\nexpected:\n{expected}")
after = transpile(qc, basis_gates=["reset", "u3"], optimization_level=optimization_level)
self.assertEqual(after.count_ops()["reset"], 2, msg=f"{after}\n does not have 2 resets.")

def test_initialize_FakeMelbourne(self):
"""Test that the zero-state resets are remove in a device not supporting them."""
Expand All @@ -828,7 +833,7 @@ def test_initialize_FakeMelbourne(self):
out_dag = circuit_to_dag(out)
reset_nodes = out_dag.named_nodes("reset")

self.assertEqual(reset_nodes, [])
self.assertEqual(len(reset_nodes), 3)

def test_non_standard_basis(self):
"""Test a transpilation with a non-standard basis"""
Expand Down

0 comments on commit 676b329

Please sign in to comment.