moors/
lib.rs

1//! # moors
2//!
3//! <div align="center">
4//! <strong>Multi‑Objective Optimization in Pure Rust</strong><br>
5//! Fast, extensible evolutionary algorithms with first‑class ndarray support.
6//! </div>
7//!
8//! ---
9//!
10//! ## Overview
11//!
12//! `moors` provides a battery of evolutionary algorithms for solving *multi‑objective*
13//! optimization problems.  The core goals are:
14//!
15//! * **Performance** – minimal allocations, Rayon‑powered parallel loops where it matters.
16//! * **Extensibility** – every operator (sampling, crossover, mutation, selection,
17//!   survival) is pluggable via pure Rust traits.
18//!
19//! Currently implemented algorithms
20//!
21//! | Family | Algorithms |
22//! |--------|------------|
23//! | NSGA   | **NSGA‑II**, NSGA‑III, RNSGA‑II |
24//! | SPEA   | SPEA‑2 |
25//! | Others | AGE‑MOEA, REVEA *(WIP)* |
26//!
27//! ## Quick start
28//!
29//! ```rust,no_run
30//! use ndarray::{Array1, Array2, Axis, stack};
31//!
32//! use moors::{
33//!     algorithms::{AlgorithmError, Nsga2Builder},
34//!     duplicates::ExactDuplicatesCleaner,
35//!     operators::{SinglePointBinaryCrossover, BitFlipMutation, RandomSamplingBinary},
36//! };
37//!
38//! // ----- problem data (0/1 knapsack) -------------------------------------
39//! const WEIGHTS: [f64; 5] = [12.0, 2.0, 1.0, 4.0, 10.0];
40//! const VALUES:  [f64; 5] = [ 4.0, 2.0, 1.0, 5.0,  3.0];
41//! const CAPACITY: f64 = 15.0;
42//!
43//! /// Multi‑objective fitness ⇒ [−total_value, total_weight]
44//! fn fitness(pop_genes: &Array2<f64>) -> Array2<f64> {
45//!     let w = Array1::from_vec(WEIGHTS.into());
46//!     let v = Array1::from_vec(VALUES.into());
47//!     let total_v = pop_genes.dot(&v);
48//!     let total_w = pop_genes.dot(&w);
49//!     stack(Axis(1), &[(-&total_v).view(), total_w.view()]).unwrap()
50//! }
51//!
52//! /// Single inequality constraint ⇒ total_weight − CAPACITY ≤ 0
53//! fn constraints(pop_genes: &Array2<f64>) -> Array1<f64> {
54//!     let w = Array1::from_vec(WEIGHTS.into());
55//!     pop_genes.dot(&w) - CAPACITY
56//! }
57//!
58//! fn main() -> Result<(), AlgorithmError> {
59//!     let mut algo = Nsga2Builder::default()
60//!         .fitness_fn(fitness)
61//!         .constraints_fn(constraints)
62//!         .sampler(RandomSamplingBinary::new())
63//!         .crossover(SinglePointBinaryCrossover::new())
64//!         .mutation(BitFlipMutation::new(0.5))
65//!         .duplicates_cleaner(ExactDuplicatesCleaner::new())
66//!         .num_vars(5)
67//!         .population_size(100)
68//!         .crossover_rate(0.9)
69//!         .mutation_rate(0.1)
70//!         .num_offsprings(32)
71//!         .num_iterations(200)
72//!         .build()?;
73//!
74//!     algo.run()?;
75//!     Ok(())
76//! }
77//! ```
78//!
79//! ## Module layout
80//!
81//! * [`algorithms`](crate::algorithms) – high‑level algorithm builders
82//! * [`operators`](crate::operators)  – sampling, crossover, mutation, selection, survival
83//! * [`genetic`](crate::genetic)      – core data types (`Individual`, `Population`, …)
84//! * [`evaluator`](crate::evaluator)  – fitness + constraints evaluation pipeline
85//! * [`random`](crate::random)        – pluggable RNG abstraction
86//! * [`duplicates`](crate::duplicates) – duplicate‑handling strategies
87//!
88//! ---
89
90extern crate core;
91extern crate paste;
92
93pub mod algorithms;
94pub mod duplicates;
95pub mod evaluator;
96pub mod genetic;
97pub(crate) mod helpers;
98pub mod non_dominated_sorting;
99pub mod operators;
100mod private;
101pub mod random;
102pub use algorithms::{
103    AgeMoea, AgeMoeaBuilder, AlgorithmBuilder, AlgorithmBuilderError, AlgorithmError,
104    GeneticAlgorithm, Ibea, IbeaBuilder, InitializationError, Nsga2, Nsga2Builder, Nsga3,
105    Nsga3Builder, Revea, ReveaBuilder, Rnsga2, Rnsga2Builder, Spea2, Spea2Builder,
106};
107pub use duplicates::{
108    CloseDuplicatesCleaner, ExactDuplicatesCleaner, NoDuplicatesCleaner, PopulationCleaner,
109};
110pub use evaluator::{ConstraintsFn, EvaluatorError, FitnessFn, NoConstraints};
111pub use genetic::{
112    Individual, IndividualMOO, IndividualSOO, Population, PopulationMOO, PopulationSOO,
113};
114pub use helpers::linalg::cross_euclidean_distances;
115pub use operators::selection;
116pub use operators::survival;
117pub use operators::{
118    AgeMoeaSurvival, ArithmeticCrossover, BitFlipMutation, CrossoverOperator,
119    DanAndDenisReferencePoints, DisplacementMutation, ExponentialCrossover,
120    FrontsAndRankingBasedSurvival, GaussianMutation, InversionMutation, MutationOperator,
121    Nsga2RankCrowdingSurvival, Nsga3ReferencePointsSurvival, OrderCrossover, PermutationSampling,
122    RandomSamplingBinary, RandomSamplingFloat, RandomSamplingInt, RandomSelectionMOO,
123    RankAndScoringSelectionMOO, ReveaReferencePointsSurvival, Rnsga2ReferencePointsSurvival,
124    SamplingOperator, ScrambleMutation, SelectionOperator, SimulatedBinaryCrossover,
125    SinglePointBinaryCrossover, Spea2KnnSurvival, StructuredReferencePoints, SurvivalOperator,
126    SwapMutation, TwoPointBinaryCrossover, UniformBinaryCrossover, UniformBinaryMutation,
127    UniformRealMutation, evolve::EvolveError,
128};
129pub use random::{MOORandomGenerator, NoopRandomGenerator, RandomGenerator, TestDummyRng};