NVIDIA / cuda-quantum

C++ and Python support for the CUDA Quantum programming model for heterogeneous quantum-classical workflows
https://nvidia.github.io/cuda-quantum/
Other
524 stars 186 forks source link

Unexpected sampling outcome with reset operation #2202

Open Squirtle007 opened 2 months ago

Squirtle007 commented 2 months ago

Required prerequisites

Describe the bug

Some differences in the results from the cudaq.sample call are observed when the reset operation is involved, Ex. Single kernel execution for N shots vs. N kernel executions for single shot Even when the kernel and its arguments are the same. The statistics of the bitstring distributions should be similar.

Steps to reproduce the bug

HOW TO REPRODUCE The script mimics the dephasing behavior of the 1st qubit (reset is applied to the 2nd qubit in each time step):

import cudaq
import numpy as np
import matplotlib.pyplot as plt

@cudaq.kernel
def dephasing_channel(theta:float, t: int):
    q = cudaq.qvector(2)

    h(q[0])
    for _ in range(t):
        ry.ctrl(theta,q[0],q[1])
        reset(q[1]) # reset the target qubit
    h(q[0])

    # measure the ctrl qubit
    mz(q[0])

p = 0.1 # dephasing probability
theta = float(2*np.arccos(np.sqrt(1-p))) # transform the dephasing probability to the rotation angle
shots = 2048
steps = 20 # number of time steps
"""# Try 2048 shots"""

prob_0 = [] # list to store the probability of measuring 0
for t in range(steps):
    counts = cudaq.sample(dephasing_channel, theta, t, shots_count=shots)
    counts = dict(counts.items())
    prob_0.append(counts['0']/shots)

fig, ax = plt.subplots(figsize=(4,3), dpi=128)

plt.title("Try 2048 shots")
plt.plot(prob_0)
plt.ylabel("Probability")
plt.xlabel("Time")
plt.ylim(0,1.05)
plt.show()

"""# Try 1 shot 2048 times"""

prob_0 = np.zeros(steps)
for t in range(steps):
    for i in range(shots):
        counts = cudaq.sample(dephasing_channel, theta, t, shots_count=1)
        if '0' in counts:
            prob_0[t] += 1

fig, ax = plt.subplots(figsize=(4,3), dpi=128)

plt.title("Try 1 shot 2048 times")
plt.plot(prob_0/shots)
plt.ylabel("Probability")
plt.xlabel("Time")
plt.ylim(0,1.05)
plt.show()

Expected behavior

Image

Is this a regression? If it is, put the last known working version (or commit) here.

Not a regression

Environment

Suggestions

Another note, cudaq.draw currently can not visualize the reset even for the simple example:

@cudaq.kernel
def kernel():
    q = cudaq.qubit()

    x(q)
    reset(q)
    mz(q)

print(cudaq.draw(kernel))