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

Add iterator-access methods to SparseObservable #13370

Merged
merged 3 commits into from
Nov 5, 2024

Conversation

jakelishman
Copy link
Member

Summary

This adds a new related class, SparseObservable.Term to be the item type of the iteration methods, and imbibes it with the simplest mathematical binary relations with SparseObservable as the other operand.

For some reason, in my head, the methods to convert terms and observables to their corresponding Pauli basis are related to iteration? The SparseObservable.pauli_bases and SparseObservable.Term.pauli_base methods perform a similar bitwise trick to do this reduction as exemplified in the documentation, but return the other quantum_info-native classes PauliList and Pauli, respectively. These methods are expected to be used by the primitives.

Details and comments

Built on top of #13298.

There's still one more part of SparseObservable to go - apply_layout, compose and evolve - then potentially a follow-on PR that reorganises the class into two really separate components; a pure Rust core for Python-free consumption, and a pyclass wrapper around it.

@jakelishman jakelishman added on hold Can not fix yet Changelog: New Feature Include in the "Added" section of the changelog mod: quantum info Related to the Quantum Info module (States & Operators) mod: primitives Related to the Primitives module labels Oct 24, 2024
@jakelishman jakelishman added this to the 1.3.0 milestone Oct 24, 2024
@jakelishman jakelishman requested a review from a team as a code owner October 24, 2024 22:53
@qiskit-bot
Copy link
Collaborator

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

  • @Qiskit/terra-core

@coveralls
Copy link

coveralls commented Oct 24, 2024

Pull Request Test Coverage Report for Build 11684850034

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

  • 236 of 253 (93.28%) changed or added relevant lines in 1 file are covered.
  • 776 unchanged lines in 48 files lost coverage.
  • Overall coverage increased (+0.1%) to 88.789%

Changes Missing Coverage Covered Lines Changed/Added Lines %
crates/accelerate/src/sparse_observable.rs 236 253 93.28%
Files with Coverage Reduction New Missed Lines %
qiskit/circuit/library/boolean_logic/inner_product.py 1 96.0%
qiskit/transpiler/target.py 1 93.84%
crates/qasm2/src/expr.rs 1 94.02%
qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py 1 94.54%
qiskit/circuit/store.py 1 97.06%
qiskit/circuit/library/iqp.py 1 96.15%
qiskit/circuit/library/boolean_logic/quantum_or.py 1 98.08%
crates/accelerate/src/basis/basis_translator/basis_search.rs 1 99.31%
qiskit/circuit/library/boolean_logic/quantum_and.py 1 97.96%
qiskit/qasm2/export.py 1 98.48%
Totals Coverage Status
Change from base Build 11591703186: 0.1%
Covered Lines: 77006
Relevant Lines: 86729

💛 - Coveralls

@jakelishman
Copy link
Member Author

Rebased and no longer on hold.

This adds a new related class, `SparseObservable.Term` to be the item
type of the iteration methods, and imbibes it with the simplest
mathematical binary relations with `SparseObservable` as the other
operand.

For some reason, in my head, the methods to convert terms and
observables to their corresponding Pauli basis are related to iteration?
The `SparseObservable.pauli_bases` and
`SparseObservable.Term.pauli_base` methods perform a similar bitwise
trick to do this reduction as exemplified in the documentation, but
return the other `quantum_info`-native classes `PauliList` and `Pauli`,
respectively.  These methods are expected to be used by the primitives.
@jakelishman
Copy link
Member Author

Rebased again, since it had a minor conflict with #13372. This also uses the new PyReadwriteArray::make_nonwriteable method from rust-numpy==0.22.1, since we're using that now.

Copy link
Contributor

@Cryoris Cryoris left a comment

Choose a reason for hiding this comment

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

Overall LGTM, just some questions below 🙂

crates/accelerate/src/sparse_observable.rs Outdated Show resolved Hide resolved
@@ -697,7 +757,7 @@ impl From<LabelError> for PyErr {
/// observable generate only a small number of duplications, and like-term detection has additional
/// costs. If this does not fit your use cases, you can either periodically call :meth:`simplify`,
/// or discuss further APIs with us for better building of observables.
#[pyclass(module = "qiskit.quantum_info")]
#[pyclass(module = "qiskit.quantum_info", sequence)]
Copy link
Contributor

Choose a reason for hiding this comment

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

Are len and __getitem__ the only two methods we need to add to qualify this as a Sequence? 🙂

Copy link
Member Author

Choose a reason for hiding this comment

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

Python actually has two concepts of "sequence" - one at the low level (which is this one) and collections.abc.Sequence. The requirements of the C API sequence is just to have a __getitem__ that acts on sequential integers and a correct __len__. Here's the glossary term in their docs with a brief explanation: https://docs.python.org/3/glossary.html#term-sequence.

The C-API-level "sequence" (as here) implies that a few functions are filled in on the corresponding Python type object as C-level function pointers, rather than needing Python-space look-ups to do. That can make it quite a bit more efficient to interact with the object from the C level. A bit more detail here: https://docs.python.org/3/c-api/typeobj.html#c.PySequenceMethods.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok I see! And a dumb question: in the glossary it requires __len__ but here we're adding len, is that an issue?

Copy link
Member Author

Choose a reason for hiding this comment

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

I see us as adding __len__?

Copy link
Contributor

Choose a reason for hiding this comment

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

Lol me too, I don't know what happened, maybe my brain parsed the double underscore into len 😂

crates/accelerate/src/sparse_observable.rs Outdated Show resolved Hide resolved
crates/accelerate/src/sparse_observable.rs Show resolved Hide resolved
crates/accelerate/src/sparse_observable.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@Cryoris Cryoris left a comment

Choose a reason for hiding this comment

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

LGTM, feel free to put into the merge queue pending on the len vs __len__ question above 🙂

@Cryoris Cryoris added this pull request to the merge queue Nov 5, 2024
Merged via the queue into Qiskit:main with commit c883c26 Nov 5, 2024
17 checks passed
@jakelishman jakelishman deleted the sparse-observable/iterators branch November 5, 2024 19:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: New Feature Include in the "Added" section of the changelog mod: primitives Related to the Primitives module mod: quantum info Related to the Quantum Info module (States & Operators)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants