Python package and PyO3 bindings
The fcmaes-rust Python distribution installs the public fcmaes_rust
package. Its private fcmaes_rust._fcmaes_ext PyO3 module exposes the native
optimizer core; fcmaes_rust.native provides explicit access to that
low-level surface. SciPy result adapters and plotting are not bundled.
Build and import
Using maturin in a virtual environment:
python -m venv .venv
.venv/bin/python -m pip install "maturin[patchelf]>=1.7,<2"
env -u CONDA_PREFIX VIRTUAL_ENV="$PWD/.venv" \
PATH="$PWD/.venv/bin:$PATH" \
.venv/bin/maturin develop --release \
--manifest-path crates/fcmaes-py/Cargo.toml
.venv/bin/python -c \
'import fcmaes_rust; print(fcmaes_rust.__version__); print(fcmaes_rust.phase1_build_info())'
For an installed release:
python -m pip install fcmaes-rust
The facade exports the optimizer functions and classes documented below. They return low-level tuples, dictionaries, and NumPy arrays. The binary extension remains private so future facade-level result adapters can evolve without changing its import location.
Every public callable, stateful method, and property has a runtime docstring. Use Python’s normal inspection tools for the exact installed version:
import fcmaes_rust
help(fcmaes_rust.optimize_de)
help(fcmaes_rust.MODE)
help(fcmaes_rust.Archive.optimize_map_elites)
CI inspects the installed extension and rejects newly exposed callables or descriptors without docstrings. The guide supplies workflow context; runtime docstrings supply callback contracts, array shapes, parameter meaning, result layouts, stopping behavior, raised exceptions, and parallelism notes at the API entry point.
Type checking and editor support
The distribution ships a PEP 561 py.typed marker and a
_fcmaes_ext.pyi stub, so editors and
type checkers resolve the native surface without a plugin. No configuration is
needed.
The stub also records defaults that inspect.signature cannot show. PyO3
renders any non-literal Rust default as Ellipsis in __text_signature__, and
CPython rejects a text signature that spells -inf as a default, so the real
value cannot be surfaced through introspection at all. Seventeen parameters
across ten entry points are affected:
| Parameter | Real default | Shown by inspect.signature |
|---|---|---|
stop_fitness | -inf | Ellipsis |
value_limit | inf | Ellipsis |
stop_hist | -1.0 | Ellipsis |
update_gap | -1 | Ellipsis |
Read the stub, not help(), when a default matters. test_type_stubs.py
compares the stub against the built extension — names, parameter order, and
every default — so the two cannot drift apart silently.
Runnable Python example
examples/python/test_cma.py adapts the
Rosenbrock tests from the original fcmaes.testfun and fcmaes.test_cma
modules. It demonstrates both the one-shot optimize_acma function and the
ACMA ask/tell class:
.venv/bin/python examples/python/test_cma.py
.venv/bin/python -m pytest examples/python/test_cma.py
The objective monitor verifies that the result returned by Rust matches the best point observed by Python and that the evaluation counts agree.
Optimizer surface
| Algorithm | One-shot function | Stateful class |
|---|---|---|
| Differential Evolution | optimize_de | DE |
| Active CMA-ES | optimize_acma | ACMA |
| CR-FM-NES | optimize_crfmnes | CRFMNES |
| PGPE | optimize_pgpe | PGPE |
| Dual Annealing | optimize_da | — |
| BiteOpt | optimize_bite | Bite |
| MODE | Ask/tell only | MODE |
| MAP-Elites / Diversifier | Archive methods | Archive |
Stateful scalar classes expose ask, tell, population, and result where
the underlying optimizer supports them. ACMA also exposes tell_x. BiteOpt
enforces pending-batch call order and exact feedback lengths. The authoritative
callable signatures and docstrings are generated from the
#[pyo3(signature = ...)] declarations and Rust documentation comments under
crates/fcmaes-py/src/.
MODE and quality diversity
MODE.ask() returns a (popsize, dim) matrix. tell() accepts a
(popsize, nobj + ncon) matrix in which minimized objectives precede
constraints; constraints are feasible at values less than or equal to zero.
tell_switch() changes the update mode for one batch, and set_population()
installs validated decision and objective matrices.
The native QD Archive constructor receives decision bounds, descriptor
bounds, capacity, CVT sampling density, and a seed. For two descriptors,
samples_per_niche=0 selects constant-time grid lookup; positive values build
CVT centers.
Archive.optimize_map_elites() runs the SBX/mutation or Iso+LineDD emitter and
optional CMA emitter generations. Archive.diversify() runs the CMA-ME-style
improvement search. xs(), ys(), and descriptors() expose archive arrays;
occupied, best_y, and qd_score expose summary values.
Persistence, archive joins, shared-memory statistics, and plotting are not part of this binding crate.
Retry surface
The extension exports minimize_retry, minimize_advanced_retry, and
minimize_moretry. Returned dictionaries contain:
x,fun,nfev,nit, andsuccess;retry_xsandretry_ysfor retained results;improvementsfor completed-retry best-value samples.
The advanced-retry optimizer callback receives local bounds, an optional guess, step-size information, its evaluation budget, and an independently spawned seed. The moretry callback receives sampled scalarization weights and retains the original vector-valued evaluations.
GTOP surface
The extension exposes:
gtop_gtoc1gtop_cassini1andgtop_cassini1_minlpgtop_cassini2andgtop_cassini2_minlpgtop_messengerandgtop_messengerfullgtop_rosettagtop_sagasgtop_tandemandgtop_tandem_unconstrained
Wrong input dimensions return the GTOP penalty result instead of accessing outside native arrays.
GIL and parallelism
Optimizer loops execute under py.allow_threads. Each Python objective call
constructs a NumPy vector and reacquires the GIL. Consequently:
- Native Rust objectives scale across retry workers without the GIL.
- Python objectives dominated by an extension may scale if that extension releases the GIL.
- Cheap Python callbacks are normally callback/GIL limited.
- Combining retry-level workers with population-level workers can oversubscribe the machine and should be measured.