1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
//! # moors
//!
//! <div align="center">
//! <strong>Multi‑Objective Optimization in Pure Rust</strong><br>
//! Fast, extensible evolutionary algorithms with first‑class ndarray support.
//! </div>
//!
//! ---
//!
//! ## Overview
//!
//! `moors` provides a battery of evolutionary algorithms for solving *multi‑objective*
//! optimization problems. The core goals are:
//!
//! * **Performance** – minimal allocations, Rayon‑powered parallel loops where it matters.
//! * **Extensibility** – every operator (sampling, crossover, mutation, selection,
//! survival) is pluggable via pure Rust traits.
//!
//! Currently implemented algorithms
//!
//! | Family | Algorithms |
//! |--------|------------|
//! | NSGA | **NSGA‑II**, NSGA‑III, RNSGA‑II |
//! | SPEA | SPEA‑2 |
//! | Others | AGE‑MOEA, REVEA *(WIP)* |
//!
//! ## Quick start
//!
//! ```rust,no_run
//! use ndarray::{Array1, Axis, stack};
//!
//! use moors::{
//! algorithms::{MultiObjectiveAlgorithmError, Nsga2Builder},
//! duplicates::ExactDuplicatesCleaner,
//! genetic::{PopulationConstraints, PopulationFitness, PopulationGenes},
//! operators::{
//! crossover::SinglePointBinaryCrossover, mutation::BitFlipMutation,
//! sampling::RandomSamplingBinary,
//! },
//! };
//!
//! // ----- problem data (0/1 knapsack) -------------------------------------
//! const WEIGHTS: [f64; 5] = [12.0, 2.0, 1.0, 4.0, 10.0];
//! const VALUES: [f64; 5] = [ 4.0, 2.0, 1.0, 5.0, 3.0];
//! const CAPACITY: f64 = 15.0;
//!
//! /// Multi‑objective fitness ⇒ [−total_value, total_weight]
//! fn fitness(pop_genes: &PopulationGenes) -> PopulationFitness {
//! let w = Array1::from_vec(WEIGHTS.into());
//! let v = Array1::from_vec(VALUES.into());
//! let total_v = pop_genes.dot(&v);
//! let total_w = pop_genes.dot(&w);
//! stack(Axis(1), &[(-&total_v).view(), total_w.view()]).unwrap()
//! }
//!
//! /// Single inequality constraint ⇒ total_weight − CAPACITY ≤ 0
//! fn constraints(pop_genes: &PopulationGenes) -> PopulationConstraints {
//! let w = Array1::from_vec(WEIGHTS.into());
//! (pop_genes.dot(&w) - CAPACITY).insert_axis(Axis(1))
//! }
//!
//! fn main() -> Result<(), MultiObjectiveAlgorithmError> {
//! let mut algo = Nsga2Builder::default()
//! .fitness_fn(fitness)
//! .constraints_fn(constraints)
//! .sampler(RandomSamplingBinary::new())
//! .crossover(SinglePointBinaryCrossover::new())
//! .mutation(BitFlipMutation::new(0.5))
//! .duplicates_cleaner(ExactDuplicatesCleaner::new())
//! .num_vars(5)
//! .num_objectives(2)
//! .num_constraints(1)
//! .population_size(100)
//! .crossover_rate(0.9)
//! .mutation_rate(0.1)
//! .num_offsprings(32)
//! .num_iterations(200)
//! .build()?;
//!
//! algo.run()?;
//! println!("Final population size: {}", algo.population()?.len());
//! Ok(())
//! }
//! ```
//!
//! ## Module layout
//!
//! * [`algorithms`](crate::algorithms) – high‑level algorithm builders
//! * [`operators`](crate::operators) – sampling, crossover, mutation, selection, survival
//! * [`genetic`](crate::genetic) – core data types (`Individual`, `Population`, …)
//! * [`evaluator`](crate::evaluator) – fitness + constraints evaluation pipeline
//! * [`random`](crate::random) – pluggable RNG abstraction
//! * [`duplicates`](crate::duplicates) – duplicate‑handling strategies
//!
//! ---
extern crate core;