Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix state transfer not working for GRAPE and CRAB #36

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions src/qutip_qoc/objective.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,6 @@ def __init__(self, initial, H, target, weight=1):
self.target = target
self.weight = weight

# Check if any Hamiltonian in H is a superoperator
if any(qt.issuper(H_i) for H_i in (H if isinstance(H, list) else [H])):
# Convert initial and target accordingly
self.initial = qt.to_super(self.initial)
self.target = qt.to_super(self.target)

def __getstate__(self):
"""
Extract picklable information from the objective.
Expand Down
43 changes: 42 additions & 1 deletion src/qutip_qoc/pulse_optim.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
from qutip_qoc._optimizer import _global_local_optimization
from qutip_qoc._time import _TimeInterval

import qutip as qt

try:
from qutip_qoc._rl import _RL
_rl_available = True
Expand All @@ -28,6 +30,7 @@ def optimize_pulses(
optimizer_kwargs=None,
minimizer_kwargs=None,
integrator_kwargs=None,
optimization_type=None,
):
"""
Run GOAT, JOPT, GRAPE, CRAB or RL optimization.
Expand Down Expand Up @@ -124,6 +127,11 @@ def optimize_pulses(
Options for the solver, see :obj:`MESolver.options` and
`Integrator <./classes.html#classes-ode>`_ for a list of all options.

optimization_type : str, optional
Type of optimization. By default, QuTiP-QOC will try to automatically determine
whether this is a *state transfer* or a *gate synthesis* problem. Set this
flag to ``"state_transfer"`` or ``"gate_synthesis"`` to set the mode manually.

Returns
-------
result : :class:`qutip_qoc.Result`
Expand Down Expand Up @@ -187,10 +195,43 @@ def optimize_pulses(
"maxiter": algorithm_kwargs.get("max_iter", 1000),
"gtol": algorithm_kwargs.get("min_grad", 0.0 if alg == "CRAB" else 1e-8),
}
# Iterate over objectives and convert initial and target states based on the optimization type
for objective in objectives:
H_list = objective.H if isinstance(objective.H, list) else [objective.H]
if any(qt.issuper(H_i) for H_i in H_list):
if isinstance(optimization_type, str) and optimization_type.lower() == "state_transfer":
if qt.isket(objective.initial):
objective.initial = qt.operator_to_vector(qt.ket2dm(objective.initial))
elif qt.isoper(objective.initial):
objective.initial = qt.operator_to_vector(objective.initial)
if qt.isket(objective.target):
objective.target = qt.operator_to_vector(qt.ket2dm(objective.target))
elif qt.isoper(objective.target):
objective.target = qt.operator_to_vector(objective.target)
elif isinstance(optimization_type, str) and optimization_type.lower() == "gate_synthesis":
objective.initial = qt.to_super(objective.initial)
objective.target = qt.to_super(objective.target)
elif optimization_type is None:
if qt.isoper(objective.initial) and qt.isoper(objective.target):
if np.isclose(qt.tr(objective.initial), 1) and np.isclose(qt.tr(objective.target), 1):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't work because qt.tr doesn't exist. (I am confused that the tests pass, they really do not seem to be testing much.)

Otherwise it looks good to me, but when you have fixed this could you please check that everything works by trying to run some of the example notebooks?

objective.initial = qt.operator_to_vector(objective.initial)
objective.target = qt.operator_to_vector(objective.target)
else:
objective.initial = qt.to_super(objective.initial)
objective.target = qt.to_super(objective.target)
if qt.isket(objective.initial):
objective.initial = qt.operator_to_vector(qt.ket2dm(objective.initial))
if qt.isket(objective.target):
objective.target = qt.operator_to_vector(qt.ket2dm(objective.target))

# prepare qtrl optimizers
qtrl_optimizers = []
if alg == "CRAB" or alg == "GRAPE":
dyn_type = "GEN_MAT"
for objective in objectives:
if any(qt.isoper(H_i) for H_i in (objective.H if isinstance(objective.H, list) else [objective.H])):
dyn_type = "UNIT"

if alg == "GRAPE": # algorithm specific kwargs
use_as_amps = True
minimizer_kwargs.setdefault("method", "L-BFGS-B") # gradient
Expand Down Expand Up @@ -247,7 +288,7 @@ def optimize_pulses(
"accuracy_factor": None, # deprecated
"alg_params": alg_params,
"optim_params": algorithm_kwargs.get("optim_params", None),
"dyn_type": algorithm_kwargs.get("dyn_type", "GEN_MAT"),
"dyn_type": algorithm_kwargs.get("dyn_type", dyn_type),
"dyn_params": algorithm_kwargs.get("dyn_params", None),
"prop_type": algorithm_kwargs.get(
"prop_type", "DEF"
Expand Down