Crate genetic_rs

Crate genetic_rs 

Source
Expand description

§genetic-rs

github crates.io docs.rs

A small crate for quickstarting genetic algorithm projects.

§Features

First off, this crate comes with the builtin, crossover, and genrand features by default. If you want it to be parallelized (which is true in most cases), you can add the rayon feature. If you want your crossover to be speciated, you can add the speciation feature.

§How to Use

[!NOTE] If you are interested in implementing NEAT with this, try out the neat crate

Here’s a simple genetic algorithm:

use genetic_rs::prelude::*;

// `Mitosis` can be derived if both `Clone` and `RandomlyMutable` are present.
#[derive(Clone, Debug, Mitosis)]
struct MyGenome {
    field1: f32,
}

// required in all of the builtin Repopulators as requirements of `Mitosis` and `Crossover`
impl RandomlyMutable for MyGenome {
    fn mutate(&mut self, rate: f32, rng: &mut impl Rng) {
        self.field1 += rng.gen::<f32>() * rate;
    }
}

// allows us to use `Vec::gen_random` for the initial population. note that `Vec::gen_random` has a slightly different function signature depending on whether the `rayon` feature is enabled.
impl GenerateRandom for MyGenome {
    fn gen_random(rng: &mut impl Rng) -> Self {
        Self { field1: rng.gen() }
    }
}

fn my_fitness_fn(ent: &MyGenome) -> f32 {
    // this just means that the algorithm will try to create as big a number as possible due to fitness being directly taken from the field.
    // in a more complex genetic algorithm, you will want to utilize `ent` to test them and generate a reward.
    ent.field1
}

fn main() {
    let mut rng = rand::rng();
    let mut sim = GeneticSim::new(
        // you must provide a random starting population. 
        // size will be preserved in builtin nextgen fns, but it is not required to keep a constant size if you were to build your own nextgen function.
        // in this case, the compiler can infer the type of `Vec::gen_random` because of the input of `my_fitness_fn`.
        // this is the `rayon` feature signature.
        Vec::gen_random(100),
        FitnessEliminator::new_with_default(my_fitness_fn),
        MitosisRepopulator::new(0.25), // 25% mutation rate
    );
 
    // perform evolution (100 gens)
    sim.perform_generations(100);
 
    dbg!(sim.genomes);
}

That is the minimal code for a working genetic algorithm on default features (+ rayon). You can read the docs or check the examples for more complicated systems. I highly recommend looking into crossover reproduction, as it tends to produce better results than mitosis.

§License

This project falls under the MIT license.

Modules§

builtin
Built-in nextgen functions and traits to go with them.
prelude

Structs§

GeneticSim
This struct is the main entry point for the simulation. It handles the state and evolution of the genomes based on what eliminator and repopulator it receives.

Traits§

Eliminator
Tests and eliminates the unfit from the simulation.
FeatureBoundedEliminator
Internal trait that simply deals with the trait bounds of features to avoid duplicate code. It is blanket implemented, so you should never have to reference this directly.
FeatureBoundedGenome
Internal trait that simply deals with the trait bounds of features to avoid duplicate code. It is blanket implemented, so you should never have to reference this directly.
FeatureBoundedRepopulator
Internal trait that simply deals with the trait bounds of features to avoid duplicate code. It is blanket implemented, so you should never have to reference this directly.
GenerateRandom
Helper trait used in the generation of random starting populations
GenerateRandomCollection
Blanket trait used on collections that contain objects implementing GenerateRandom
Repopulator
Refills the population of the simulation based on survivors.
Rng