Skip to content

Commit 1b0276a

Browse files
authored
Avoid triggering register/layout warning in remove_final_measurements (#16026)
`QuantumCircuit.remove_final_measurements` has always been a bit fragile because it attempts to do effectively in-place deletions of bits of metadata while leaving others intact. Since the "layout" warning is only about modifying the `qregs`, and those are untouched by `remove_final_measurements`, we know that the register modifications are at least safe here and can avoid the warning.
1 parent 12c06a7 commit 1b0276a

3 files changed

Lines changed: 34 additions & 4 deletions

File tree

qiskit/circuit/quantumcircuit.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4719,16 +4719,18 @@ def remove_final_measurements(self, inplace: bool = True) -> QuantumCircuit | No
47194719
qubits=circ._data.qubits, reserve=len(circ._data), global_phase=circ.global_phase
47204720
)
47214721

4722-
# Re-add old registers
4722+
# Re-add old registers. We avoid `add_register` since we already know the registers are
4723+
# valid, the bits exist, and we don't want to trigger the "modified the quantum registers
4724+
# with a set layout" warning.
47234725
for qreg in old_qregs:
4724-
circ.add_register(qreg)
4726+
circ._data.add_qreg(qreg)
47254727

47264728
# We must add the clbits first to preserve the original circuit
47274729
# order. This way, add_register never adds clbits and just
47284730
# creates registers that point to them.
47294731
circ.add_bits(clbits_to_add)
47304732
for creg in cregs_to_add:
4731-
circ.add_register(creg)
4733+
circ._data.add_creg(creg)
47324734

47334735
# Set circ instructions to match the new DAG
47344736
for node in new_dag.topological_op_nodes():
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
fixes:
3+
- |
4+
:meth:`.QuantumCircuit.remove_final_measurements` will no longer emit a spurious warning about
5+
trying to add registers when called on a circuit with a set layout.

test/python/circuit/test_circuit_operations.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"""Test Qiskit's QuantumCircuit class."""
1515
import copy
1616
import pickle
17+
import warnings
1718
from itertools import combinations
1819

1920
import numpy as np
@@ -37,7 +38,7 @@
3738
from qiskit.providers.fake_provider import GenericBackendV2
3839
from qiskit.providers.basic_provider import BasicSimulator
3940
from qiskit.quantum_info import Operator
40-
from qiskit.transpiler import Layout, CouplingMap
41+
from qiskit.transpiler import Layout, CouplingMap, passes
4142
from test import QiskitTestCase
4243

4344

@@ -1058,6 +1059,28 @@ def test_remove_final_measurements_parametric_global_phase(self):
10581059
qc.remove_final_measurements(inplace=True)
10591060
self.assertEqual(qc.assign_parameters({a: 1}), expected)
10601061

1062+
def test_remove_final_measurement_with_layout(self):
1063+
def apply_layout(qc):
1064+
layout = Layout(dict(zip(qc.qubits, [1, 0])))
1065+
return passes.ApplyLayout()(qc, property_set={"layout": layout})
1066+
1067+
qc = QuantumCircuit(2, 2)
1068+
qc.h(0)
1069+
qc.cx(0, 1)
1070+
qc.measure([0, 1], [0, 1])
1071+
qc = apply_layout(qc)
1072+
1073+
expected = QuantumCircuit(2)
1074+
expected.h(0)
1075+
expected.cx(0, 1)
1076+
expected = apply_layout(expected)
1077+
1078+
with warnings.catch_warnings():
1079+
warnings.filterwarnings("error", module=r"(qiskit|test)")
1080+
self.assertEqual(qc.remove_final_measurements(inplace=False), expected)
1081+
qc.remove_final_measurements(inplace=True)
1082+
self.assertEqual(qc, expected)
1083+
10611084
def test_reverse(self):
10621085
"""Test reverse method reverses but does not invert."""
10631086
qc = QuantumCircuit(2, 2)

0 commit comments

Comments
 (0)