Skip to content

Commit

Permalink
fix documentation build and search
Browse files Browse the repository at this point in the history
  • Loading branch information
Patrick committed May 5, 2024
1 parent 5d226d1 commit 6c8843c
Show file tree
Hide file tree
Showing 12 changed files with 126 additions and 54 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ src/qutip_qoc/version.py

# Documentation
doc/apidoc/*.rst
doc/.DS_Store

# PyInstaller
# Usually these files are written by a python script from a template
Expand Down
26 changes: 8 additions & 18 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,19 @@
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

# Required
version: 2

# Set the version of Python and other tools you might need
formats:
- pdf

build:
os: ubuntu-22.04
tools:
python: "3.10"
apt_packages:
- pandoc
#jobs:
# pre_build:
# # Each command is executed in a new shell process
# - cd doc; python source/tutorials-website/create_tutorials_html.py
python: "mambaforge-4.10"

conda:
environment: doc/rtd-environment.yml

# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: doc/conf.py

# We recommend specifying your dependencies to enable reproducible builds:
# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: doc/requirements.txt
- method: pip
path: .
fail_on_warning: false
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# QuTiP - Quantum Optimal Control

The qutip-qoc package builds up on the `qutip-qtrl` [package](https://github.com/qutip/qutip-qtrl).
The `qutip-qoc` package builds up on the `qutip-qtrl` [package](https://github.com/qutip/qutip-qtrl).

It enhances it by providing two additional algorithms to optimize analytically defined control functions.
The first one is an extension of Gradient Optimization of Analytic conTrols [(GOAT)](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.120.150401).
Expand All @@ -12,8 +12,8 @@ gradient driven `scipy.optimize.minimize` methods.

The package also aims for a more general way of defining control problems with QuTiP and makes switching between the four control algorithms (GOAT, JOPT, and GRAPE and CRAB implemented in qutip-qtrl) very easy.

As with qutip-qtrl, the qutip-qoc package aims at providing advanced tools for the optimal control of quantum devices.
Compared to other libraries for quantum optimal control, qutip-qoc puts additional emphasis on the physics layer and the interaction with the QuTiP package.
As with `qutip-qtrl`, the `qutip-qoc` package aims at providing advanced tools for the optimal control of quantum devices.
Compared to other libraries for quantum optimal control, `qutip-qoc` puts additional emphasis on the physics layer and the interaction with the QuTiP package.
Along with the extended GOAT and JOPT algorithms the package offers support for both the CRAB and GRAPE methods defined in `qutip-qtrl`.

If you would like to know the future development plan and ideas, have a look at the [qutip roadmap and ideas](https://qutip.readthedocs.io/en/latest/development/roadmap.html).
Expand Down
2 changes: 1 addition & 1 deletion doc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ help:
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

html:
sphinx-apidoc -f -e -P -o ./apidoc/ ../src/qutip_qoc/
sphinx-apidoc -f -e -P -o ./apidoc/ ../src/qutip_qoc/ ../src/qutip_qoc/pulse.*
@$(SPHINXBUILD) -M html "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
9 changes: 5 additions & 4 deletions doc/guide/guide-control.rst
Original file line number Diff line number Diff line change
Expand Up @@ -262,15 +262,16 @@ Eventually, the optimization for a desired `fid_err_targ` can be started by call
result = qoc.optimize_pulses(
objectives=[objective], # list of objectives
control_parameters={
"p": {"guess": p_guess, "bounds": p_bounds},
"q": {"guess": q_guess, "bounds": q_bounds}
"p": {"guess": p_guess, "bounds": p_bounds},
"q": {"guess": q_guess, "bounds": q_bounds},
},
tlist=np.linspace(0, 1, 100),
algorithm_kwargs={
"alg": "GOAT",
"fid_err_targ": 0.1,
"fid_err_targ": 0.1,
"alg": "GOAT",
},
)
.. TODO: add examples
Examples for Liouvillian dynamics and multi-objective optimization will follow soon.
16 changes: 7 additions & 9 deletions doc/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,10 @@ scipy>=1.10.1
jax>=0.4.23
jaxlib>=0.4.23
qutip>=5.0.1
cython==0.29.33
sphinx==6.1.3
sphinx_rtd_theme==1.2.0
sphinxcontrib-bibtex==2.5.0
readthedocs-sphinx-search==0.2.0
cython>=0.29.33
numpydoc==1.5.0
matplotlib>=3.6.1
docutils==0.18.1
sphinxcontrib-bibtex==2.5.0
alabaster==0.7.12
Babel==2.9.1
certifi==2020.12.5
Expand All @@ -27,11 +22,14 @@ pyparsing==2.4.7
pytz==2021.1
requests==2.25.1
snowballstemmer==2.1.0
sphinxcontrib-applehelp==1.0.2
Sphinx==6.1.3
sphinx-gallery==0.12.2
sphinx-rtd-theme==1.2.1
sphinxcontrib-applehelp==1.0.3
sphinxcontrib-bibtex==2.5.0
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.0
sphinxcontrib-htmlhelp==2.0.1
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
urllib3==1.26.4
#wincertstore==0.2.1
2 changes: 1 addition & 1 deletion doc/rtd-environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ dependencies:
- scipy>=1.10.1
- jax>=0.4.23
- jaxlib>=0.4.23
- cython==0.29.33
- cython>=0.29.33
- sphinx==6.1.3
- sphinx_rtd_theme==1.2.0
- sphinxcontrib-bibtex==2.5.0
Expand Down
3 changes: 2 additions & 1 deletion src/qutip_qoc/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from .version import version as __version__ # noqa

from qutip_qoc.time import TimeInterval
from qutip_qoc.result import Result
from qutip_qoc.objective import Objective
from qutip_qoc.pulse_optim import optimize_pulses

__all__ = ["TimeInterval", "Objective", "optimize_pulses"]
__all__ = ["TimeInterval", "Result", "Objective", "optimize_pulses"]
4 changes: 2 additions & 2 deletions src/qutip_qoc/_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def min_callback(self, intermediate_result: OptimizeResult):
if intermediate_result.fun < self._result.infidelity:
if intermediate_result.fun > 0:
if self.inside_bounds(intermediate_result.x):
self._result.update(
self._result._update(
intermediate_result.fun, intermediate_result.x
)
raise StopIteration
Expand Down Expand Up @@ -164,7 +164,7 @@ def opt_callback(self, x, f, accept):
)
terminate = False
elif self.inside_bounds(x):
self._result.update(f, x)
self._result._update(f, x)

return terminate

Expand Down
39 changes: 30 additions & 9 deletions src/qutip_qoc/objective.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,40 @@ class Objective:
"""
A class for storing information about an optimization objective.
*Examples*
>>> initial = qt.basis(2, 0)
>>> target = qt.basis(2, 1)
Examples
--------
To specify an objective for GOAT, provide a gradient function::
>>> sin = lambda t, p: np.sin(p * t)
initial = qt.basis(2, 0)
target = qt.basis(2, 1)
>>> def d_sin(t, p, idx):
>>> if idx==0: return t * np.cos(t) # wrt p
>>> if idx==1: return p * np.cos(t) # wrt t
sin = lambda t, p: np.sin(p * t)
>>> H = [qt.sigmax(), [qt.sigmay(), sin, {'grad': d_sin}]]
def d_sin(t, p, idx):
if idx==0: return t * np.cos(t) # w.r.t. p
if idx==1: return p * np.cos(t) # w.r.t. t
>>> obj = Objective(initial, H, target)
H = [qt.sigmax(), [qt.sigmay(), sin, {'grad': d_sin}]]
obj = Objective(initial, H, target)
To specify an objective for JOPT, no need for gradient function::
initial = qt.basis(2, 0)
target = qt.basis(2, 1)
@jax.jit
def sin(t, p)
return jax.numpy.sin(p * t)
def d_sin(t, p, idx):
if idx==0: return t * np.cos(t) # w.r.t. p
if idx==1: return p * np.cos(t) # w.r.t. t
H = [qt.sigmax(), [qt.sigmay(), sin]]
obj = Objective(initial, H, target)
Attributes
----------
Expand Down
54 changes: 51 additions & 3 deletions src/qutip_qoc/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ class Result:
"""
Class for storing the results of a pulse control optimization run.
Attributes:
-----------
Attributes
----------
objectives : list of :class:`qutip_qoc.Objective`
List of objectives to be optimized.
Expand Down Expand Up @@ -59,6 +59,9 @@ class Result:
message : str
Reason for termination.
optimized_params : list of ndarray
List of optimized parameters.
guess_controls : list of ndarray
List of guess control pulses used to initialize the optimization.
Expand Down Expand Up @@ -161,12 +164,18 @@ def __repr__(self):

@property
def total_seconds(self):
"""
Total time in seconds the optimization took.
"""
if self._total_seconds is None:
self._total_seconds = sum(self.iter_seconds)
return self._total_seconds

@property
def optimized_params(self):
"""
Parameter values after optimization.
"""
if self._optimized_params is None:
# reshape (optimized) new_parameters array to match
# shape and type of the guess_parameters list
Expand Down Expand Up @@ -196,6 +205,9 @@ def optimized_params(self, params):

@property
def optimized_controls(self):
"""
Control pulses after optimization.
"""
if self._optimized_controls is None:
opt_ctrl = []

Expand Down Expand Up @@ -228,6 +240,9 @@ def optimized_controls(self):

@property
def guess_controls(self):
"""
Control pulses before the optimization.
"""
if self._guess_controls is None:
if self.qtrl_optimizers:
qtrl_res = self.qtrl_optimizers[0]._create_result()
Expand Down Expand Up @@ -263,6 +278,9 @@ def guess_controls(self):

@property
def optimized_H(self):
"""
Optimized Hamiltonians with optimized controls.
"""
if self._optimized_H is None:
opt_H = []

Expand Down Expand Up @@ -301,6 +319,9 @@ def optimized_H(self):

@property
def final_states(self):
"""
Evolved system states after optimization.
"""
if self._final_states is None:
states = []

Expand Down Expand Up @@ -342,24 +363,36 @@ def final_states(self):
self._final_states = states
return self._final_states

def update(self, infidelity, parameters):
def _update(self, infidelity, parameters):
"""
Used to update the result during optimization.
"""
self.infidelity = infidelity
self.new_params = parameters

def dump(self, filename):
"""
Save the result to a file.
"""
with open(filename, "wb") as dump_fh:
pickler = pickle.Pickler(dump_fh)
pickler.dump(self)

@classmethod
def load(cls, filename, objectives=None):
"""
Load a objective from a file.
"""
with open(filename, "rb") as dump_fh:
result = pickle.load(dump_fh)
result.objectives = objectives
return result

@property
def evo_full_final(self):
"""
Deprecated, use final_states[0] instead.
"""
warnings.warn(
"evo_full_final is deprecated, use final_states[0] instead",
DeprecationWarning,
Expand All @@ -368,32 +401,47 @@ def evo_full_final(self):

@property
def fid_err(self):
"""
Deprecated, use infidelity instead.
"""
warnings.warn(
"fid_err is deprecated, use infidelity instead", DeprecationWarning
)
return self.infidelity

@property
def grad_norm_final(self):
"""
Deprecated, not supported.
"""
warnings.warn(
"grad_norm_final is deprecated, it is not supported", DeprecationWarning
)
return None # not supported

@property
def termination_reason(self):
"""
Deprecated, use message instead.
"""
warnings.warn(
"termination_reason is deprecated, use message instead", DeprecationWarning
)
return self.message

@property
def num_iter(self):
"""
Deprecated, use n_iters instead.
"""
warnings.warn("num_iter is deprecated, use n_iters instead", DeprecationWarning)
return self.n_iters

@property
def wall_time(self):
"""
Deprecated, use total_seconds instead.
"""
warnings.warn(
"wall_time is deprecated, use total_seconds instead", DeprecationWarning
)
Expand Down
Loading

0 comments on commit 6c8843c

Please sign in to comment.