metalforge 0.1.0

forge: a deterministic metaheuristic optimization substrate in Rust. Unified Problem/MultiProblem/Anneal traits; DDS, SCE-UA, DE, PSO, NSGA-II and simulated annealing; reproducible by seed; optional Rayon parallelism.
Documentation

forge-core

A deterministic metaheuristic optimization substrate in Rust. forge is to optimization what surtgis-core is to raster data: a shared engine that several tools in the ecosystem consume rather than an application in itself.

Every optimizer speaks one interface — the [Problem] trait — minimizes by convention, counts objective evaluations as its budget, rejects non-finite candidates, and is reproducible for a given seed (the portfolio's certified-determinism seal).

What sets it apart

Generic Rust optimization crates exist (argmin, optirustic). forge's value is not to reimplement them but to provide:

  1. Geoscientific global optimizers the generic libraries omit — DDS and SCE-UA — central to hydrological calibration.
  2. Certified determinism via one seedable RNG ([Rng]).
  3. One unified [Problem] trait for the whole ecosystem.

The DDS and SCE-UA implementations are migrated from rainflow-core, where they were validated against airGR (GR4J calibration NSE 0.7956 vs 0.7957).

Quick start

use forge_core::{Dds, Optimizer, Termination};
use forge_core::testfn::Sphere;

let problem = Sphere::new(5);
let report = Dds::default().optimize(&problem, &Termination::budget(2000));
assert!(report.best_value() < 1e-2);

Maximization (e.g. NSE/KGE in rainflow) wraps the problem so the minimizing core stays the single convention:

use forge_core::{Optimizer, Sce, Termination};
use forge_core::problem::{func, Maximize};

// Maximize a concave bump peaking at x = 2.
let p = Maximize(func(vec![(-10.0, 10.0)], |x| -(x[0] - 2.0).powi(2)));
let report = Sce::default().optimize(&p, &Termination::budget(3000));
assert!((report.best()[0] - 2.0).abs() < 0.1);
assert!(report.best_value_maximized() > -1e-2);

Robust restarts via independent islands (deterministic with or without the rayon feature):

use forge_core::{ensemble, De, Termination};
use forge_core::testfn::Rastrigin;

let problem = Rastrigin::new(3);
let report = ensemble(&De::default(), &problem, &Termination::budget(5000), 8, 42);
assert!(report.best_value() < 1.0);

Multi-objective optimization with NSGA-II returns a Pareto front:

use forge_core::{NsgaII, Termination};
use forge_core::problem::multi_func;

// Schaffer N.1: minimize x² and (x−2)²; Pareto-optimal x ∈ [0, 2].
let sch = multi_func(vec![(-5.0, 5.0)], 2, |x| vec![x[0] * x[0], (x[0] - 2.0).powi(2)]);
let front = NsgaII::default().optimize(&sch, &Termination::budget(6000));
assert!(!front.is_empty());