Optimize both discrete and continuous variables using just a continuous optimizer such as scipy.optimize
Project description
wrapdisc
wrapdisc is a Python 3.10 package to wrap a discrete optimization objective such that it can be optimized by a continuous optimizer such as scipy.optimize
.
It maps the discrete variables into a continuous space, and uses an in-memory cache over the discrete space.
Both discrete and continuous variables are supported, and are motivated by Ray Tune's search spaces.
Limitations
The current implementation has these limitations:
- Additional fixed parameters needed by the objective function are not supported.
- The wrapped objective function cannot be pickled, and so multiple workers cannot be used for optimization.
- An unbounded in-memory cache is used over the original objective function, imposing a memory requirement.
Links
Caption | Link |
---|---|
Repo | https://github.com/impredicative/wrapdisc/ |
Changelog | https://github.com/impredicative/wrapdisc/releases |
Package | https://pypi.org/project/wrapdisc/ |
Installation
Python ≥3.10 is required. To install, run:
pip install wrapdisc
Variables
The following classes of variables are available:
Space | Usage | Description | Examples |
---|---|---|---|
Discrete | ChoiceVar(items) | Unordered categorical | • fn(["USA", "Panama", "Cayman"]) |
Discrete | GridVar(values) | Ordinal (ordered categorical) | • fn([2, 4, 8, 16]) • fn(["good", "better", "best"]) |
Discrete | RandintVar(lower, upper) | Integer from lower to upper , both inclusive |
• fn(0, 6) • fn(3, 9) • fn(-10, 10) |
Discrete | QrandintVar(lower, upper, q) | Quantized integer from lower to upper in multiples of q |
• fn(0, 12, 3) • fn(1, 10, 2) • fn(-10, 10, 4) |
Continuous | UniformVar(lower, upper) | Float from lower to upper |
• fn(0.0, 5.11) • fn(0.2, 4.6) • fn(-10.0, 10.0) |
Continuous | QuniformVar(lower, upper, q) | Quantized float from lower to upper in multiples of q |
• fn(0.0, 5.1, 0.3) • fn(-5.1, -0.2, 0.3) |
Usage
Example:
import operator
import scipy.optimize
from wrapdisc import Objective
from wrapdisc.var import ChoiceVar, GridVar, QrandintVar, QuniformVar, RandintVar, UniformVar
def your_mixed_optimization_objective(x: tuple) -> float:
return float(sum(x_i if isinstance(x_i, (int, float)) else len(str(x_i)) for x_i in x))
wrapped_objective = Objective(
your_mixed_optimization_objective,
[
ChoiceVar(["foobar", "baz"]),
ChoiceVar([operator.index, abs, operator.invert]),
GridVar([0.01, 0.1, 1, 10, 100]),
GridVar(["disagreed", "neutral", "agreed"]),
RandintVar(-8, 10),
QrandintVar(1, 10, 2),
UniformVar(1.2, 3.4),
QuniformVar(-11.1, 9.99, 0.22),
],
)
result = scipy.optimize.differential_evolution(wrapped_objective, wrapped_objective.bounds, seed=0)
encoded_solution = result.x
decoded_solution = wrapped_objective[encoded_solution]
assert result.fun == wrapped_objective(encoded_solution)
assert result.fun == your_mixed_optimization_objective(decoded_solution)
Output:
>>> wrapped_objective.bounds
((0.0, 1.0), (0.0, 1.0), (0.0, 1.0), (0.0, 1.0), (0.0, 1.0), (-0.49999999999999994, 4.499999999999999), (-0.49999999999999994, 2.4999999999999996), (-8.499999999999998, 10.499999999999998), (1.0000000000000002, 10.999999999999998), (1.2, 3.4), (-11.109999999999998, 10.009999999999998))
>>> result
fun: 16.210000000000004
jac: array([0. , 0. , 0. , 0. , 0. ,
0. , 0. , 0. , 0. , 1.00000009,
0. ])
message: 'Optimization terminated successfully.'
nfev: 7284
nit: 43
success: True
x: array([ 0.29493233, 0.88254257, 0.12721268, 0.48978776,
0.39078759, -0.04540115, 1.87464003, -8.02943494,
1.02999311, 1.2 , -10.98560722])
>>> decoded_solution
('baz', <built-in function abs>, 0.01, 'agreed', -8, 2, 1.2, -11.0)
>>> your_mixed_optimization_objective(decoded_solution)
16.210000000000004
>>> wrapped_objective.cache_info
CacheInfo(hits=217, misses=7067, maxsize=None, currsize=7067)
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 Distribution
wrapdisc-1.0.2.tar.gz
(21.4 kB
view hashes)
Built Distribution
wrapdisc-1.0.2-py3-none-any.whl
(20.5 kB
view hashes)