mirror of https://github.com/Qiskit/qiskit.git
Fix handling of `Var` nodes in full-rebuild control-flow blocks (#11666)
In the control-flow builders, there are typically two ways the individual blocks can be reconstructed to be unified over the qubit and clbit resources. We generally attempt to avoid completely rebuilding the cirucits unless we have to. In cases where the resources are visited in an incompatible order, however, we have to construct new circuit objects, and in these cases, we were failing to transfer the `Var` use over completely.
This commit is contained in:
parent
3af3cf5880
commit
8c2afa965e
|
@ -174,8 +174,16 @@ def _unify_circuit_resources_rebuild( # pylint: disable=invalid-name # (it's t
|
|||
out_circuits = []
|
||||
for circuit in circuits:
|
||||
out = QuantumCircuit(
|
||||
qubits, clbits, *circuit.qregs, *circuit.cregs, global_phase=circuit.global_phase
|
||||
qubits,
|
||||
clbits,
|
||||
*circuit.qregs,
|
||||
*circuit.cregs,
|
||||
global_phase=circuit.global_phase,
|
||||
inputs=circuit.iter_input_vars(),
|
||||
captures=circuit.iter_captured_vars(),
|
||||
)
|
||||
for var in circuit.iter_declared_vars():
|
||||
out.add_uninitialized_var(var)
|
||||
for instruction in circuit.data:
|
||||
out._append(instruction)
|
||||
out_circuits.append(out)
|
||||
|
|
|
@ -3245,6 +3245,48 @@ class TestControlFlowBuilders(QiskitTestCase):
|
|||
|
||||
self.assertEqual(base, expected)
|
||||
|
||||
def test_rebuild_captures_variables_in_blocks(self):
|
||||
"""Test that when the separate blocks of a statement cause it to require a full rebuild of
|
||||
the circuit objects during builder resolution, the variables are all moved over
|
||||
correctly."""
|
||||
|
||||
a = expr.Var.new("🐍🐍🐍", types.Uint(8))
|
||||
|
||||
qc = QuantumCircuit(3, 1, inputs=[a])
|
||||
qc.measure(0, 0)
|
||||
b_outer = qc.add_var("b", False)
|
||||
with qc.switch(a) as case:
|
||||
with case(0):
|
||||
qc.cx(1, 2)
|
||||
qc.store(b_outer, True)
|
||||
with case(1):
|
||||
qc.store(qc.clbits[0], False)
|
||||
with case(2):
|
||||
# Explicit shadowing.
|
||||
b_inner = qc.add_var("b", True)
|
||||
with case(3):
|
||||
qc.store(a, expr.lift(1, a.type))
|
||||
with case(case.DEFAULT):
|
||||
qc.cx(2, 1)
|
||||
|
||||
# (inputs, captures, declares) for each block of the `switch`.
|
||||
expected = [
|
||||
([], [b_outer], []),
|
||||
([], [], []),
|
||||
([], [], [b_inner]),
|
||||
([], [a], []),
|
||||
([], [], []),
|
||||
]
|
||||
actual = [
|
||||
(
|
||||
list(block.iter_input_vars()),
|
||||
list(block.iter_captured_vars()),
|
||||
list(block.iter_declared_vars()),
|
||||
)
|
||||
for block in qc.data[-1].operation.blocks
|
||||
]
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestControlFlowBuildersFailurePaths(QiskitTestCase):
|
||||
|
|
Loading…
Reference in New Issue