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

StatevectorSampler always samples the same outcomes when seed is an integer #13047

Open
timmintam opened this issue Aug 27, 2024 · 3 comments
Open
Labels
bug Something isn't working mod: primitives Related to the Primitives module

Comments

@timmintam
Copy link
Contributor

timmintam commented Aug 27, 2024

Environment

  • Qiskit version: 1.2.0
  • Python version: 3.12.2
  • Operating system: MacOS

What is happening?

Suppose you have a StatevectorSampler with the seed set to an integer. Then if you run the same circuit multiple times, it will always sample the same outcomes.

The same issue probably affects StatevectorEstimator.

How can we reproduce the issue?

from qiskit.circuit import QuantumCircuit
from qiskit.primitives.statevector_sampler import StatevectorSampler

qc = QuantumCircuit(1)
qc.h(0)
qc.measure_all()

sampler = StatevectorSampler(seed=0)
job = sampler.run(pubs=[qc, qc], shots=5)
result = job.result()
print("1st run, 1st pub:", result[0].data.meas.get_bitstrings())
print("1st run, 2nd pub:", result[1].data.meas.get_bitstrings())

job = sampler.run(pubs=[qc], shots=5)
result = job.result()
print("2nd run, 1st pub:", result[0].data.meas.get_bitstrings())

Output:

1st run, 1st pub: ['1', '0', '0', '0', '1']
1st run, 2nd pub: ['1', '0', '0', '0', '1']
2nd run, 1st pub: ['1', '0', '0', '0', '1']

What should happen?

It should give different outcomes for each pub and for each call to the run method, even if the circuits are the same.
If you set the seed to a numpy.random.Generator it has the expected behavior. For instance keeping the code snippet from above but only changing the seed as

from numpy.random import default_rng
...
sampler = StatevectorSampler(seed=default_rng(0))
...

then it will output:

1st run, 1st pub: ['1', '0', '0', '0', '1']
1st run, 2nd pub: ['1', '1', '1', '1', '1']
2nd run, 1st pub: ['1', '0', '1', '0', '1']

Any suggestions?

Currently the StatevectorSampler class stores the private attribute _seed as it is (either Generator, int or None). The run method iterates over the circuits. Inside this for loop, it fixes the seed of the statevector, which transforms the integer seed into a Generator when needed. It means the exact same Generator is instantiated each single time.
Instead we could transform an integer seed into a Generator at the initiliazation of StatevectorSampler objects, such that the attribute _seed is either a Generator or None.
For instance:

class StatevectorSampler(BaseSamplerV2):
...
    def __init__(self, *, default_shots: int = 1024, seed: np.random.Generator | int | None = None):
        ...
        self._seed = default_rng(seed) if isinstance(seed, int) else seed
@timmintam timmintam added the bug Something isn't working label Aug 27, 2024
@ElePT ElePT added the mod: primitives Related to the Primitives module label Aug 27, 2024
@ElePT
Copy link
Contributor

ElePT commented Aug 27, 2024

Good catch @timmintam, I think you are right and the generator should be set in the init, not every time users call run. And this issue extends to the StatevectorEstimator too.

@t-imamichi
Copy link
Member

As for StatevectorEstimator, it is an intentional behavior to fix #12519. See #12862 for details.

@t-imamichi
Copy link
Member

t-imamichi commented Aug 28, 2024

I recalled that I first implemented StatevectorSampler #11566 (comment) in the same way as proposed in this issue.

def __init__(self, *, seed: np.random.Generator | int | None = None):
"""
Args:
seed: The seed for random number generator.
"""
self._seed = seed
if isinstance(self._seed, np.random.Generator):
self._rng = self._seed
else:
self._rng = np.random.default_rng(self._seed)

But, I modified it in the current way to apply @chriseclectic's suggestion #11566 (review)
So, we need to discuss the int seed behavior with @chriseclectic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working mod: primitives Related to the Primitives module
Projects
None yet
Development

No branches or pull requests

3 participants