Parameterized Shots

The Helios platform provides a function call to get the shot index. The user program can be parameterized by the shot index. The shot index can be returned in Guppy using guppylang.std.qsystem.utils.get_current_shot().

Use Case 1: RNG Seed

The seed value can be unique per shot using get_current_shot. In the code sample provided, the seed is incremented every shot. The RNG object is instantiated every shot and used to generate 32-bit random floats.

from guppylang import guppy
from guppylang.std.angles import angle
from guppylang.std.builtins import result, comptime, array
from guppylang.std.quantum import qubit, measure_array
from guppylang.std.qsystem import zz_phase
from guppylang.std.qsystem.utils import get_current_shot
from guppylang.std.qsystem.random import RNG

INIT_SEED = 0

N = 18
nlayer = 3

@guppy
def layer(
    q: array[qubit, comptime(N)],
    rng: RNG,
    index_shift: bool
) -> None:
    a = array(rng.random_float() for _ in range(comptime(N//2)))
    result("angle", a)
    for k in range(comptime(N//2)):
        i = 2 * k + int(index_shift)
        j = 2 * k + 1 + int(index_shift)
        if i >= comptime(N):
            i = i - comptime(N)
        if j >= comptime(N):
            j = j - comptime(N)
        zz_phase(q[i], q[j], angle(a[k]))

@guppy
def main() -> None:
    q_array = array(qubit() for _ in range(comptime(18)))
    rng = RNG(comptime(INIT_SEED) + get_current_shot())
    for _ in range(comptime(nlayer)):
        layer(q_array, rng, False)
        layer(q_array, rng, True)
    r_array = measure_array(q_array)
    result("mresult", r_array)
    rng.discard()

hugr_binary = main.compile()
import qnexus as qnx
import uuid

unique_suffix = uuid.uuid1()

project = qnx.projects.get_or_create("Helios-Samples")
qnx.context.set_active_project(project)

ref_hugr = qnx.hugr.upload(
    hugr_binary, 
    name=f"rng-usecase0-{unique_suffix}"
)
result_ref = qnx.start_execute_job(
    programs=[ref_hugr],
    n_shots=[1],
    backend_config=config,
    name=f"job-rng-usecase0-{unique_suffix}"
)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[3], line 4
      1 result_ref = qnx.start_execute_job(
      2     programs=[ref_hugr],
      3     n_shots=[1],
----> 4     backend_config=config,
      5     name=f"job-rng-usecase0-{unique_suffix}"
      6 )

NameError: name 'config' is not defined
qnx.jobs.wait_for(result_ref)
job_result = qnx.jobs.results(result_ref)[0].download_result()
print(job_result)

Use Case 2: Parameterized Angles

Pre-generated angles can be parameterized using the current shot index. The code sample generates a 4 Pauli Exponential primitives across 4-qubits and then measures the qubits. This process is repeated 4 times. The qubits are implictly reused via dynamic qubit allocation.

import numpy as np

from guppylang import guppy
from guppylang.std.angles import angle
from guppylang.std.quantum import cx, rz, measure_array, qubit
from guppylang.std.builtins import comptime, array
from guppylang.std.qsystem.utils import get_current_shot

P = np.random.random_sample((4, 4)) / np.pi

@guppy
def gadget(
    gate_angle: angle,
    q_array: array[qubit, 4]
) -> None:
    for i in range(3):
        cx(q_array[i], q_array[i+1])
    rz(q_array[3], gate_angle)
    for i in range(1, 4):
        cx(q_array[4-i], q_array[4-i+1])


@guppy
def main() -> None:
    params_set = comptime(P.tolist())
    shot_index = get_current_shot()
    param = array(p for p in params_set[shot_index])
    result("parameters", param)
    for _ in range(4):
        q_array = array(qubit() for _ in range(4))
        for i in range(4):
            gadget(angle(param[i]), q_array)
        outcome = measure_array(q_array)
        result("measurements", outcome)
hugr_binary = main.compile()

ref_hugr = qnx.hugr.upload(
    hugr_binary, 
    name=f"rng-usecase1-{unique_suffix}"
)
result_ref = qnx.start_execute_job(
    programs=[ref_hugr],
    n_shots=[1],
    backend_config=config,
    name=f"job-rng-usecase1-{unique_suffix}"
)
qnx.jobs.wait_for(result_ref)
job_result = qnx.jobs.results(result_ref)[0].download_result()
print(job_result)