Skip to main content

fugue_evo/
lib.rs

1// Clippy allows for intentional patterns in this library
2#![allow(clippy::needless_range_loop)] // Matrix operations are clearer with explicit indices
3#![allow(clippy::derivable_impls)] // Some Default impls have doc comments
4#![allow(clippy::redundant_closure)] // Closure style consistency
5#![allow(clippy::should_implement_trait)] // Custom add methods for domain types
6#![allow(clippy::get_first)] // Explicit .get(0) is clearer in some contexts
7#![allow(clippy::useless_conversion)] // into_iter() for clarity
8#![allow(clippy::unnecessary_unwrap)] // Pattern clarity
9#![allow(clippy::wrong_self_convention)] // from_* methods for domain types
10#![allow(clippy::only_used_in_recursion)] // Tree traversal parameters
11#![allow(clippy::if_same_then_else)] // Sometimes intentional for clarity
12#![allow(clippy::manual_clamp)] // Explicit clamp logic for clarity
13#![allow(clippy::manual_memcpy)] // Matrix operations clarity
14
15//! # fugue-evo
16//!
17//! Evolutionary computation for Rust, in **two layers**:
18//!
19//! 1. **Classic EC (`classic` feature; standalone, no fugue dependency).**
20//!    SimpleGA, CMA-ES, NSGA-II, Island Model, Evolution Strategy, EDA/UMDA,
21//!    SteadyState, the interactive GA, all operators, checkpointing, and the
22//!    WASM surface. Compiles with
23//!    `--no-default-features --features std,parallel,checkpoint,classic`
24//!    with no probabilistic-programming dependency at all. Conversely,
25//!    `--features std,ppl` builds the inference layer with no classic code.
26//! 2. **Evolutionary inference (`ppl` feature, on by default): evolutionary
27//!    algorithms *as* probabilistic programs.** The prior over genomes is a
28//!    user-written fugue [`Model`](fugue::Model) (a [`GenomePrior`](inference::prior::GenomePrior)),
29//!    fitness enters as `factor(β·f(x))`, so the Boltzmann posterior
30//!    `π_β(x) ∝ p(x)·exp(β·f(x))` **is a fugue program** — and every sampler
31//!    is fugue's own inference machinery:
32//!    [`EvolutionChain`](inference::mh::EvolutionChain) (typed single-site MH),
33//!    [`EvolutionSMC`](inference::smc::EvolutionSMC) (adaptive tempered SMC
34//!    with a population-coupled crossover kernel and a log-evidence estimate),
35//!    [`ArithmeticGrammarPrior`](inference::grammar::ArithmeticGrammarPrior)
36//!    (genetic programming over a probabilistic grammar, where subtree
37//!    mutation/crossover are generic trace moves),
38//!    [`GenomeLikelihood`](inference::likelihood::GenomeLikelihood)
39//!    (likelihoods as observation programs, with latent nuisance parameters
40//!    jointly inferred), annealed **optimizer mode**
41//!    ([`EvolutionSMC::anneal`](inference::smc::EvolutionSMC::anneal)), and
42//!    the **Pareto posterior**
43//!    ([`ParetoScalarization`](inference::pareto::ParetoScalarization) —
44//!    multi-objective optimization as inference).
45//!
46//! The boundary between the layers is the
47//! [`TraceGenome`](genome::trace_genome::TraceGenome) extension trait: classic
48//! algorithms require only [`EvolutionaryGenome`](genome::traits::EvolutionaryGenome);
49//! genomes that also implement `TraceGenome` can be driven by the inference
50//! layer.
51//!
52//! ## Features
53//!
54//! - **Multiple Algorithms**: SimpleGA, CMA-ES, NSGA-II, Island Model, EDA, Interactive GA (standalone EC)
55//! - **Flexible Genomes**: RealVector, BitString, Permutation, TreeGenome
56//! - **Modular Operators**: Pluggable selection, crossover, and mutation operators
57//! - **Adaptive Hyperparameters**: opt-in Thompson-sampling tuning of operator parameters
58//! - **Evolutionary inference** (`ppl`): priors as programs, tempered SMC over the
59//!   Boltzmann posterior, MH with typed proposals, symbolic regression as exact
60//!   Bayesian inference
61//! - **Production Ready**: Checkpointing (bit-identical resume), parallel evaluation, WASM support
62//!
63//! ## Quick Start (classic optimization)
64//!
65#![cfg_attr(feature = "classic", doc = "```rust")]
66#![cfg_attr(not(feature = "classic"), doc = "```rust,ignore")]
67//! use fugue_evo::prelude::*;
68//! use rand::rngs::StdRng;
69//! use rand::SeedableRng;
70//!
71//! fn main() -> Result<(), Box<dyn std::error::Error>> {
72//!     let mut rng = StdRng::seed_from_u64(42);
73//!     let bounds = MultiBounds::symmetric(5.12, 10);
74//!     let result = SimpleGABuilder::real_valued()
75//!         .population_size(100)
76//!         .bounds(bounds)
77//!         .fitness(Sphere::new(10))
78//!         .max_generations(200)
79//!         .build()?
80//!         .run(&mut rng)?;
81//!     println!("Best fitness: {:.6}", result.best_fitness);
82//!     Ok(())
83//! }
84//! ```
85//!
86//! ## Quick Start (evolution as inference, `ppl`)
87//!
88#![cfg_attr(feature = "ppl", doc = "```rust")]
89#![cfg_attr(not(feature = "ppl"), doc = "```rust,ignore")]
90//! use fugue_evo::prelude::*;
91//! # use rand::SeedableRng;
92//! # #[derive(Clone)]
93//! # struct Quadratic;
94//! # impl Fitness for Quadratic {
95//! #     type Genome = RealVector;
96//! #     type Value = f64;
97//! #     fn evaluate(&self, g: &RealVector) -> f64 {
98//! #         -0.5 * g.genes().iter().map(|x| (x - 1.0).powi(2)).sum::<f64>()
99//! #     }
100//! # }
101//! # const DIM: usize = 2;
102//! # let fitness = Quadratic;
103//! # let mut rng = rand::rngs::StdRng::seed_from_u64(1);
104//!
105//! // Prior as a program; fitness as a likelihood factor; posterior by SMC.
106//! let model = EvolutionModel::new(GaussianPrior::new(0.0, 2.0, DIM), fitness);
107//! let posterior = EvolutionSMC::run(&mut rng, &model, EvoSmcConfig::default());
108//! let mean = posterior.weighted_mean(0).expect("gene#0 is a real coordinate");
109//! println!("posterior mean: {mean}");
110//! println!("log evidence:   {}", posterior.log_evidence);
111//! # assert!((mean - 0.8).abs() < 0.3); // conjugate: τ = 1/4 + 1, mean = 1/τ = 0.8
112//! ```
113//!
114//! ## Module Overview
115//!
116//! - [`algorithms`]: Classic optimization algorithms (SimpleGA, CMA-ES, NSGA-II, Island Model)
117//! - [`genome`]: Genome types, [`EvolutionaryGenome`](genome::traits::EvolutionaryGenome), and (behind `ppl`) [`TraceGenome`](genome::trace_genome::TraceGenome)
118//! - [`operators`]: Selection, crossover, and mutation operators
119//! - [`fitness`]: Fitness traits and benchmark functions
120//! - [`population`]: Population management and individual types
121//! - [`termination`]: Stopping criteria
122//! - [`hyperparameter`]: Adaptive and Bayesian hyperparameter tuning
123//! - [`interactive`]: Human-in-the-loop evolutionary optimization
124//! - [`checkpoint`]: State serialization for pause/resume
125//! - [`inference`]: Evolution as inference — priors as programs, MH, tempered SMC, grammar GP (`ppl`)
126//!
127//! ## Examples
128//!
129//! - `sphere_optimization.rs`, `rastrigin_benchmark.rs`, `cma_es_example.rs`,
130//!   `island_model.rs`, `symbolic_regression.rs` (classic GP),
131//!   `checkpointing.rs`, `interactive_evolution.rs`: the classic layer
132//! - `bayesian_evolution.rs`: the inference layer end-to-end (SMC + MH + adaptive GA)
133//! - `symbolic_regression_inference.rs`: **flagship** — symbolic regression as
134//!   exact Bayesian inference over a probabilistic grammar
135
136#[cfg(feature = "classic")]
137pub mod algorithms;
138#[cfg(feature = "classic")]
139pub mod checkpoint;
140#[cfg(feature = "classic")]
141pub mod diagnostics;
142pub mod error;
143pub mod fitness;
144#[cfg(feature = "ppl")]
145pub mod inference;
146
147/// Deprecated alias for [`inference`] (the module was renamed in 0.2.0).
148#[cfg(feature = "ppl")]
149#[deprecated(since = "0.2.0", note = "renamed to `inference`")]
150pub use inference as fugue_integration;
151pub mod genome;
152#[cfg(feature = "classic")]
153pub mod hyperparameter;
154#[cfg(feature = "classic")]
155pub mod interactive;
156#[cfg(feature = "classic")]
157pub mod operators;
158#[cfg(feature = "classic")]
159pub mod population;
160#[cfg(feature = "classic")]
161pub mod termination;
162
163/// Prelude module for convenient imports
164pub mod prelude {
165    #[cfg(feature = "classic")]
166    pub use crate::algorithms::prelude::*;
167    #[cfg(feature = "classic")]
168    pub use crate::checkpoint::prelude::*;
169    #[cfg(feature = "classic")]
170    pub use crate::diagnostics::prelude::*;
171    pub use crate::error::*;
172    pub use crate::fitness::prelude::*;
173    pub use crate::genome::prelude::*;
174    #[cfg(feature = "classic")]
175    pub use crate::hyperparameter::prelude::*;
176    #[cfg(feature = "ppl")]
177    pub use crate::inference::prelude::*;
178    #[cfg(feature = "classic")]
179    pub use crate::interactive::prelude::*;
180    #[cfg(feature = "classic")]
181    pub use crate::operators::prelude::*;
182    #[cfg(feature = "classic")]
183    pub use crate::population::prelude::*;
184    #[cfg(feature = "classic")]
185    pub use crate::termination::prelude::*;
186}