Hosted by
Alice & Bob
aqora template dynamiqs-2025-2
test
.aqora lab -p dynamiqs-2025-2
submission/solution.ipynb
.
Fill in your solution. You can run the notebook locally to test your
solution by running the following in the terminalaqora test
aqora upload
import dynamiqs as dq
import jax
import jax.numpy as jnp
import numpy as np
import matplotlib.pyplot as plt
from tqdm import tqdm
import optax
dq.plot.mplstyle(dpi=150)
tsave, target = input
# Declare useful helpers to handle units
MHz = 2 * jnp.pi
kHz = 2 * jnp.pi * 1e-3
us = 1.0
ns = 1.0e-3
# Instanciate our bosonic annihilation operator
Na = 15 # bosonic mode truncation
a = dq.destroy(Na) & dq.eye(2)
# Qubit Pauli gate operators
X = dq.eye(Na) & dq.sigmax() # X gate
Y = dq.eye(Na) & dq.sigmay() # Y gate
Z = dq.eye(Na) & dq.sigmaz() # Z gate
# coupling between the memory and the qubit
chi_aq = 2.0 * MHz
tsave = np.linspace(0, 1 * us, 100)
target = dq.fock(Na, 2) & dq.basis(2, 0)
def simulate(drives, progress_meter=True):
# Redefine Hamiltonian with the new g2 value
H = dq.pwc(tsave, drives["memory"]["x"], a + a.dag()) # memory drive along x
H += dq.pwc(tsave, drives["memory"]["y"], 1j * (a - a.dag())) # memory drive along y
H += dq.pwc(tsave, drives["qubit"]["x"], X) # qubit drive, pauli X
H += dq.pwc(tsave, drives["qubit"]["y"], Y) # qubit drive, pauli Y
H += dq.constant(chi_aq * a.dag() @ a @ Z) # memory-qubit coupling
# initial state: memory in vacuum and qubit in |0>
psi0 = dq.coherent(Na, 0) & dq.basis(2, 0)
options = dq.Options(
progress_meter=
dq.progress_meter.TqdmProgressMeter() if progress_meter
else dq.progress_meter.NoProgressMeter(),
)
# Perform the master equation simulation
return dq.sesolve(H, psi0, tsave, options=options)
def cost_function(drive, do_sum=True):
final_states = simulate(drive, progress_meter=False).states[:, -1]
loss = (1 - abs(target.dag() @ final_states) ** 2)
if do_sum:
loss = loss.sum()
return loss
BATCH_SIZE
. Here it's set at 200, meaning that we are going to optimize on 200 candidate set of control parameters at the timeBATCH_SIZE = 200
NUM_TRAIN_STEPS = 500
MAX_AMP = 2.0 # maximum drive strength
key = jax.random.PRNGKey(42) # random number generation seed
keys = jax.random.split(key, 4)
draw = lambda key: dq.random.real(key, (BATCH_SIZE, len(tsave)-1), max=0.1)
memory_drive = dict(x=draw(keys[0]), y=draw(keys[1]))
qubit_drive = dict(x=draw(keys[2]), y=draw(keys[3]))
params = dict(memory=memory_drive, qubit=qubit_drive)
optimizer = optax.chain(
optax.adam(learning_rate=1e-2),
optax.clip(1.0)
)
opt_state = optimizer.init(params)
@jax.jit
def step(params, opt_state):
cost = cost_function(params, do_sum=False)[..., 0, 0] # log all costs
cost_grad = jax.grad(cost_function)(params) # compute costs gradient
updates, opt_state = optimizer.update(cost_grad, opt_state, params)
params = optax.apply_updates(params, updates)
return cost, params, opt_state
params_history, costs_history = [], []
for i in tqdm(range(NUM_TRAIN_STEPS), disable=False):
cost, params, opt_state = step(params, opt_state)
params_history.append(params)
costs_history.append(cost)
costs_history = np.array(costs_history)
plt.plot(costs_history.min(axis=1), label="min")
plt.plot(costs_history.mean(axis=1), label="mean")
plt.plot(costs_history.max(axis=1), label="max")
plt.legend()
# this is the index of the pulse sequence that minimizes the cost
idx_best_sequence = np.argmin(costs_history[:, -1])
res = simulate(params_history[-1]).states[idx_best_sequence]
dq.plot.wigner_mosaic(res.ptrace(0), n=15, nrows=3)
fig, axs = plt.subplots(2, 1)
memory_pulse = params_history[-1]["memory"]["x"][idx_best_sequence] + 1j * params_history[-1]["memory"]["y"][idx_best_sequence]
qubit_pulse = params_history[-1]["qubit"]["x"][idx_best_sequence] + 1j * params_history[-1]["qubit"]["y"][idx_best_sequence]
dq.plot.pwc_pulse(tsave, memory_pulse, ax=axs[0])
dq.plot.pwc_pulse(tsave, qubit_pulse, ax=axs[1])
output = dict(
memory=dict(
x=params_history[-1]["memory"]["x"][idx_best_sequence],
y=params_history[-1]["memory"]["y"][idx_best_sequence],
),
qubit=dict(
x=params_history[-1]["qubit"]["x"][idx_best_sequence],
y=params_history[-1]["qubit"]["y"][idx_best_sequence],
),
)
$ aqora upload