Separate bounds on each control for GRAPE
Opened this issue · 0 comments
Can GRAPE have different bounds on each control?
The docstring for pulseoptim.create_pulse_optimizer
states that amp_lbound
and amp_ubound
can be a list specifying different bounds for each of the controls. But this does not work with the default alg='GRAPE'
because when the pulse_generator
is created in lines 2087-2097 in pulseoptim.py, a single pulse_generator
is used for all controls, but the bounds are still set with amp_lbound
and amp_ubound
as lists. This will fail because the PulseGen
class expects the bounds to be floats, e.g., when bounds checking in _apply_bounds_and_offset
. Having a single pulse generator also does not conceptually align with having different bounds on each control. None of this is an issue if amp_lbound
and amp_ubound
are specified as a single float for all controls, or if alg='CRAB'
is used instead because a pulse_generator
is created for each control.
The coding fix is simple, but it is unclear whether instantiating a pulse generator for each control, like in CRAB, is still valid for GRAPE.
Below is a simple example that will fail:
from qutip import identity, sigmax, sigmay, sigmaz
from qutip_qip.operations import hadamard_transform
import qutip_qtrl.pulseoptim as cpo
# Drift
H_d = sigmaz()
# Control
H_c = [sigmax(), sigmay()]
# Initial unitary
U_0 = identity(2)
# Target unitary
U_targ = hadamard_transform(N=1)
# Number of time slots
n_ts = 10
# Total time
evo_time = 10
# Bounds
amp_lbound = [-1 for _ in range(len(H_c))]
amp_ubound = [1 for _ in range(len(H_c))]
result = cpo.optimize_pulse_unitary(H_d, H_c, U_0, U_targ, n_ts, evo_time,
amp_lbound=amp_lbound, amp_ubound=amp_ubound,
alg='GRAPE')