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

Getting started

Prerequisites

The native library requires Rust 1.88 or newer with Cargo. Rust 1.88 is the tested minimum supported Rust version (MSRV) for the edition-2024 source and the current locked dependency set. Python is optional and needed only when building the PyO3 extension crate.

Check the toolchain:

rustc --version
cargo --version

To reproduce the minimum-version check used in CI:

rustup toolchain install 1.88.0
cargo +1.88.0 check --workspace --locked

Build and test the Rust workspace

Run these commands from the repository root:

cargo build --workspace
cargo test --workspace

Use an optimized build for performance work and real optimization runs:

cargo build --release --workspace

The release profile enables thin LTO and one code-generation unit. Debug builds are suitable for tests but are not representative for optimizer timing.

Generate the API reference

The source contains rustdoc comments for public types and methods:

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

Without --open, the main pages are generated below target/doc/, including target/doc/fcmaes_core/index.html and target/doc/fcmaes_examples/index.html.

Use fcmaes-core from Rust

Inside this workspace, depend on the core crate with:

[dependencies]
fcmaes-core = { path = "../crates/fcmaes-core" }

The following program minimizes a five-dimensional sphere with Differential Evolution:

use fcmaes_core::{De, DeParams, Fitness};

fn sphere(x: &[f64]) -> f64 {
    x.iter().map(|value| value * value).sum()
}

fn main() {
    let dim = 5;
    let lower = vec![-5.0; dim];
    let upper = vec![5.0; dim];
    let fitness = Fitness::bounded(dim, 1, &lower, &upper);
    let params = DeParams {
        max_evaluations: 20_000,
        seed: 1,
        ..Default::default()
    };
    let mut optimizer = De::new(fitness, &[], &[], None, &params);
    let result = optimizer.optimize(&sphere);

    println!("value={} evaluations={} x={:?}",
             result.y, result.evaluations, result.x);
}

Objectives are ordinary Fn(&[f64]) -> f64 + Sync functions or closures. The blanket Objective implementation avoids an adapter type for the common single-objective case.

Build the Python extension

Create a virtual environment and install the extension build tools:

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

Verify that Python loaded the Rust backend:

.venv/bin/python -c \
  'import fcmaes_rust; print(fcmaes_rust.__version__); print(fcmaes_rust.phase1_build_info())'

The returned dictionary should contain "backend": "rust". The installed distribution exposes the documented facade as fcmaes_rust and keeps the low-level extension available as fcmaes_rust.native.

Run native examples

List the example CLI options:

cargo run --release -p fcmaes-examples --bin gtop-examples -- --help
cargo run --release -p fcmaes-examples --bin gtop-advexamples -- --help

The first binary uses independent retry; the second uses coordinated retry with adaptive budgets, crossover guesses, and diversity filtering. See Examples for the full problem list and commands.

The application ports are separate binaries. For example, run the embedded flexible job-shop problem with:

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

The complete binary catalog, optional data inputs, and commands for Mazda, trading, material flow, job-shop/harvesting, t-design, transfer scheduling, damp control, F-8, and Lotka-Volterra are in Native Rust examples.

Standalone application tutorials are tested and run from their own directories. For example:

cd tutorials/cfd-room-ventilation
cargo test --all-targets
cargo run --release --bin cfd-room-ventilation -- --mode evaluate

The tutorial index explains all twenty-two application models, optimizer formulations, recorded evidence, and plotting workflow.

Common mistakes

  • Do not benchmark a debug build. Optimizer numerics are substantially slower without --release.
  • Retry workers and optimizer population workers are separate levels of parallelism. Avoid enabling both without considering oversubscription.
  • Bounds must be finite, non-empty, equal-length vectors with lower[i] < upper[i].
  • Population optimizers can finish their current population after crossing an evaluation limit, so reported evaluations can slightly exceed the request.
  • A low value_limit filters retained retry results; it is not a target that stops the run. stop_fitness is the early-stop control.