rrmeister / pyQuEST

Python interface for the Quantum Exact Simulation Toolkit (QuEST)
MIT License
16 stars 4 forks source link

Sampling from vector state #3

Closed TerraVenil closed 1 month ago

TerraVenil commented 1 month ago

Hi, @rrmeister. One of the features for the backend that I am looking for is connected to sampling from a vector state. Haven't found any relevant code to this functionality in pyQuest as well as in QuEST. So in general was considering two options

rrmeister commented 1 month ago

Hi Oleksii,

that will somewhat depend on what you want to sample. If you are after just a small subset of qubits, you can use the prob_of_all_outcomes method of the Register class to get the probabilties of all possible bitstring outcomes in one go. But if you have a lot of measurement qubits, the result might become quite large. Note that if you were to measure all qubits, you will get an array the same size as the state vector.

But to say what the best approach might be, you would have to provide some more details about what exactly you are trying to do.

Cheers! Richard

TerraVenil commented 1 month ago

Nothing special, just noticed that some simulators, for example Qiskit or Qulacs, support sampling/shots functionality and were looking in QuEST something similar. For local simulations it's possible to implement sampling from a state vector having prob_of_all_outcomes as you mentioned above but in the distributed(MPI) case will require additional efforts.

rrmeister commented 1 month ago

in the distributed(MPI) case will require additional efforts

I don't quite get this comment. Are you trying to sample so many qubits that the result of prob_of_all_outcomes doesn't fit in a single node?

TerraVenil commented 1 month ago

The result of prob_of_all_outcomescan be stored and processed within a single node's memory. However, despite this, the sampling process can be parallelized using MPI so we can exploit parallelism and distribute the computational workload across multiple nodes.

rrmeister commented 1 month ago

I'm not sure the sampling itself is so computationally expensive that parallelising would speed up the computation in a meaningful way for most tasks. The calculation of the probabilities is already distributed and parallelised by the QuEST backend. Sampling from the resulting distribution should not be too pricey, but maybe I'm just not familiar enough with the application you have in mind.

TysonRayJones commented 1 month ago

Seconding Richard's understanding! Pseudorandom number generation is relatively trivial, and for non-pathological numbers of samples, is orders of magnitude faster than the distributed calculation of the probability distribution itself (through functions like prob_of_all_outcomes()). Frankly, trying to distribute the RNG itself will likely slow things down - the communication to form sample consensus between nodes might well be slower than local RNG of all samples.

Simulators providing a "get samples" utility are either making an agnostic interface for deploying the same code to real hardware (where only samples can be obtained), else providing syntactic sugar to abbreviate tiny Python code like:

from numpy.random import choice

qubits = [0, 1, 2]
probs = qureg.prob_of_all_outcomes(qubits)
samps = choice(range(len(probs)), 999, p=probs)

or something manual like:

def sample(probs):
    rand = random() # [0, 1]
    cumu = 0
    for i, prob in enumerate(probs):
        cumu += prob
        if rand < cumu:
            return i

probs = qureg.prob_of_all_outcomes(...)
samples = [sample(probs) for _ in range(1000)]

Imo the task of a simulator is to efficiently obtain the distribution for the user; an emulator might wish to further constrain users to shots. Hope this helps!