Skip to content

[linq] Circuit convenience methods return self (closes #408)#419

Open
999purple999 wants to merge 1 commit into
sandbox-quantum:developfrom
999purple999:fix/408-simplify-returns-self
Open

[linq] Circuit convenience methods return self (closes #408)#419
999purple999 wants to merge 1 commit into
sandbox-quantum:developfrom
999purple999:fix/408-simplify-returns-self

Conversation

@999purple999

Copy link
Copy Markdown

Closes #408.

Circuit.simplify() returns NoneType instead of an empty circuit, because the convenience wrapper splats the underlying function's result into self.__dict__ and returns nothing. Three sibling methods on Circuit have the exact same shape, so this PR fixes all four at once for consistency.

What changed

tangelo/linq/circuit.py — added return self to:

  • Circuit.simplify()
  • Circuit.remove_redundant_gates()
  • Circuit.remove_small_rotations()
  • Circuit.merge_rotations()

The two docstrings that already promised Returns: Circuit: The circuit without ... are tightened; the two that didn't get a matching Returns clause added.

tangelo/linq/tests/test_circuits.py — new regression test test_simplify_returns_circuit_when_everything_cancels that pins the exact failing one-liner from the issue body:

result = Circuit([Gate("H", 0)] * 2).simplify()
assert result is not None
assert isinstance(result, Circuit)
assert len(result._gates) == 0
assert result.width == 1

Plus analogous assertions for the other three methods.

FIX_ISSUE_408_README.md — design rationale (why return self over a separate simplified() API), full file listing.

Compatibility

The in-place semantic is preserved — these methods still mutate self.__dict__ before returning. The existing test_simplify_circuit passes unchanged because the assertions on circuit state after .simplify() are still valid.

The change enables the chainable expression form (Circuit(...).simplify().draw()) without breaking any existing code that called these methods for their side-effects and discarded the return value.

Open question for review

If you'd rather have a separate simplified() / remove_redundant_gates_copy() API (returning a new circuit, leaving the original untouched), this PR can be reworked in that direction — happy to align on whichever shape fits the linq module's broader conventions.


Francesco Pernice Botta · 999purple999

@alexfleury-sb

alexfleury-sb commented May 26, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the PR @999purple999! This is still in draft mode, so I am assuming your work is not completed yet.

Code changes are pretty much good with me. Two things:

…andbox-quantum#408)

Circuit.simplify(), .remove_redundant_gates(), .remove_small_rotations(),
and .merge_rotations() all wrap a top-level "out-of-place" function and
then splat its result back into self.__dict__. None of them returned
anything, so

    Circuit([Gate("H", 0)] * 2).simplify()

returned None even though the convenience function it wraps returns a
Circuit. Worse, two of the four methods documented "Returns: Circuit:
The circuit without ..." in their docstrings, so the documentation was
already correct and only the implementation needed to catch up.

This patch adds "return self" to all four methods, keeping the in-place
semantic (existing callers that ignore the return value behave
identically) while letting the expression form work:

    c = Circuit([Gate("H", 0)] * 2).simplify()   # now an empty Circuit
    assert isinstance(c, Circuit) and len(c._gates) == 0 and c.width == 1

Docstrings on the two methods that did not have a Returns clause
(merge_rotations, simplify) are updated to match.

A new regression test test_simplify_returns_circuit_when_everything_cancels
pins down both the original failing example and the analogous case for
the other three methods. The existing test_simplify_circuit is unchanged
and continues to pass.
@999purple999 999purple999 force-pushed the fix/408-simplify-returns-self branch from 4e172f3 to 1eb1da6 Compare May 27, 2026 15:32
@999purple999 999purple999 changed the base branch from main to develop May 27, 2026 15:32
@999purple999

Copy link
Copy Markdown
Author

Thanks @alexfleury-sb! Both points addressed in 1eb1da6:

  • Rebased onto develop (PR base also changed via gh).
  • Removed FIX_ISSUE_408_README.md from the PR.

The README content (root-cause walk-through + design rationale for return self) can be archived as a comment on #408 if helpful happy to post it there separately, just say the word. Otherwise it lives in the commit message + PR description.

Let me know if anything else needs a tweak.

@999purple999

Copy link
Copy Markdown
Author

Hi @alexfleury-sb — both changes applied in commit 1eb1da6:

  • Branch rebased onto develop (single commit, no merge of unrelated work).
  • FIX_ISSUE_408_README.md removed from the diff.

The PR is no longer marked as draft. Ready for re-review whenever you have a moment — thanks for taking the time on this one.

@alexfleury-sb alexfleury-sb marked this pull request as ready for review May 29, 2026 15:44
@alexfleury-sb alexfleury-sb self-requested a review May 29, 2026 15:45

@alexfleury-sb alexfleury-sb left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Circuit.simplify returns NoneType instead of an empty circuit

2 participants