-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Conversation
One or more of the following people are relevant to this code:
|
6389829
to
3ec4289
Compare
Pull Request Test Coverage Report for Build 11684850034Warning: 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
💛 - Coveralls |
3ec4289
to
6b45a62
Compare
6b45a62
to
ac46ea1
Compare
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.
ac46ea1
to
0aa0080
Compare
Rebased again, since it had a minor conflict with #13372. This also uses the new |
There was a problem hiding this 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 🙂
@@ -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)] |
There was a problem hiding this comment.
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
? 🙂
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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__
?
There was a problem hiding this comment.
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 😂
There was a problem hiding this 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 🙂
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 withSparseObservable
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
andSparseObservable.Term.pauli_base
methods perform a similar bitwise trick to do this reduction as exemplified in the documentation, but return the otherquantum_info
-native classesPauliList
andPauli
, 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
andevolve
- then potentially a follow-on PR that reorganises the class into two really separate components; a pure Rust core for Python-free consumption, and apyclass
wrapper around it.