Turn optimization loops inside out
Project description
Eversion – Turning Optimization Loops Inside Out
CernML is the project of bringing numerical optimization, machine learning and reinforcement learning to the operation of the CERN accelerator complex.
CernML-COI defines common interfaces that facilitate using numerical optimization and reinforcement learning (RL) on the same optimization problems. This makes it possible to unify both approaches into a generic optimization application in the CERN Control Center.
CernML-COI-Evert defines a function evert() that turns the control flow of an
optimization loop inside out. Instead of a solve() function that calls
a callback loss = objective(params) in a loop, you get an Eversion object
from which you get params = eversion.ask() and to which you give feedback via
eversion.tell(loss). The API comes in a regular, blocking variant and an
asynchronous one. It is compatible and meant to be used with
CernML-COI-Optimizers and CernML-COI-Loops.
This repository can be found online on CERN's Gitlab.
Table of Contents
[[TOC]]
Motivation
Many optimization routines are implemented as a function called solve that takes a callback function objective and an initial argument x0. The solve function then runs a loop, potentially for a long time, and calls objective repeatedly until it has calculated a result.
>>> import numpy as np
>>> from functools import partial
...
>>> def luus_jaakola(objective, x0, annealing, bounds, seed):
... x0 = np.asanyarray(x0)
... rng = np.random.default_rng(seed)
... rate = 1.0
... lower, upper = bounds
... value = objective(x0)
... while rate > 0.01:
... max_step = min(abs(upper - x0), abs(x0 - lower))
... step = rng.uniform(lower - x0, upper - x0, x0.shape)
... x = x0 + rate * step
... new_value = objective(x0 + rate * step)
... if new_value < value:
... x0 = x
... value = new_value
... else:
... rate *= annealing
... return x0
...
>>> solve = partial(
... luus_jaakola, annealing=0.98, seed=42, bounds=(-2, 2)
... )
Because solve seizes the control flow, its caller is stuck waiting for however long it takes and cannot do anything else. This is inconvenient if the callback function is computationally expensive (it might need to do I/O) and you're writing an application that is expected to remain responsive during this time.
>>> def objective(x):
... # Imagine this function had to communicate with the
... # outside world to calculate its result.
... return 3 * x**2 - 6*x + 1
...
>>> # No intervention is possible while `solve()` runs!
>>> xbest = solve(objective, 0.0)
>>> np.isclose(xbest, 1.0, rtol=1e-3)
True
Installation
To install this package from the Acc-Py Repository, run the following line while on the CERN network:
$ pip install cernml-coi-evert
You can also install this package directly from Git:
$ pip install git+https://gitlab.cern.ch/geoff/cernml-coi-evert
Finally, you can also clone the repository first and then install it:
$ git clone https://gitlab.cern.ch/geoff/cernml-coi-evert
$ cd ./cernml-coi-evert/
$ pip install .
Quickstart
If you have a package created with [acc-py init][], add this package to your
dependencies:
REQUIREMENTS: dict = {
'core': [
'cernml-coi-evert ~= 1.0',
...
],
...
}
Use the registry APIs of the COI and of the COI Optimizers to create optimizer and optimization problem:
# Run `pip install cern_awake_env` for this particular example.
import cern_awake_env
from cernml import coi, optimizers
env = coi.make("AwakeSimEnvH-v1")
opt = optimizers.make("BOBYQA")
Then combine the two into a solve function and pass it into an eversion
context. In this context, you can call ask() and tell() in a loop:
from cernml.evert import evert
solve = optimizers.make_solve_func(opt, env)
with evert(solve, env.get_initial_params()) as eversion:
while True:
params = eversion.ask()
loss = env.compute_single_objective(params)
eversion.tell(loss)
When the optimization is finished, ask() will raise an exception that is
caught by the context. Once you have exited the context, you can proceed as
normal. Call eversion.join() to retrieve the optimization result:
result = eversion.join()
print("Optimization finished")
print(f"f({result.x}) = {result.fun} after {result.niter} iterations")
Documentation
Inside the CERN network, you can read the package documentation on the Acc-Py documentation server. The API is also documented via extensive Python docstrings.
Changelog
Stability
This package uses Semantic Versioning.
License
Except as otherwise noted, this work is licensed under either of GNU Public License, Version 3.0 or later, or European Union Public License, Version 1.2 or later, at your option. See COPYING for details.
Unless You explicitly state otherwise, any contribution intentionally submitted by You for inclusion in this Work (the Covered Work) shall be dual-licensed as above, without any additional terms or conditions.
For full authorship information, see the version control history.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cernml_coi_evert-1.1.0-py3-none-any.whl.
File metadata
- Download URL: cernml_coi_evert-1.1.0-py3-none-any.whl
- Upload date:
- Size: 26.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e5075988fb365cf0fb0e8d15b070aaf11c088523cdec909e6026934c789a78be
|
|
| MD5 |
6a06b6c9064ab373e3f2c9f3ce49e605
|
|
| BLAKE2b-256 |
a112bd85cfd53af70a159ffe68eaa3f31dae81493e083a5ddc5a6db7729f4224
|