Skip to content

Get started

AMM (Adaptive Multi Mode) minimises a function you can only evaluate, with no gradients. You give it a starting point, a search box and the number of evaluations you can afford. It returns the best point it found.

AMM is released as the distribution amm-optimizer and imported as amm_optimizer. PyPI status: 0.3.0 on PyPI (0.2.0 yanked).

Terminal window
pip install amm-optimizer

The release 0.2.0 was withdrawn (yanked) because it imported as amm or atm and its default minimize was the original ATM sampler. From a checkout of the public repository (https://github.com/BjBodner/amm-optimizer), pip install -e . installs the development version; pip install -e ".[bench]" adds the COCO tooling used by the benchmarks.

The package is version 0.3.0 and needs Python 3.12 or newer, NumPy 2.0 or newer and SciPy 1.18 or newer, as declared in pyproject.toml of the repository. The licence is Apache-2.0.

This is the example from the home page, with its output.

import numpy as np
import amm_optimizer
def rosenbrock(x):
return float(np.sum(100 * (x[1:] - x[:-1] ** 2) ** 2 + (1 - x[:-1]) ** 2))
result = amm_optimizer.minimize(
rosenbrock, x0=np.zeros(5), bounds=(-5, 5), budget=2000, seed=0,
config=amm_optimizer.presets.get("c46"),
)
print(result.nfev, result.fun)
print(result.x.round(3))
2000 2.4585372370019567e-13
[1. 1. 1. 1. 1.]

The known optimum is x = (1, 1, 1, 1, 1) with f = 0. The output was produced by the frozen configuration c46 (config hash 2153948ebed51150). The last digits of fun depend on the number of BLAS threads the machine uses (one thread gives a different value near 1e-13); x does not change at this precision. Without the config= line the same call runs the original ATM sampler and reaches only f = 1.7 on this example.

The signature in the repository is minimize(fun, x0, budget, *, seed=None, rng=None, config=None, profile=False, bounds=None).

Argument Meaning
fun A function that takes a 1-D NumPy array and returns a number (it is passed through float). It must be deterministic.
x0 The starting point. Its length is the dimension D. The objective must be finite there, or ValueError is raised. With budget=1 the only evaluation is x0. Different starting points give different runs; the benchmarks draw them uniformly from the box.
budget The maximum number of calls to fun, at least 1. With the default accounting no more than budget calls are made, every call counts, and the best point found is kept even if the budget ends mid-step. result.nfev is the true number of calls.
bounds (lower, upper), each a scalar or one value per coordinate. Finite, with every lower bound below its upper bound. c46 and the other presets raise ValueError without it.
seed Makes the run reproducible: the same seed, objective, x0, budget and bounds give the same result on the same software. rng takes an existing numpy.random.RandomState instead.
config An ATMConfig. None means the original ATM sampler, not AMM. See the API reference.
profile True records the time spent in each named block of the algorithm in result.timings. It does not change the result.

Bounds are used by the optimizer, not enforced on your function from outside. In the code, the presets fold their samples back into the box before calling fun. In a small test with c46 (three different boxes, a budget of 300 evaluations) every point the objective received was inside the box, but that is a test, not a proof. If your function is undefined outside the box, check this on your own problem. The guides go into more detail.

minimize returns an OptimizeResult with five fields.

Field Content
x The best point found, as a NumPy array of length D.
fun The objective value at x (a Python float). It is the best value observed.
nfev The number of objective calls made.
nrestarts The number of restarts the run made.
timings None, unless profile was set.

There is no success flag, convergence message or evaluation history. The README says the run uses its whole budget, and nfev equalled budget in every test run for this page.

Budgets are best thought of as a multiple of the dimension D. The benchmarks on the results page use 10, 30, 100, 300 and 1000 times D evaluations, on 24 functions in dimensions 2, 5, 10, 20 and 40.

D 10 x D 100 x D 1000 x D
2 20 200 2000
5 50 500 5000
10 100 1000 10000
40 400 4000 40000

The example above has D = 5 and a budget of 2000, which is 400 x D. AMM reads the budget and the dimension when it chooses what to run, so a larger budget does not just mean more of the same.

Outside the tested range nothing is claimed. Budgets below 10 x D, dimensions above 40 and budgets far above 1000 x D were not benchmarked, and the field comparison stops at 1000 x D. Some development confirmations used up to 3000 x D. See the limits page for the cells where AMM loses inside the tested range.

The same point must give the same value every time. The method was tested on noiseless, continuous, box-bounded problems only. Noisy objectives are untested, and results beyond the bbob suite are not yet testedpending. See wrapping your objective.

A Colab notebook does not exist yet. It is a pending item and will be linked here when it does.

  • Guides: budget, bounds, seeds, parallel evaluation, wrapping an objective, errors.
  • API reference: every public name of version 0.3.0.
  • Reproduce: the pinned versions and commands behind the benchmark numbers.