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 Shots.bins() generator method #5433

Closed
albi3ro opened this issue Mar 22, 2024 · 10 comments · Fixed by #5476
Closed

Add Shots.bins() generator method #5433

albi3ro opened this issue Mar 22, 2024 · 10 comments · Fixed by #5476
Assignees
Labels
good first issue Good for newcomers

Comments

@albi3ro
Copy link
Contributor

albi3ro commented Mar 22, 2024

qml.measurements.Shots is our class for keeping track of how many shots to use in calculating measurements.

One of the reasons we need a class like this is to better interact with and support shot vectors. A shot vector is when the same measurements as calculated multiple times using subsets of the total shots. For example, shots=(1, 10, 100, 100) requests that measurements are done with 1 shot, 10 shots, 100 shots, and 100 shots again:

@qml.qnode(qml.device('default.qubit'))
def circuit():
    return qml.counts(wires=0)

circuit(shots=(1, 10, 100,100))
({'0': tensor(1, requires_grad=True)},
 {'0': tensor(10, requires_grad=True)},
 {'0': tensor(100, requires_grad=True)},
 {'0': tensor(100, requires_grad=True)})

If we calculated 211 total shots, measurement 1 would be calculated from shots 0:1, measurement 2 from 1:11, measurement 3 from 11:111, and 3 from 111:211.

This task is to add a property that makes it easy and convenient to access these ranges as "bins", a tuple of (lower_bound, upper_bound).

For example:

>>> shots = Shots((1, 10, 100, 100))
>>> shots.bins()
<generator object <genexpr> at 0x3095a5630>
>>> list(shots.bins())
[(0,1), (1,11), (11,111), (111,211)]
>>> for bin in shots.bins():
...     print(bin)
(0,1)
(1,11)
(11,111)
(111,211)

To complete this task, the contributor should:

  1. Add the bins method to Shots in pennylane/measurements/shots.py
  2. Add tests for the new method in tests/measurements/test_shots.py
  3. Add a changelog entry under Community Contributions
  4. Add your name to the list of contributors at the bottom of the changelog
  5. Make sure that all tests pass and the code adheres to our black and pylint standards
@albi3ro albi3ro added the good first issue Good for newcomers label Mar 22, 2024
@Tarun-Kumar07
Copy link
Contributor

Hey @albi3ro, would it be possible for me to work on this issue? Could you please assign it to me?

@albi3ro
Copy link
Contributor Author

albi3ro commented Apr 2, 2024

Thanks for reaching out @Tarun-Kumar07 . I've assigned you the issue.

@Tarun-Kumar07
Copy link
Contributor

Hey @albi3ro, I was wondering about the method bins. Is it part of a larger task or project?

@albi3ro
Copy link
Contributor Author

albi3ro commented Apr 2, 2024

More of something that could make things easier in the future.

An example of where this could be used is here:

Currently in devices/qubit/sampling.py, we handle shot vectors by sampling multiple times and processing the shots independently. In an ideal world, we would want to just sample once, and then process each bin separately. We made compromises due to time constraints and conceptual ease. This method would allow us to move toward the more ideal way of implementing sampling.

So a follow-on to this task would be to improve the implementation of _measure_with_samples_diagonalizing_gates.

@Tarun-Kumar07
Copy link
Contributor

Hey @albi3ro just wanted to confirm the case when there are duplicates i.e. shot quantity is repeated twice,
is below the expected behaviour

>>> shots = Shots((1, 1, 2, 3))
>>> list(shots.bins())
[(0,1), (1,2), (2,4), (4,7)]

@albi3ro
Copy link
Contributor Author

albi3ro commented Apr 4, 2024

Exactly 👍

Another quick note that the same shots class can also be created with:

>>> qml.measurements.Shots(((1,2), 2, 3))
Shots(total_shots=7, shot_vector=(ShotCopies(1 shots x 2), ShotCopies(2 shots x 1), ShotCopies(3 shots x 1)))

@Tarun-Kumar07
Copy link
Contributor

Hey @albi3ro , is there an issue for a follow up task as mentioned in this comment.
I would love to work on it :)

@albi3ro
Copy link
Contributor Author

albi3ro commented Apr 5, 2024

That'd be great. Would you like to do that a separate PR or add the change into #5476 ?

Basically, you would need to update _measure_with_samples_diagonalizing_gates and how it handles the case of partitioned shot vectors. Instead of sampling + processing many times, we sample shots.total_shots once, and then pass along individual bins to _process_single_shot and then SampleMeasurement.process_samples.

Since this would just be a change in implementation details, no tests would need to be changed or added.

@Tarun-Kumar07
Copy link
Contributor

@albi3ro , I will add it to #5476, and change the description of PR as well.
I will move it to Draft till I am back with updated implementation of _measure_with_samples_diagonalizing_gates

@Tarun-Kumar07
Copy link
Contributor

Hey @albi3ro #5476 PR is ready for review, can you please have a look at it.
Thanks :)

albi3ro added a commit that referenced this issue Apr 18, 2024
**Context:**
The current approach for sampling multiple shots involves handling shot
vectors by sampling multiple times and processing each shot
independently. However, a more efficient strategy would be to sample all
shots at once and then process each bin separately. The `shots.bins()`
method facilitates this by providing the lower and upper bounds for each
bin.

**Description of the Change:**
- The `shots.bins()` method generates a sequence of tuples, where each
tuple represents the lower and upper bounds of a bin.
- In `_measure_with_samples_diagonalizing_gates` sample once with total
number of shots and use `shots.bins()` to process each bin separately

**Benefits:**
This method is particularly useful for processing shot quantities in a
partitioned manner, as it allows for the separate handling of each bin's
range

**Possible Drawbacks:**

**Related GitHub Issues:**
Fixes #5433

---------

Co-authored-by: Christina Lee <[email protected]>
Co-authored-by: Christina Lee <[email protected]>
Co-authored-by: Nathan Killoran <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants