Expand description
§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:
- Geoscientific global optimizers the generic libraries omit — DDS and SCE-UA — central to hydrological calibration.
- Certified determinism via one seedable RNG (
Rng). - One unified
Problemtrait 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());Re-exports§
pub use algo::ensemble;pub use algo::Algorithm;pub use algo::Anneal;pub use algo::Dds;pub use algo::De;pub use algo::NsgaII;pub use algo::NsgaIII;pub use algo::Optimizer;pub use algo::ParallelTempering;pub use algo::Pso;pub use algo::Sa;pub use algo::SaResult;pub use algo::Sce;pub use algo::Schedule;pub use algo::TemperingResult;pub use problem::func;pub use problem::multi_func;pub use problem::Maximize;pub use problem::MultiProblem;pub use problem::Problem;pub use rng::Rng;pub use solution::MultiSolution;pub use solution::ParetoFront;pub use solution::Report;pub use solution::Solution;pub use solution::StopReason;pub use termination::Termination;