Skip to main content
Yanked

This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Consider using release 0.5.0 instead.
Reason given by maintainers: outdated and contains pi

AMM: budget-aware routing of classical solvers by online probes

AMM is a derivative-free optimizer for continuous black-box problems with a known evaluation budget and a known box. It does not run one algorithm: it spends a small, counted part of the budget on online probes (curvature, plateau, separability, kink, basin and fractal readings of the objective near the incumbent) and uses their outcomes to route the rest of the budget among quasi-Newton (SLSQP, L-BFGS-B), trust-region (COBYQA), coordinate (STEP), multistart (MLSL) and population (CMA-ES family, the ATM sampler) engines. A probe that does not fire leaves the run on a general path, so a misreading costs evaluations, not the run. Every rule reads only the dimension, the budget, the box and evaluated function values.

The method, its development protocol and its evaluation on COCO/bbob are described in the paper (citation below). The package was developed under the code name ATM; the implementation therefore lives in atm, and amm is an alias for the same objects.

Install

pip install amm-optimizer            # NumPy and SciPy only
pip install -e ".[dev]"              # from a checkout; add ",bench" for the COCO/bbob tooling

Quick start (the configuration frozen for the paper)

import numpy as np
import amm                                  # `import atm` is equivalent

def f(x):
    return float(np.sum((x - 1.0) ** 2))

result = amm.minimize(
    f,
    x0=np.zeros(10),
    budget=100 * 10,                        # maximum number of function evaluations
    seed=0,                                 # runs are deterministic given the seed
    bounds=(-5, 5),                         # required: the box (scalars or one value per coordinate)
    config=amm.presets.get("c46"),          # the frozen configuration; see docs/FREEZE_2026-10-22.md
)
print(result.x, result.fun, result.nfev)

bounds is required by this preset (it raises ValueError without it). The box is used, not enforced as a constraint: samples are folded into it before the function is called. The objective must be deterministic. Tested on noiseless, continuous, box-constrained problems with budgets of 10 to 1000 x the dimension.

Reproducing the paper. The code is that of git tag freeze-2026-10-22; the configuration hash of amm.presets.get("c46").config_hash() is 2153948ebed51150. Pre-registrations and result notes of every batch are in docs/research/batches/, and docs/FREEZE_2026-10-22.md records what was frozen and why.

Citation. See CITATION.cff (the paper's reference will be added when it is public).

Legacy ATM presets

The sections below document the original ATM sampler and the older presets (ATMConfig(), composite(), improved()); they are kept because every recorded result and test depends on them. This repository is a clean, tested re-implementation of the original ATM that reproduces its results exactly (see docs/DEVIATIONS.md).

import numpy as np
import atm

def sphere(x):
    return np.sum((x - 2) ** 2)

result = atm.minimize(sphere, x0=np.zeros(10), budget=2000, seed=0)
print(result.x, result.fun, result.nfev)

budget is the maximum number of function evaluations, and ATM uses all of them (the best point found is kept even if the budget ends mid-iteration). Pass seed= (or an rng=np.random.RandomState) for reproducible runs. A starting point where the function is NaN or infinite raises ValueError; NaN or infinite values elsewhere count as failed evaluations and never win.

The defaults reproduce the original ATM exactly (see docs/DEVIATIONS.md); ATMConfig(strict_budget=False) also restores the original's looser budget accounting.

Better results: the improved preset

If you know the search box, ATMConfig.improved() gets far more out of the same budget:

result = atm.minimize(
    sphere,
    x0=np.zeros(10),
    budget=2000,
    seed=0,
    bounds=(-5, 5),                      # scalars or one value per coordinate
    config=atm.ATMConfig.improved(),
)
print(result.fun)

The box is used, not enforced as a constraint: samples are folded back into it before the function is called, so the function only ever sees points inside. Without bounds= the preset raises ValueError. The objective must be deterministic.

This preset is a hybrid, not just ATM. It takes ATM's sampler with five improvements (success-rate control of the search width, a uniform first pool over the box, bounds folded with a 25 % corner clip, a pool sized from the budget, no re-evaluation of the incumbent) and adds local-search stages: a simplex search in up to 4 dimensions and a (1+1)-ES above, for the first part of small budgets; a learned covariance up to 10 dimensions; and, up to 10 dimensions, a simplex search over the last half of the budget. Each option is documented in docs/DEVIATIONS.md and docs/EXPERIMENTS.md.

Presets, from simplest to largest:

Preset What it is Evidence
ATMConfig() the original ATM, bit for bit tests/golden, 400-case parity sweep
ATMConfig.composite() ATM's sampler plus the five improvements; stays pure ATM +.101, +.097, +.099 on three untouched holdouts
ATMConfig.improved() the composite plus the local stages above (recommended) +.196 over the original, +.096 over the composite on a fourth holdout
ATMConfig.improved_wave6() an earlier version, kept for reproducibility; loses on multimodal functions at medium budgets Tier 4, docs/HOLDOUT_TIER4.md

tests/golden/presets.json pins the exact cost traces of all of them.

What to expect from improved(), measured on COCO bbob (2021 suite) instances 96-100 that were not used to design it (docs/HOLDOUT_TIER5.md, 18,000 runs per arm, raw COCO evaluation):

  • ECDF value (fraction of targets reached) improves by +.196 [95 % CI +.180, +.212] over the defaults, averaged over budgets of 30, 100 and 300 x dimension, and by +.096 [+.085, +.108] over composite().
  • The gain shrinks as the dimension grows: over the defaults +.412 at D = 2, +.197 at D = 5, +.127 at D = 10, +.082 at D = 20, +.055 at D = 40; over composite() +.215 at D = 2 down to +.017 at D = 40, where the two are almost the same algorithm.
  • It does not beat everything: a plain (1+1)-ES with the 1/5 rule is still ahead at 40 dimensions (-.031) and level at 20, and CMA-ES is far ahead of every ATM variant at large budgets (on the Tier 4 instances: .597 against .504 for the closest hybrid at 1000 x D).
  • Only noiseless, continuous, box-constrained problems with budgets of 10 to 1000 x D were tested. The three-algorithm design means its gain should not be described as an improvement of ATM's sampler alone; use composite() if you want that.

Development

pytest -m "not slow"      # fast suite, includes golden-master and parity tests
pytest -m slow            # 400 random cases against the frozen original in reference/
python tools/record_golden.py   # re-record golden masters (only for deliberate changes)
python benchmarks/perf.py       # repeatable speed benchmark, original vs this package
python benchmarks/block_profile.py   # where the time goes, per algorithm block
Path What it is
src/atm/ the package
reference/ byte-identical copy of the original module, used only by tests
tests/golden/ recorded trajectories from the original
docs/AUDIT.md audit of the original, with severity and evidence
docs/REFACTOR_PLAN.md phases, principles, definition of done
docs/DEVIATIONS.md every difference from the original
docs/PERF.md speed measurements, method and repeatability
docs/BENCHMARKS.md COCO protocol, harness usage, parity and profiling results
docs/EXPERIMENTS.md prioritized, lightweight experiments to improve ATM on bbob (protocol, cards, log)
docs/research/ literature report, code-review report and their notes
docs/WORKPLAN.md scan of the codebase and the plan for readability, tests, extensibility, profiling
benchmarks/ speed harness (perf.py), per-block timing (block_profile.py), COCO/bbob harness (run_bbob.py, compare_bbob.py, postprocess_bbob.py) and stored results

CI runs on your laptop

There is deliberately no GitHub Actions CI for now (it would use Actions minutes). Run the same checks locally with the project's virtual environment:

.venv\Scripts\python tools/ci.py          # fast gate, about 2 minutes: lint, format, types, quick tests
.venv\Scripts\python tools/ci.py --full   # about 3 minutes (longer on a busy machine): all tests incl. the 400-case parity sweep, 100 % coverage gate

Both stop at the first failing step and exit non-zero (--keep-going runs everything). To run the fast gate automatically before every git push, opt in with git config core.hooksPath .githooks (undo with git config --unset core.hooksPath; skip once with git push --no-verify). It is not enabled by default.

A GitHub Actions workflow is parked, switched to manual start, in ci/github-actions-ci.yml; moving it to .github/workflows/ needs a token with the workflow scope.

Licensed under Apache-2.0.

Metadata

Release files for amm-optimizer 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for amm-optimizer 0.2.0
File Size Uploaded Provenance
amm_optimizer-0.2.0.tar.gz 2.0 MB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for amm-optimizer 0.2.0
File Interpreter ABI Platform
amm_optimizer-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 2.1 MB

Release files / amm_optimizer-0.2.0.tar.gz

Download URL amm_optimizer-0.2.0.tar.gz
Size 2.0 MB
Tags Source
SHA-256 checksum
How to use checksums
e82b7142bd0b86da7367525f12b3b591d0ffdc9bb3720f6597104999639f47f3
BLAKE2b-256 checksum
How to use checksums
b2706993102ea2bc615f78c1f1d07484dc3968513c964a3ef9408ec92ca74357
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release files / amm_optimizer-0.2.0-py3-none-any.whl

Download URL amm_optimizer-0.2.0-py3-none-any.whl
Size 153.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3c696d883e737a19d43dbdd8525716770c96467ee8f1d18bcd99b4ae1adcd347
BLAKE2b-256 checksum
How to use checksums
563f172242b8210ec808534b23df4b641f2d77f4fee507ae8027a1f108a06eb0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Security for amm-optimizer 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page