Skip to content

Commit

Permalink
Fix build ordering of BlueprintCircuit._append (#11181) (#11183)
Browse files Browse the repository at this point in the history
`QuantumCircuit._append` is the actual append primitive and is allowed
in inner-loop appends (and for `QuantumCircuit` to assume that it's
callable from other methods), so it's important that the "ensure built"
check happens there, not in `append`.

(cherry picked from commit a2c5412)

Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
  • Loading branch information
mergify[bot] and jakelishman authored Nov 2, 2023
1 parent 88b4c07 commit 46d23c3
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 4 deletions.
4 changes: 2 additions & 2 deletions qiskit/circuit/library/blueprintcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,10 @@ def qasm(self, formatted=False, filename=None, encoding=None):
self._build()
return super().qasm(formatted, filename, encoding)

def append(self, instruction, qargs=None, cargs=None):
def _append(self, instruction, _qargs=None, _cargs=None):
if not self._is_built:
self._build()
return super().append(instruction, qargs, cargs)
return super()._append(instruction, _qargs, _cargs)

def compose(self, other, qubits=None, clbits=None, front=False, inplace=False, wrap=False):
if not self._is_built:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
fixes:
- |
:class:`.BlueprintCircuit` subclasses will now behave correctly when the semi-public method
:meth:`.QuantumCircuit._append` is used with the blueprint in an unbuilt state, *i.e.* the
circuit will be built before attempting the append.
39 changes: 37 additions & 2 deletions test/python/circuit/library/test_blueprintcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,15 @@
from ddt import ddt, data

from qiskit.test.base import QiskitTestCase
from qiskit.circuit import QuantumRegister, Parameter, QuantumCircuit, Gate, Instruction
from qiskit.circuit.library import BlueprintCircuit
from qiskit.circuit import (
QuantumRegister,
Parameter,
QuantumCircuit,
Gate,
Instruction,
CircuitInstruction,
)
from qiskit.circuit.library import BlueprintCircuit, XGate


class MockBlueprint(BlueprintCircuit):
Expand Down Expand Up @@ -139,6 +146,34 @@ def test_to_gate_and_instruction(self, method):
gate = circuit.to_instruction()
self.assertIsInstance(gate, Instruction)

def test_build_before_appends(self):
"""Test that both forms of direct append (public and semi-public) function correctly."""

class DummyBlueprint(BlueprintCircuit):
"""Dummy circuit."""

def _check_configuration(self, raise_on_failure=True):
return True

def _build(self):
super()._build()
self.z(0)

expected = QuantumCircuit(2)
expected.z(0)
expected.x(0)

qr = QuantumRegister(2, "q")
mock = DummyBlueprint()
mock.add_register(qr)
mock.append(XGate(), [qr[0]], [])
self.assertEqual(expected, mock)

mock = DummyBlueprint()
mock.add_register(qr)
mock._append(CircuitInstruction(XGate(), (qr[0],), ()))
self.assertEqual(expected, mock)


if __name__ == "__main__":
unittest.main()

0 comments on commit 46d23c3

Please sign in to comment.