-
Notifications
You must be signed in to change notification settings - Fork 11
Description
The following script sets up a simple example problem where a (dissipative) qubit should be transferred from the ground state to the excited state. We use GRAPE and ask for an infidelity smaller then 0.001
. We then use the optimized control returned by GRAPE to re-run the time evolution manually.
The final infidelity claimed by GRAPE is 0.0008
. The infidelity found in the manual run is 0.0038
.
A small discrepancy would be fine due to numerical inaccuracies, different integration methods etc, and small discrepancies also occur using other algorithms. However, when we ask for an infidelity of 0.001
and the result returned by GRAPE misses it by almost 300%, it seems like an issue to me.
import numpy as np
import qutip as qt
from qutip_qoc import Objective, optimize_pulses
def infidelity(state, target_state):
"""
Infidelity used for density matrices in qutip-qtrl and qutip-qoc
"""
diff = state - target_state
return np.real(diff.overlap(diff)) / (2 * target_state.norm())
# --- Setup problem ---
Hd = qt.Qobj(np.diag([1, 2]))
c_ops = [np.sqrt(0.1) * qt.sigmam()]
Hc = qt.sigmax()
Ld = qt.liouvillian(H=Hd, c_ops=c_ops)
Lc = qt.liouvillian(Hc)
L = [Ld, Lc]
initial_state = qt.fock_dm(2, 0)
target_state = qt.fock_dm(2, 1)
times = np.linspace(0, 2 * np.pi, 250)
# --- Run GRAPE ---
guess_pulse = np.sin(times)
res_grape = optimize_pulses(
objectives = Objective(initial_state, L, target_state),
control_parameters = {
"ctrl_x": {"guess": guess_pulse, "bounds": [-1, 1]},
},
tlist = times,
algorithm_kwargs = {
"alg": "GRAPE",
"fid_err_targ": 0.001,
},
)
grape_infidelity = res_grape.infidelity
# --- Manually run evolution ---
state = initial_state
dt = times[1] - times[0]
for c in res_grape.optimized_controls[0][:-1]:
propagator = ((Ld + c * Lc) * dt).expm()
state = propagator(state)
real_infidelity = infidelity(state, target_state)
# --- These should be the same ---
print(grape_infidelity)
print(real_infidelity)
assert np.isclose(grape_infidelity, real_infidelity, atol=1e-3)
Note that I do the manual evolution by just exponentiating the propagator on every time step, since GRAPE protocols are piecewise constant. Doing the manual evolution with mesolve
gives the same result as this.
This issue was discovered while creating the interactive test notebooks in #44