Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

fcmaes-rust logo

fcmaes-rust

Choosing an optimization tool? Start with the shared solver-selection and agent guide or the optimization ecosystem overview. This repository supplies native Rust black-box, multi-objective and quality-diversity optimizers, Python bindings, and a source-built job worker. The guide also covers Python objectives, LP/MIP and smooth constrained NLPs.

unsafe forbidden crates.io docs.rs PyPI mdBook guide

Slides (PDF) · Book (PDF) · YouTube video

fcmaes-rust is a native Rust implementation of fast, parallel, gradient-free optimization algorithms and selected fcmaes application examples. The optimizer implementation in fcmaes-core is 100% Rust: it does not compile, link, load, or call the original fast-cma-es C++ implementation. Optimizer numerics, retry coordination, random-number generation, fitness evaluation, and parallel execution all run in Rust.

fcmaes-rust reimplements the algorithm set of fast-cma-es natively in Rust rather than wrapping it, and is an alternative for both Rust and Python users via its PyO3 API. For objectives written in Python, prefer the Python library fast-cma-es: it uses multiprocessing, so Python objectives evaluate in parallel. The PyO3 API here is the better fit when the objective itself is in Rust.

In this project, “port” means that algorithms were translated, reimplemented, and tested in Rust. It does not mean an FFI wrapper around the old C++ code; the public API documentation explains the algorithms through their primary literature and records implementation-specific behavior explicitly.

The repository is a standalone Cargo workspace. GTOP models and example objective functions also execute in Rust. This includes the Mazda mass and constraint response surfaces: their compact model data is embedded in the example crate and evaluated by native Rust code. The Buckingham–Pi example also implements dimension-matrix enumeration, numerical nullspace analysis, regression, and continuous-exponent optimization directly in Rust; it has no BuckinghamPy dependency.

Experimental surrogate optimization

The new source-only fcmaes-surrogate crate and fcmaes.surrogate/1 job profile implement small-budget exact-GP optimization with synchronous batches and a cancellable Rust simulation API. Current limits are 32 coordinates, 256 new plus warm observations, and eight inner threads per task. See the API guide (it links the executable tutorial), measured results and reviewed roadmap. Thompson-sampling TuRBO, asynchronous scheduling and large-budget handoff are future milestones. In an equal-budget comparison with BoTorch, egobox, scikit-optimize and Optuna it reached the lowest median final regret of the GP methods on four of five small problems at 1–3 orders of magnitude less proposal time; for separable or many-modal problems with tens of variables, BiteOpt retry (fcmaes.retry/1) remained better.

Core design principle: improve results for the same wait

Independent retry turns otherwise idle CPU cores into additional chances to find a better solution before the user’s deadline. Many useful stochastic, local, and third-party optimizers execute one search on one thread. The generic fcmaes_core::retry coordinator runs independent instances concurrently and returns the best retained result; the wrapped optimizer does not have to be an fcmaes implementation.

The controlled GTOP equal-wall experiment wrapped the external, serial cmaes crate and compared one restart lane with 16 lanes on a 16-physical-core Ryzen 9 9950X. Both arms waited approximately 4.000 seconds per pair. Across 100 paired seeds on each of seven problems, retry improved the mean returned objective on 7/7 problems. It won 86–96/100 pairs, close to the roughly 94% expected when independent retry gets about 15 times as many starts:

Equal-wall evidenceSerial external CMA-ESThrough fcmaes retry
User-visible wall time4.000109–4.000150 s4.000440–4.000523 s
Mean active cores1.0015.99–16.00
Problems with the better mean0/77/7
Cassini1 target successes38/100100/100

This is the practical library design claim: on that fixed machine and protocol, retry bought better mean quality for the same wait by spending more aggregate CPU work. The paired win rate mainly confirms that the scheduler delivered those extra independent opportunities; the mean and sdev quantify their effect on the returned distribution. This is not a theorem for every objective or budget. The full quality, wall-time, and work-accounting tables are in the benchmark report; variability fell on five problems but rose on SAGAS and Tandem.

Two complementary ways to spend the cores

Retry is not the only parallelism boundary. All population-based fcmaes-core optimizers expose ask/tell or an equivalent whole-population batch interface. The caller asks for candidates, evaluates them concurrently on CPU workers, a GPU, a simulator farm, or remote services, and tells the optimizer the ordered results. This often gives the largest wall-time benefit when one objective evaluation is expensive.

Parallel strategyUnit of parallel workBest fitMain effect at fixed wall time
Independent retryComplete optimizer runsMultimodal problems; serial internal algorithms; cheap to moderately costly objectivesExplores more independent basins and improves the distribution of the returned best
Population ask/tellCandidates from one optimizer generationExpensive simulations, training jobs, hardware tests, or remote evaluationsAdvances one search through more generations during the same wait

DE, active CMA-ES, CR-FM-NES, PGPE, BiteOpt, and MODE provide direct ask/tell interfaces. MAP-Elites and Diversifier provide equivalent batch evaluators and ordered archive updates. Dual Annealing is the deliberate exception: its next point depends on the preceding point and score, so it has no population to evaluate concurrently. Retry can still parallelize independent Dual Annealing runs. Both forms can be combined, but partition the available workers between outer retries and inner batch evaluation to avoid oversubscription. See the optimizer guide.

Implementation facts

FeatureImplementation
Optimizer core100% native Rust in fcmaes-core
Legacy C++ optimization backendNone; no C++ library is compiled, linked, loaded, or invoked
Core buildStandard Cargo build; no project build.rs, CMake, or C/C++ compiler
ParallelismIndependent retry workers plus ask/tell and ordered Rayon population batches
Objective functionsNative Rust closures and batch evaluators
Python integrationOptional PyO3 extension that exposes the Rust core; Python is not an optimizer backend

To build only the reusable optimizer library, a Rust toolchain is sufficient:

cargo build --release -p fcmaes-core

This statement deliberately applies to the optimizer core. Building every optional workspace component can additionally require Python for fcmaes-py and native tooling pulled in by data-compression or network dependencies used by examples. Those integrations do not contain or restore the historical C++ optimizer backend.

Workspace

CratePurpose
fcmaes-coreOptimizers, fitness handling, RNG, retry, multi-objective optimization, and quality diversity
fcmaes-gtopInternal native GTOP objective library shared by the examples and Python package
examples (fcmaes-examples)Native GTOP problems, application objectives, benchmarks, and executable examples
fcmaes-pyOptional PyO3 extension for embedding the Rust implementation in a Python package
foundations/Standalone standard suites, Lennard-Jones scaling, audited quality indicators, and seven compact lessons
tutorials/*Twenty-two standalone application workspaces spanning simulation, astrodynamics, circuits, mechanics, energy, routing, hydraulics, ML, and other domains; see the tutorial index

Only two registry artifacts are published: fcmaes-core on crates.io and the fcmaes-rust binding distribution on PyPI. fcmaes-gtop is an internal source dependency marked publish = false; examples/ and tutorials/ are available only from this GitHub repository and are not included in either registry package.

The application tutorials are intentionally not root workspace members. Each keeps its application-specific dependencies, artifacts, and lockfile isolated; run its Cargo commands from that tutorial directory.

New users can start with the Foundations guide: eight classic scalar functions, ZDT1–4/ZDT6, DTLZ1–7, a Lennard-Jones scaling study, a seven-step lesson ladder, and exact/typed-sampled multi-objective quality indicators. foundations/ is a user guide rather than an application tutorial, so the simulator-in-the-loop tutorial count remains twenty-two.

The optimizer-boundary guide records why the core stops at bounded gradient-free global methods and evidence utilities. Corrected paired experiments keep Nelder–Mead, Bayesian optimization, and gradient solvers behind the retry adapter boundary instead of adding them as core algorithms or dependencies.

Tutorial evidence map

The tutorial index is the exhaustive catalogue. This shorter map highlights the main experimental decisions and validation results.

Multi-objective and quality-diversity evidence

Seventeen application tutorials retain multi-objective optimization. MAP-Elites campaigns are recorded for NeXosim, Rapier, ReBop, Brahe, atmospheric source localization, room ventilation, RustPower, sindr circuit design, quadruped locomotion, phased-array register codebooks, and energy-hub sizing.

  • Descriptor redesign can help. In RustPower, direct decision variables produced only 4% archive coverage. Emergent behavior coordinates reached 68% mean coverage over three seeds at the same 100k-evaluation budget. Constrained MODE remains primary because the near-unique asset architecture survived the descriptor change.
  • A completed QD campaign can still fail its evidence gate. The SmartCore study separates fixed-fold tuning, model selection, and frozen final evaluation. Replacing two highly correlated descriptors increased range-study occupancy from 16/400 to 91/400 cells, but the subsequent 49.0%-coverage campaign still failed held-out niche retention.
  • Accepted descriptor gates. The phased-array study reaches 40.83% coverage and 95.07% holdout niche retention on its corrected 12×10 grid. The energy-hub study follows its accepted native-grid pilot with a 64-elite portfolio and an independent 8,760-hour chronological hydrogen replay.
  • Rejected descriptor gates are published too. The field-service, water-network, and truss-sizing studies reject unstable or weakly retained repertoires instead of presenting them as successful QD results.

Selected application protocols

  • Policy search: the neural-controller tutorial compares PGPE and CR-FM-NES on a 118-parameter controller using common scenarios, disjoint validation, and a frozen 1,024-scenario final test.
  • Fixed-sequence astrodynamics: the GTOC1 tutorial applies coordinated DE–CMA-ES and incumbent-seeded retry to the real 87-variable EVEEEJSJA low-thrust tour. It explains why its VSOP2013 result is not an official DE405 re-scoring.
  • Split-brain route discovery: the GTOC1 route-search tutorial keeps a provider-independent agent boundary. Its seed-42 L0 audit finds 15 admissible random routes, 24 evolutionary routes, and none from MiniMax-M3. The three promoted random controls all fail L1 closure, so independent seeds, matched promotion, and a validated L2 finalist remain open requirements.
  • Circuits and optics: the sindr study combines interpolated AC features, retry, MODE, and an E12 catalogue. The gate-driver front passes timestep refinement and a 49-design ngspice comparison. The optical-lens study validates its dependency-free ray tracer before optimizing a Cooke-triplet front.
  • Robust locomotion: the quadruped tutorial makes quality diversity the primary result and uses five-seed held-out terrain replay rather than treating training coverage as robustness.
  • Specialist baselines: the network-coverage tutorial validates its kernel and certificates before optimization. Its marginal-greedy prefix frontier dominates every finite MODE point, so the tutorial recommends the specialist method for that frozen submodular formulation.

Reproducibility

Tutorial result directories contain the canonical raw evidence and generated SVGs needed to reproduce the published pages from a clean clone. Schema-driven tutorials use run.json; room ventilation and neural policy search also check aggregate CSVs and plots spanning multiple seeds and validation studies.

Implemented algorithms include Differential Evolution, active CMA-ES, CR-FM-NES, PGPE, Dual Annealing, BiteOpt, MODE, CVT-MAP-Elites, the Diversifier, independent retry, coordinated retry, and weighted multi-objective retry. ParetoArchive2D keeps the exact non-dominated front and hypervolume of all points evaluated on a two-objective problem, next to any optimizer (guide).

The example crate includes GTOP mission optimization, Mazda factory-design objectives, stock-strategy optimization, material-flow planning, flexible job-shop and harvesting, multi-UAV task assignment, spherical t-design, transfer scheduling, Buckingham–Pi dimensional analysis, damped control, F-8 aircraft control, and Lotka-Volterra control.

Quick start

Install the released packages

Inside a Rust application, add the published optimizer library:

cargo add fcmaes-core

The crate is imported in Rust as fcmaes_core.

Python users install the published binding distribution with:

python -m pip install fcmaes-rust

It imports as fcmaes_rust; its optimizer backend is the same native Rust implementation:

import fcmaes_rust

print(fcmaes_rust.__version__)
print(fcmaes_rust.phase1_build_info())

A compatible prebuilt wheel requires neither a local Rust toolchain nor a C/C++ compiler. Published wheels support CPython 3.11 through 3.13. Building the Python package from its source distribution does require Rust.

Install from source

Everything in this repository builds from source with Rust alone; Python is needed only for the Python package. Requirements:

  • git and Rust 1.88 or newer (rustup from https://rustup.rs). Rust 1.88 is the tested minimum for the edition-2024 source and the locked dependency set; CI checks it explicitly.
  • For the Python package: CPython 3.11 to 3.13, pip, and the build backend maturin (installed automatically by pip install .).

Our own dependencies are fetched by Cargo, so no second checkout is needed: the job worker, the experiment runner and the GTOC1 tutorial depend on the shared job API, optimization-jobs, as a git dependency at the revision pinned in Cargo.toml (needs network access to GitHub on the first build; cargo fetch --locked prepares an offline build). fcmaes-core and the Python package depend on crates.io crates only.

git clone https://github.com/dietmarwo/fcmaes-rust
cd fcmaes-rust
cargo test --workspace --locked
cargo build --release --workspace --locked

Python package from the checkout, in a virtual environment:

python -m venv .venv && . .venv/bin/activate   # Windows: .venv\Scripts\activate
python -m pip install .                          # builds the Rust extension
python -c "import fcmaes_rust; print(fcmaes_rust.phase1_build_info())"

For development, python -m pip install "maturin>=1.7,<2" numpy scipy pytest and maturin develop --release --locked install an editable build; python -m pytest runs the binding tests. Without a matching wheel, pip install fcmaes-rust also builds from the source distribution and then needs the Rust toolchain.

Unreleased fcmaes-core changes are available to other Rust projects as a git dependency:

[dependencies]
fcmaes-core = { git = "https://github.com/dietmarwo/fcmaes-rust" }

The job worker and the runner build together (cargo build --release --locked -p optimization-runner -p fcmaes-job-worker); see the job API guide. RELEASING.md describes the registry releases.

Run a small native optimization:

cargo run --release -p fcmaes-examples --bin jobshop -- --evals 2000

Run a GTOP retry workload:

cargo run --release -p fcmaes-examples --bin gtop-examples -- \
  --problem cassini1 --retries 16 --evaluations 5000 --workers 16 --seed 1

With fcmaes-rust installed, run the repository’s active CMA-ES Python example with:

python examples/python/test_cma.py

Documentation

Generate the complete API reference with:

cargo doc --workspace --no-deps --open

Build the rendered guide locally with mdBook 0.5.4:

python scripts/check_doc_consistency.py
python scripts/build_book.py
python scripts/check_book_links.py

The builder stages canonical repository files under target/; it does not maintain duplicate copies of the guides or tutorial results.

Optimizer comparison

Equal-budget GTOP results

The reproducible GTOP optimizer comparison uses 100 experiments per problem and a common 240,000-evaluation cap. fcmaes has the best mean optimum on six of seven problems. Its independent BiteOpt retry arm has the lowest mean optimizer wall time per actual evaluation on all seven, at 142–310 ns/evaluation. Raw total wall time is not the headline speed measure because plain cmaes CMA-ES stops protectively after using only 7.4%–58.8% of its allowance. The exception in mean solution quality is Tandem, where adaptive BIPOP-CMA-ES leads the equal-budget table but does not reach the -1493 target.

Tandem stress test

In the pre-registered Tandem stress test, BIPOP-CMA-ES reached 0/1,000 targets: its best result was -1410.050665 after 9,466,290,846 actual evaluations. In contrast, fcmaes coordinated DE→CMA retry reached the target in 85/100 experiments with a mean of 230,727,025 evaluations. Across their complete campaigns, the 100 fcmaes experiments used 23.07 billion actual evaluations, 2.44 times the 9.47 billion used by the 1,000-retry stress test. These are separate budget regimes and allocations: the equal-budget table supports the controlled comparison, while the larger coordinated result demonstrates the benefit of adaptive retry coordination on a hard problem. The original Python/C++ fcmaes performance table reports a similar 81/100 Tandem success rate; the linked report records both results and their exact parallel execution models.

Controlled CMA-ES implementation diagnostic

The separate controlled active CMA-ES implementation diagnostic holds the objective and parallel architecture much closer between fcmaes-core and cmaes 0.2.2. Its complete 20-pair campaign finds no universal quality winner:

  • cmaes leads serial throughput on cheap and high-dimensional cases.
  • fcmaes-core leads median aggregate throughput under equal 16-instance multistart.
  • Protective-stop behavior differs substantially and is reported rather than normalized away.

The easy analytic functions isolate implementation effects; they are not recommended CMA-ES workloads. At 100 µs objective cost, the serial speed gap is already negligible.

Equal-wall parallel retry

The complementary GTOP equal-wall retry experiment plugs that external, single-threaded cmaes implementation into fcmaes_core::retry. Its primary 100-pair experiment compares the best-objective mean/sdev returned by one serial restart lane and by 16 lanes after the same four-second wait. Measured wall mean/sdev checks fairness; starts, evaluations, CPU time, and active cores expose the deliberately higher parallel work. This demonstrates that retry is an optimizer adapter rather than a facility reserved for fcmaes algorithms.

In the completed seven-problem campaign:

  • retry improves mean objective on every case and wins 86–96 of 100 pairs;
  • it reduces standard deviation on five cases but increases it on SAGAS and Tandem; and
  • both arms measure about 4.000 seconds, at roughly 1 versus 16 active cores.

Because the retry arm completed about 15 times as many independent starts, iid restart order statistics alone predict a win rate near 15/16, or 94%. The observed wins are consistent with that baseline; the improved means measure the distributional benefit relevant to the user.

A separate five-pair pilot retains equal-work scheduler-scaling evidence but is not part of the practical quality claim.

Data-backed examples

The examples are self-contained by default:

  • Trading includes an offline adjusted-close cache and can optionally refresh it through Yahoo Finance.
  • Mazda bundles its decision table and compact response-surface data under examples/data/; neither binary needs or accepts an external model path. The Mazda data notice records provenance and the benchmark’s acknowledgement request.
  • The Multi-UAV data and compatibility notice documents the native task-assignment port and source benchmark.
  • The Buckingham notice records the dimension-matrix catalog’s provenance and the numerical port’s deliberately narrower scope than BuckinghamPy.

Both Mazda drivers accept --workers N for ordered parallel objective batches; use --workers 16 for sixteen evaluation threads or --workers 0 to select available parallelism.

This public workspace intentionally contains only the Rust port and its related documentation, native examples, benchmark results, and optional Rust bindings. Historical Python/C++ implementations and port-planning material are not part of this repository.

License

The Rust source and documentation are MIT licensed; see LICENSE. The embedded Mazda benchmark data retains its recorded provenance and acknowledgement request; see the Mazda data notice.