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

Expectation value of observables non diagonal in the computational basis #1489

Merged
merged 20 commits into from
Oct 31, 2024

Conversation

BrunoLiegiBastonLiegi
Copy link
Contributor

@BrunoLiegiBastonLiegi BrunoLiegiBastonLiegi commented Oct 15, 2024

Currently, our SymbolicHamiltonian.expectation_from_samples only works for observables that are composition of Z operators. To compute the expectation value of some non-Z operator, for instance XZ + YX, one has to manually rotate the measurement basis accordingly, collect the frequencies and then calculate the expectation value of a ZZ operator starting from those frequencies. Therefore, in this example, one has to measure M(0,1, basis=["X", "Z"]) first, collect the frequencies and calculate the expectation of ZZ, then re-execute a second time measuring M(0,1, basis=["Y", "X"]), get the frequencies and again calculate the expectation of ZZ. The sum of the two expectations is then the global expected value.

This PR automatizes this process, by allowing circuits to be passed as inputs to SymbolicHamiltonian.expectation_from_samples.

Checklist:

  • Reviewers confirm new code works as expected.
  • Tests are passing.
  • Coverage does not decrease.
  • Documentation is updated.

Copy link

codecov bot commented Oct 15, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 99.91%. Comparing base (e7276d8) to head (f9943d7).
Report is 261 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1489      +/-   ##
==========================================
- Coverage   99.93%   99.91%   -0.02%     
==========================================
  Files          81       81              
  Lines       11795    11804       +9     
==========================================
+ Hits        11787    11794       +7     
- Misses          8       10       +2     
Flag Coverage Δ
unittests 99.91% <100.00%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@chmwzc
Copy link
Contributor

chmwzc commented Oct 16, 2024

Resolves #852, happy to see that this functionality is getting added in :)
Also, just FYI, I implemented something like this in Qibochem here, together with the use of qubit-wise commuting measurements to reduce measurement costs (Ref: https://arxiv.org/abs/1907.03358).

@marekgluza
Copy link
Contributor

That is very cool and will be very useful for my work with @Sam-XiaoyueLi

@BrunoLiegiBastonLiegi you can request review from @Sam-XiaoyueLi and she can help add further docs or examples if needed

@BrunoLiegiBastonLiegi
Copy link
Contributor Author

@stavros11 may I trouble you with the review of this PR? I changed some things in the SymbolicHamiltonian and related objects, which I presume you first implemented.

@Sam-XiaoyueLi feel free to suggest any meaningfull example for the docs, for the moment I just made up a random observable.

@marekgluza
Copy link
Contributor

marekgluza commented Oct 27, 2024 via email

doc/source/code-examples/advancedexamples.rst Outdated Show resolved Hide resolved
src/qibo/hamiltonians/hamiltonians.py Show resolved Hide resolved
src/qibo/hamiltonians/hamiltonians.py Outdated Show resolved Hide resolved
src/qibo/hamiltonians/hamiltonians.py Outdated Show resolved Hide resolved
)
frequencies = [
result.frequencies()
for result in self.backend.execute_circuits(rotated_circuits, nshots=nshots)
Copy link
Member

Choose a reason for hiding this comment

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

I understand this is useful only for hardware execution, right? Since in simulation you could just simulate the circuit and use expectation directly, which should also be more efficient (and exact).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes I had exactly in mind hardware execution for this. But even for simulation, you wouldn't want the exact expectation from the final state (is this what you are suggesting? not sure) as this is supposed to be sample dependent.

Copy link
Member

Choose a reason for hiding this comment

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

you wouldn't want the exact expectation from the final state (is this what you are suggesting? not sure) as this is supposed to be sample dependent.

Yes, above I meant to get the exact expectation from the final state, however you can still get a sample dependent estimate by first simulating the circuit with shots, getting the samples and using expectation_from_samples. I would expect this to be faster than using expectation_from_circuit for simulation, since in the first case the "state preparation" circuit is only simulated once, while expectation_from_circuit will repeat the simulation of the same circuit for every basis.

On hardware, or if you are simulating with noise, it is probably a different story.

Copy link
Contributor Author

@BrunoLiegiBastonLiegi BrunoLiegiBastonLiegi Oct 30, 2024

Choose a reason for hiding this comment

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

Ah yeah, I see, I've been thinking about doing the state preparation first and then just measuring for simulation. To do that though, we should probably move (at least some part of) the expectation_from_circuit inside the backend, which I am not against by the way, but for the moment I decided to keep it simple. In any case, I was assuming that since execute_circuits launches several parallel jobs, if I am not mistaken, the overhead of running several copies of the same simulation would have been reduced, assuming you have many cores available.

Copy link
Member

Choose a reason for hiding this comment

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

I also think we don't need to do anything about this, since it is already available by executing the circuit manually and then calling expectation_from_samples. This is a bit more manual for the user, but it is still fairly simple and it is not the best idea to provide multiple ways (almost equally simple) to do the same thing as it would increase maintenance from our side.

src/qibo/hamiltonians/hamiltonians.py Outdated Show resolved Hide resolved
Copy link
Member

@stavros11 stavros11 left a comment

Choose a reason for hiding this comment

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

Thanks for the updates @BrunoLiegiBastonLiegi.

@BrunoLiegiBastonLiegi BrunoLiegiBastonLiegi added this pull request to the merge queue Oct 31, 2024
Merged via the queue into master with commit f37c024 Oct 31, 2024
27 checks passed
@renatomello renatomello deleted the non_diag_expv branch November 14, 2024 05:51
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.

6 participants