6 releases

Uses new Rust 2024

new 0.1.3 May 21, 2025
0.1.2 May 11, 2025
0.1.1 May 8, 2025
0.1.0 May 3, 2025
0.1.0-alpha.0 May 2, 2025

#102 in Machine learning

Download history 48/week @ 2025-04-26 584/week @ 2025-05-03 432/week @ 2025-05-10 208/week @ 2025-05-17

1,272 downloads per month

MIT license

345KB
6.5K SLoC

moors

License codecov crates.io crates.io downloads

Overview

moors is the core crate of the moo-rs project for solving multi-objective optimization problems with evolutionary algorithms. It's a pure-Rust crate for high-performance implementations of genetic algorithms

Features

  • NSGA-II, NSGA-III, R-NSGA-II, Age-MOEA, REVEA, SPEA-II (many more coming soon!)
  • Pluggable operators: sampling, crossover, mutation, duplicates removal
  • Flexible fitness & constraints via user-provided closures
  • Built on ndarray and faer

Installation

[dependencies]
moors = "0.1.1"

Quickstart


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
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;

/// Compute multi-objective fitness [–total_value, total_weight]
/// Returns an Array2<f64> of shape (population_size, 2)
fn fitness_knapsack(population_genes: &PopulationGenes) -> PopulationFitness {
    let weights_arr = Array1::from_vec(WEIGHTS.to_vec());
    let values_arr = Array1::from_vec(VALUES.to_vec());

    let total_values = population_genes.dot(&values_arr);
    let total_weights = population_genes.dot(&weights_arr);

    // stack two columns: [-total_values, total_weights]
    stack(Axis(1), &[(-&total_values).view(), total_weights.view()]).expect("stack failed")
}

fn constraints_knapsack(population_genes: &PopulationGenes) -> PopulationConstraints {
    let weights_arr = Array1::from_vec(WEIGHTS.to_vec());
    (population_genes.dot(&weights_arr) - CAPACITY).insert_axis(Axis(1))
}

fn main() -> Result<(), MultiObjectiveAlgorithmError> {
    // build the NSGA-II algorithm
    let mut algorithm = Nsga2Builder::default()
        .fitness_fn(fitness_knapsack)
        .constraints_fn(constraints_knapsack)
        .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(2)
        .build()?;

    algorithm.run()?;
    let population = algorithm.population()?;
    println!("Done! Population size: {}", population.len());

    Ok(())
}

Contributing

Contributions welcome! Please read the contribution guide and open issues or PRs in the relevant crate’s repository

License

This project is licensed under the MIT License.

Dependencies

~12MB
~252K SLoC