Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix QuantumCircuit.compose within control-flow scopes #8570

Merged
merged 5 commits into from
Aug 18, 2022

Conversation

jakelishman
Copy link
Member

Summary

Previously, QuantumCircuit.compose with inplace=True would insert
the appended instructions outside the scope due to unchecked use of
QuantumCircuit._append (and direct modification of the data
attribute). This now respects any active control-flow scopes.

Using front=True in conjunction with inplace=True within a
control-flow scope has no clear meaning, and so the behaviour is
forbidden. Emitting a new circuit (inplace=False) while in an active
scope would produce a broken circuit - the active scope would need to be
cloned to ensure equivalence, but it wouldn't be part of any
Python-managed context, so the scope could never be closed.

Details and comments

Fix #8433.

Previously, `QuantumCircuit.compose` with `inplace=True` would insert
the appended instructions outside the scope due to unchecked use of
`QuantumCircuit._append` (and direct modification of the `data`
attribute).  This now respects any active control-flow scopes.

Using `front=True` in conjunction with `inplace=True` within a
control-flow scope has no clear meaning, and so the behaviour is
forbidden.  Emitting a new circuit (`inplace=False`) while in an active
scope would produce a broken circuit - the active scope would need to be
cloned to ensure equivalence, but it wouldn't be part of any
Python-managed context, so the scope could never be closed.
@jakelishman jakelishman added the Changelog: Bugfix Include in the "Fixed" section of the changelog label Aug 17, 2022
@jakelishman jakelishman requested a review from a team as a code owner August 17, 2022 15:49
@qiskit-bot

This comment was marked as duplicate.

Copy link
Member

@mtreinish mtreinish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code LGTM, but I think the docstring update might be missing something

qiskit/circuit/quantumcircuit.py Show resolved Hide resolved
@coveralls
Copy link

coveralls commented Aug 17, 2022

Pull Request Test Coverage Report for Build 2882454557

  • 6 of 6 (100.0%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.001%) to 84.054%

Totals Coverage Status
Change from base Build 2882452141: 0.001%
Covered Lines: 56321
Relevant Lines: 67006

💛 - Coveralls

Copy link
Member

@mtreinish mtreinish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more quick question inline about the docstring

qiskit/circuit/quantumcircuit.py Outdated Show resolved Hide resolved
Copy link
Member

@mtreinish mtreinish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for fixing the docstring

@mtreinish mtreinish added stable backport potential The bug might be minimal and/or import enough to be port to stable automerge labels Aug 18, 2022
@mergify mergify bot merged commit 26ba58a into Qiskit:main Aug 18, 2022
mergify bot pushed a commit that referenced this pull request Aug 18, 2022
* Fix QuantumCircuit.compose within control-flow scopes

Previously, `QuantumCircuit.compose` with `inplace=True` would insert
the appended instructions outside the scope due to unchecked use of
`QuantumCircuit._append` (and direct modification of the `data`
attribute).  This now respects any active control-flow scopes.

Using `front=True` in conjunction with `inplace=True` within a
control-flow scope has no clear meaning, and so the behaviour is
forbidden.  Emitting a new circuit (`inplace=False`) while in an active
scope would produce a broken circuit - the active scope would need to be
cloned to ensure equivalence, but it wouldn't be part of any
Python-managed context, so the scope could never be closed.

* Finish writing documentation sentence

* Add missing docstring in test

* Add missing Sphinx directive

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
(cherry picked from commit 26ba58a)
Copy link
Contributor

@jlapeyre jlapeyre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like putting the description and constraints in one place. And making more explicit what is valid input. Eg, "must not" in place of "not possible"

The google style guide and examples (which we claim to follow) support this preference. The rule is stated here.

Here is an example in the google style guide. In this case the docstring says minimum must be a "port value greater than 1024". An exception is raised if this is violated, but there is no entry for this in the Raises section. There is an entry in Raises for an exception raised if a port is not available.

EDIT: I see this was merged while I was writing this review !

@@ -835,7 +835,8 @@ def compose(
this can be anything that :obj:`.append` will accept.
qubits (list[Qubit|int]): qubits of self to compose onto.
clbits (list[Clbit|int]): clbits of self to compose onto.
front (bool): If True, front composition will be performed (not implemented yet).
front (bool): If True, front composition will be performed. This is not possible within
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be better:

... This must not be True if a control-flow builder block is active as there is no clear meaning to this action.

Then remove the corresponding entry in the Raises section below.

@jakelishman jakelishman deleted the fix-compose-controlflow-builders branch August 18, 2022 15:04
mergify bot added a commit that referenced this pull request Aug 18, 2022
* Fix QuantumCircuit.compose within control-flow scopes

Previously, `QuantumCircuit.compose` with `inplace=True` would insert
the appended instructions outside the scope due to unchecked use of
`QuantumCircuit._append` (and direct modification of the `data`
attribute).  This now respects any active control-flow scopes.

Using `front=True` in conjunction with `inplace=True` within a
control-flow scope has no clear meaning, and so the behaviour is
forbidden.  Emitting a new circuit (`inplace=False`) while in an active
scope would produce a broken circuit - the active scope would need to be
cloned to ensure equivalence, but it wouldn't be part of any
Python-managed context, so the scope could never be closed.

* Finish writing documentation sentence

* Add missing docstring in test

* Add missing Sphinx directive

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
(cherry picked from commit 26ba58a)

Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: Bugfix Include in the "Fixed" section of the changelog stable backport potential The bug might be minimal and/or import enough to be port to stable
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ControlFlow context manager places "composed" elements outside scope
5 participants