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 equality and pickling of DAGCircuit with stretches #14000

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

kevinhartman
Copy link
Contributor

@kevinhartman kevinhartman commented Mar 11, 2025

Summary

During testing, I've found two bugs with DAGCircuit's handling of stretches:

  1. Stretch capture order should not matter in circuit equality #13998
  2. DAGCircuit does not properly pickle stretches #13999

They are fixed here.

Details and comments

I've also reworked DAGCircuit's tracking of stretches to be the same as what we do for vars. Namely, there's now just an identifier_info field (which replaces var_info) which makes it easier to detect name collisions between all identifiers in tracking, and also should make it easier to support native handling of stretches in the future.

To make things a bit cleaner, I've moved Var to lib.rs and defined a macro impl_circuit_identifier to reduce boilerplate between our Qubit, Clbit, Var, and now Stretch identifier types.

I've also moved the logic of pickling identifier info tracking from __getstate__ and __setstate__ to FromPyObject and IntoPyObject implementations.

To-do

  • It looks to me like we don't have any testing of pickling / unpickling a DAGCircuit. Can that possibly be true?

This is only really a user-facing error message when
working with DAGCircuit, since QuantumCircuit first
checks if the bits being added to it are duplicates.
And, in the case of DAGCircuit, the previous error
message was already unfriendly:

ValueError: Existing bit ShareableQubit(Owned { register: OwningRegisterInfo { name: "q16", size: 2, subclass: QUBIT }, index: 0 }) cannot be re-added in strict mode.
Tracks stretches the same way we track vars.
Also happens to fix a bug in DAG equality where
order mattered between stretch captures (it should
never have). And, fixes a serialization bug with
stretches.
@kevinhartman kevinhartman added the Changelog: None Do not include in changelog label Mar 11, 2025
@kevinhartman kevinhartman added this to the 2.0.0 milestone Mar 11, 2025
@kevinhartman kevinhartman self-assigned this Mar 11, 2025
@kevinhartman kevinhartman requested a review from a team as a code owner March 11, 2025 21:57
@qiskit-bot
Copy link
Collaborator

One or more of the following people are relevant to this code:

  • @Qiskit/terra-core

@mtreinish mtreinish added the stable backport potential The bug might be minimal and/or import enough to be port to stable label Mar 11, 2025
@coveralls
Copy link

coveralls commented Mar 11, 2025

Pull Request Test Coverage Report for Build 13819534045

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 186 of 209 (89.0%) changed or added relevant lines in 3 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.05%) to 88.161%

Changes Missing Coverage Covered Lines Changed/Added Lines %
crates/circuit/src/lib.rs 13 17 76.47%
crates/circuit/src/dag_circuit.rs 171 190 90.0%
Totals Coverage Status
Change from base Build 13816498497: 0.05%
Covered Lines: 72700
Relevant Lines: 82463

💛 - Coveralls

@mtreinish
Copy link
Member

It looks to me like we don't have any testing of pickling / unpickling a DAGCircuit. Can that possibly be true?

If we have any we get it indirectly through tests that are using multiprocessing (like transpiling > 1 circuit) because pickle will be used for IPC or deep copy which also internally uses pickle. That being said see #13980 for some explicit tests I had to add for another pickle bug that's been around since 1.3 (when we ported DAGCircuit to rust).

@kevinhartman
Copy link
Contributor Author

kevinhartman commented Mar 12, 2025

see #13980 for some explicit tests I had to add for another pickle bug that's been around since 1.3 (when we ported DAGCircuit to rust).

Great, thanks! I've added a few tests based on those here to validate that stretches are preserved after pickling and deepcopy.

I also tested vars locally, but I found that there's a bug there that predates 2.0 so those tests aren't added in this PR (we ought to address that separately):

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: None Do not include in 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.

DAGCircuit does not properly pickle stretches Stretch capture order should not matter in circuit equality
4 participants