Using Krotov with QuTiP¶
The krotov
package is designed around QuTiP, a very powerful “Quantum
Toolbox” in Python. This means that all operators and states are expressed as
qutip.Qobj
quantum objects. The optimize_pulses()
interface
for Krotov’s optimization method is closely linked to the interface of QuTiP’s
central mesolve()
routine for simulating the system
dynamics of a closed or open quantum system. In particular, when setting up an
optimization, the system Hamiltonian should be represented by a nested list.
This is, a Hamiltonian of the form \(\Op{H} = \Op{H}_0 + \epsilon(t)
\Op{H}_1\) is represented as H = [H0, [H1, eps]]
where H0
and H1
are
Qobj
operators, and eps
is a function with signature
eps(t, args)
, or an array of pulse values of the length the time grid
(tlist parameter in mesolve()
). The operator can depend
on multiple controls, resulting in H = [H0, [H1, eps1], [H2, eps2], ...]
.
The central routine provided by the krotov
package is
optimize_pulses()
. It takes as input a list of objectives, which are
custom tuples of type Objective
. Each objective has an
initial_state, which is a qutip.Qobj
representing a Hilbert space
state or density matrix, an output_state, and a Hamiltonian H in the
nested-list format described above. For dissipative dynamics, it may also
include a list c_ops of collapse (Lindblad) operators, where each Lindblad
operator is a Qobj
operator directly, or, for time-dependent
Lindblad operators, a nested list.
In order to simulate the dynamics of the guess pulse, you can use
Objective.mesolve()
.
The optimization routine will automatically extract all controls that it can
find in the objectives (in any of the Hamiltonians, or any of the collapse
operators), and iteratively calculate updates to all controls in order to meet
all objectives simultaneously. The result of the optimization will be in the
returned Result
object, with a list of the optimized controls in the
optimized_controls attribute.
The Result.optimized_objectives
property contains a copy of the
objectives with the optimized_controls plugged into the Hamiltonian and
collapse operators. The dynamics under the optimized controls can then again be
simulated through Objective.mesolve()
.
While the guess controls that are in the objectives on input may be functions or an array of pulse values on the time grid, the output optimized_controls will always be an array of pulse values.