quantumlib/qsim

Bugs on 'qsim_simulator' with repetitions option

mchan90 opened this issue · 4 comments

With very rare probability (less than 1% in my experience), qsim_simulator with repetitions fails.

For example,
run_out = qsim_simulator.run(program=circuit, repetitions=n_shot)
with n_shot=4000 fails with following error message

screenshot

Usually, I avoid this error by following fix near the line 335 of "qsim_simulator.py" file.

image

But, this is just a workaround. Please, find the origin of this problem and resolve the problem.

Thanks for filing an issue @mchan90!

From what I can gather, this error implies that 4000 repetitions were requested but raw_results only contains 3999. There doesn't appear to be anything that would reduce the size of raw_results between it being generated by the C++ libraries and it being piped into full_results.

@sergeisakov, at first glance I would guess this is related to this section of StateSpace.Sample:

qsim/lib/statespace_basic.h

Lines 217 to 225 in e581751

for (uint64_t k = 0; k < size; ++k) {
auto re = p[2 * k];
auto im = p[2 * k + 1];
csum += re * re + im * im;
while (rs[m] < csum && m < num_samples) {
bitstrings.emplace_back(k);
++m;
}
}

I could imagine cumulative floating-point errors combined with an extremal random value could cause a single sample to be skipped in this loop.

@mchan90, thank you for filling an issue. Could you share a minimal code that reproduces this error?

@sergeisakov. Thank you for reply. Here's a simple code that reproduce error.

import numpy as np
import cirq

n_qubit_circuit = 2
qr_circuit  = cirq.LineQubit.range(n_qubit_circuit)
qr          = qr_circuit[1:]
qm          = qr_circuit[0]

import qsimcirq
ncores_per_task = 1
options = {'t': ncores_per_task}

qsim_simulator = qsimcirq.QSimSimulator(options)

from typing import List
from cirq import value
def ControlledUnitary1Q(theta: List[value.TParamVal], qr_, qm_):
    # global phase : -((theta[3] + (theta[1]+theta[2])/2)/2 are added
    # compared to exact one.
    gates = cirq.Circuit()
    gates += cirq.rz((theta[3] + (theta[1]+theta[2])/2)).on(qm_)
    gates += cirq.rz(theta[2]).on(qr_).controlled_by(qm_)
    gates += cirq.ry(theta[0]).on(qr_).controlled_by(qm_)
    gates += cirq.rz(theta[1]).on(qr_).controlled_by(qm_)
    return gates
    
n_run = 10000
n_shot = 4000
for i_run in range(n_run):    
    params = np.random.uniform(0,2*np.pi,4)
    circuit = cirq.Circuit()
    circuit += cirq.H.on(qm)
    circuit += ControlledUnitary1Q(params,qr[0],qm)
    circuit += cirq.H.on(qm)
    circuit += cirq.measure(qm)
    run_out = qsim_simulator.run(program=circuit, repetitions=n_shot)
    if (i_run%1000==0):
        print(i_run,n_run)

If this does not give an error, increase n_run or run script few times, because the error comes with a rare probability.

Thank you. #663 should fix that.