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

Reconstruct expectation values of SparsePauliOp operators in notebooks #523

Merged
merged 2 commits into from
Apr 10, 2024

Conversation

caleb-johnson
Copy link
Collaborator

@caleb-johnson caleb-johnson commented Mar 31, 2024

Fixes #157
Fixes #489

  • Filtering the depth calls to include only non-local gates provides a more meaningful picture of depth-savings

Fixes #524

  • All circuits in notebooks will have updated style

TODO:

Problem:

In our tutorials and how-tos we treat PauliList like a list of individual observables. They aren't allowed to have a non-trivial phase (phase other than 1.0 + 0j) and they are all assumed to have weight 1.0 + 0j. This is somewhat of a misuse of PauliList, in my opinion. The PauliList class more naturally describe a single N-qubit operator with terms of complex unit magnitude and some global phase.

It would be better if we supported the primary Pauli operator class from Qiskit, SparsePauliOp; however, supporting this class alongside or in place of PauliList would be extremely disruptive to our codebase, requiring significant modifications to a sizeable portion of the source and our API.

#######################################

A few thoughts:

  • CKT.cutting is actually agnostic to the phases and coefficients of the Pauli terms in an observable, so the extra info within SparsePauliOp (e.g. the coefficients/phases) would be ignored until the very last step of reconstruction.
  • We already have a nice set of grouping utils, so we don't need that from SparsePauliOp.
  • The cutting package actually plays very seamlessly with the SparsePauliOp.paulis: PauliList field. SparsePauliOp will remove any non-trivial phase from each Pauli term and shift it to the coefficient (i.e. ("-IIXX", 1.0) becomes ("IIXX", -1.0)). This means the SparsePauliOp.paulis output will always contain Paulis with trivial phases, making it a compatible PauliList for CKT.

#########################################

Solution:

Rather than tearing up our codebase to support a class which doesn't provide us any additional flexibility in our workflows, I believe it is better to show users how to create an expectation value for their SparsePauliOp operator by passing the underlying Pauli terms to CKT and recombining the terms' expvals with their coefficients in a single-line last step of reconstruction.
final_expval = np.dot(reconstructed_expvals, observable.coeffs)

In addition to this being a very clean fix which only affects our docs, it allows us to showcase the primary operator class in Qiskit, SparsePauliOp, and it allows us to stop treating PauliLists like lists of observables in our docs, which is an abuse of the class. I believe this is a rare case of the easy fix being the correct one, and I believe we can close #157 .

##########################################

Final thought:

  • Evaluating a single SparsePauliOp for a circuit with several cuts, will already result in a large batch of circuits. The CKT workflow being set up for one list of Pauli observables at a time seems totally reasonable to me, considering the batch-size/time constraints of Qiskit Runtime. For large cutting workflows involving many SparsePauliOps (or even one large one), users can batch/group their Pauli terms however they like (likely across all their observables), they can run their experiments over the course of hours or days, and they can handle their own reconstruction at that level, using reconstruct_expectation_values as a tool within a larger reconstruction workflow (error mitigated expvals will also be reconstructed at this time). CKT will remain:

circuit/list_of_paulis --> CKT --> list_of_expvals

@coveralls
Copy link

coveralls commented Mar 31, 2024

Pull Request Test Coverage Report for Build 8638707318

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

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • 144 unchanged lines in 6 files lost coverage.
  • Overall coverage increased (+0.06%) to 95.433%

Files with Coverage Reduction New Missed Lines %
circuit_knitting/cutting/cutqc/mip_model.py 12 93.19%
circuit_knitting/utils/conversion.py 17 63.04%
circuit_knitting/cutting/cutqc/wire_cutting_evaluation.py 22 84.62%
circuit_knitting/cutting/cutqc/wire_cutting_post_processing.py 23 88.44%
circuit_knitting/cutting/cutqc/wire_cutting.py 29 91.62%
circuit_knitting/utils/metrics.py 41 52.5%
Totals Coverage Status
Change from base Build 8485494916: 0.06%
Covered Lines: 3448
Relevant Lines: 3613

💛 - Coveralls

@caleb-johnson caleb-johnson changed the title Show how to use CKT with SparsePauliOp in our docs Reconstruct expectation values of SparsePauliOp operators in notebooks Mar 31, 2024
@ibrahim-shehzad
Copy link
Collaborator

Filtering the depth calls to include only non-local gates provides a more meaningful picture of depth-savings.

It appears that the depth reduction that is reported in the tutorials is a consequence of this definition-change (for lack of a better phrase) and is not otherwise related to the change to SparsePauliOp. Is that accurate?

@caleb-johnson
Copy link
Collaborator Author

caleb-johnson commented Apr 1, 2024

Filtering the depth calls to include only non-local gates provides a more meaningful picture of depth-savings.

It appears that the depth reduction that is reported in the tutorials is a consequence of this definition-change (for lack of a better phrase) and is not otherwise related to the change to SparsePauliOp. Is that accurate?

Yes, it's such a small change, I included it here as I re-ran all the notebooks. Just included a kwarg to the depth calls.

The single-Q rotations and extra ECRs were artificially blowing up the depth. Comparing CX depth to ECR depth directly is still dubious to me since one CX compiles to two ECRs, and it's not clear that two ECRGates produces more noise than a single CX gate.

@caleb-johnson
Copy link
Collaborator Author

As discussed offline, some of the commentary about PauliList above is not quite correct. A PauliList may be used to describe discrete observables; however, showing users how to interface CKT with a SparsePauliOp is still important and beneficial for some of the reasons mentioned above.

@garrison garrison added this to the 0.7.0 milestone Apr 9, 2024
garrison
garrison previously approved these changes Apr 10, 2024
Copy link
Member

@garrison garrison left a comment

Choose a reason for hiding this comment

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

Thanks, this looks great! Very obvious in retrospect that this is how we should be demonstrating use with SparsePauliOp. I had a local branch that attempted to do this implicitly, but I think explicit is the way to go.

@caleb-johnson caleb-johnson enabled auto-merge (squash) April 10, 2024 22:51
@caleb-johnson caleb-johnson disabled auto-merge April 10, 2024 22:52
@caleb-johnson caleb-johnson merged commit 8b1dc17 into main Apr 10, 2024
11 checks passed
@caleb-johnson caleb-johnson deleted the sparse-pauli-op branch April 10, 2024 22:52
garrison added a commit that referenced this pull request Apr 11, 2024
garrison added a commit that referenced this pull request Apr 17, 2024
* Add sampling overhead table

* typos

* Fix heading level

* Rearrange table

* Fix some Sphinx cross references

* Fix Sphinx LaTeX expressions

* Add link to IBM blog post on LOCC cutting

* Tweaks to intro

* Lots of progress

* Update docs/circuit_cutting/explanation/index.rst

Co-authored-by: Ibrahim Shehzad <[email protected]>

* Rephrase LOCC vs dynamic circuits

following discussion at
#342 (comment)

* Removed `PauliList` limitation, lifted by #523

Follow up to
#342 (comment)

* Rephrase circuit cutting intro

#342 (comment)

* Remove circuit cutting graph

It's actually very similar to the one at the top of the explanation

#342 (comment)

* Update docs/circuit_cutting/explanation/index.rst

Co-authored-by: Ibrahim Shehzad <[email protected]>

* Update docs/circuit_cutting/explanation/index.rst

Co-authored-by: Ibrahim Shehzad <[email protected]>

---------

Co-authored-by: Ibrahim Shehzad <[email protected]>
mergify bot pushed a commit that referenced this pull request Apr 17, 2024
* Add sampling overhead table

* typos

* Fix heading level

* Rearrange table

* Fix some Sphinx cross references

* Fix Sphinx LaTeX expressions

* Add link to IBM blog post on LOCC cutting

* Tweaks to intro

* Lots of progress

* Update docs/circuit_cutting/explanation/index.rst

Co-authored-by: Ibrahim Shehzad <[email protected]>

* Rephrase LOCC vs dynamic circuits

following discussion at
#342 (comment)

* Removed `PauliList` limitation, lifted by #523

Follow up to
#342 (comment)

* Rephrase circuit cutting intro

#342 (comment)

* Remove circuit cutting graph

It's actually very similar to the one at the top of the explanation

#342 (comment)

* Update docs/circuit_cutting/explanation/index.rst

Co-authored-by: Ibrahim Shehzad <[email protected]>

* Update docs/circuit_cutting/explanation/index.rst

Co-authored-by: Ibrahim Shehzad <[email protected]>

---------

Co-authored-by: Ibrahim Shehzad <[email protected]>
(cherry picked from commit 299c849)

# Conflicts:
#	test/cutting/qpd/test_qpd.py
garrison added a commit that referenced this pull request Apr 17, 2024
…ckport #342) (#553)

* Add sampling overhead table and expand/update cutting explanation (#342)

* Add sampling overhead table

* typos

* Fix heading level

* Rearrange table

* Fix some Sphinx cross references

* Fix Sphinx LaTeX expressions

* Add link to IBM blog post on LOCC cutting

* Tweaks to intro

* Lots of progress

* Update docs/circuit_cutting/explanation/index.rst

Co-authored-by: Ibrahim Shehzad <[email protected]>

* Rephrase LOCC vs dynamic circuits

following discussion at
#342 (comment)

* Removed `PauliList` limitation, lifted by #523

Follow up to
#342 (comment)

* Rephrase circuit cutting intro

#342 (comment)

* Remove circuit cutting graph

It's actually very similar to the one at the top of the explanation

#342 (comment)

* Update docs/circuit_cutting/explanation/index.rst

Co-authored-by: Ibrahim Shehzad <[email protected]>

* Update docs/circuit_cutting/explanation/index.rst

Co-authored-by: Ibrahim Shehzad <[email protected]>

---------

Co-authored-by: Ibrahim Shehzad <[email protected]>
(cherry picked from commit 299c849)

# Conflicts:
#	test/cutting/qpd/test_qpd.py

* Fix conflict

---------

Co-authored-by: Jim Garrison <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants