forge_core/lib.rs
1//! # forge-core
2//!
3//! A **deterministic metaheuristic optimization substrate** in Rust. forge is
4//! to optimization what `surtgis-core` is to raster data: a shared engine that
5//! several tools in the ecosystem consume rather than an application in itself.
6//!
7//! Every optimizer speaks one interface — the [`Problem`] trait — minimizes by
8//! convention, counts objective evaluations as its budget, rejects non-finite
9//! candidates, and is **reproducible for a given seed** (the portfolio's
10//! certified-determinism seal).
11//!
12//! ## What sets it apart
13//!
14//! Generic Rust optimization crates exist (`argmin`, `optirustic`). forge's
15//! value is not to reimplement them but to provide:
16//!
17//! 1. **Geoscientific global optimizers** the generic libraries omit — **DDS**
18//! and **SCE-UA** — central to hydrological calibration.
19//! 2. **Certified determinism** via one seedable RNG ([`Rng`]).
20//! 3. **One unified [`Problem`] trait** for the whole ecosystem.
21//!
22//! The DDS and SCE-UA implementations are migrated from `rainflow-core`, where
23//! they were validated against `airGR` (GR4J calibration NSE 0.7956 vs 0.7957).
24//!
25//! ## Quick start
26//!
27//! ```
28//! use forge_core::{Dds, Optimizer, Termination};
29//! use forge_core::testfn::Sphere;
30//!
31//! let problem = Sphere::new(5);
32//! let report = Dds::default().optimize(&problem, &Termination::budget(2000));
33//! assert!(report.best_value() < 1e-2);
34//! ```
35//!
36//! Maximization (e.g. NSE/KGE in rainflow) wraps the problem so the minimizing
37//! core stays the single convention:
38//!
39//! ```
40//! use forge_core::{Optimizer, Sce, Termination};
41//! use forge_core::problem::{func, Maximize};
42//!
43//! // Maximize a concave bump peaking at x = 2.
44//! let p = Maximize(func(vec![(-10.0, 10.0)], |x| -(x[0] - 2.0).powi(2)));
45//! let report = Sce::default().optimize(&p, &Termination::budget(3000));
46//! assert!((report.best()[0] - 2.0).abs() < 0.1);
47//! assert!(report.best_value_maximized() > -1e-2);
48//! ```
49//!
50//! Robust restarts via independent islands (deterministic with or without the
51//! `rayon` feature):
52//!
53//! ```
54//! use forge_core::{ensemble, De, Termination};
55//! use forge_core::testfn::Rastrigin;
56//!
57//! let problem = Rastrigin::new(3);
58//! let report = ensemble(&De::default(), &problem, &Termination::budget(5000), 8, 42);
59//! assert!(report.best_value() < 1.0);
60//! ```
61//!
62//! Multi-objective optimization with NSGA-II returns a Pareto front:
63//!
64//! ```
65//! use forge_core::{NsgaII, Termination};
66//! use forge_core::problem::multi_func;
67//!
68//! // Schaffer N.1: minimize x² and (x−2)²; Pareto-optimal x ∈ [0, 2].
69//! let sch = multi_func(vec![(-5.0, 5.0)], 2, |x| vec![x[0] * x[0], (x[0] - 2.0).powi(2)]);
70//! let front = NsgaII::default().optimize(&sch, &Termination::budget(6000));
71//! assert!(!front.is_empty());
72//! ```
73
74pub mod algo;
75pub mod constraint;
76pub mod indicators;
77pub mod problem;
78pub mod rng;
79pub mod solution;
80pub mod termination;
81pub mod testfn;
82
83pub use algo::{
84 ensemble, Algorithm, Anneal, Behavioral, CmaEs, Dds, De, EpsilonLShade, Glue, GlueResult,
85 GlueSample, LShade, LSrtde, Moead, NsgaII, NsgaIII, Optimizer, Padds, PaddsSelection,
86 ParallelTempering, Pso, Restart, RestartCmaEs, Sa, SaResult, Sce, Schedule, SmsEmoa,
87 TemperingResult,
88};
89pub use problem::{
90 func, multi_func, validate, validate_multi, BoundsError, Maximize, MultiProblem, Problem,
91};
92pub use rng::Rng;
93pub use solution::{MultiSolution, ParetoFront, Report, Solution, StopReason};
94pub use termination::Termination;