quantumlib / qsim

Schrödinger and Schrödinger-Feynman simulators for quantum circuits.
Apache License 2.0
454 stars 151 forks source link

Bugs on 'qsim_simulator' with repetitions option #662

Open mchan90 opened 8 months ago

mchan90 commented 8 months ago

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.

95-martin-orion commented 8 months ago

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: https://github.com/quantumlib/qsim/blob/e5817518b16858e0732269b56525f72bcdb30764/lib/statespace_basic.h#L217-L225

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

sergeisakov commented 8 months ago

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

mchan90 commented 8 months ago

@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.

sergeisakov commented 8 months ago

Thank you. #663 should fix that.