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)