Implementation of the NEAT algorithm using genetic-rs.
- serde - Implements
SerializeandDeserializeon most of the types in this crate.
Do you like this crate and want to support it? If so, leave a ⭐
The NeuralNetwork<I, O> struct is the main type exported by this crate. The I is the number of input neurons, and O is the number of output neurons. It implements GenerateRandom, RandomlyMutable, Mitosis, and Crossover, with a lot of customizability. This means that you can use it standalone as your organism's entire genome:
use neat::*;
fn fitness(net: &NeuralNetwork<5, 6>) -> f32 {
// ideally you'd test multiple times for consistency,
// but this is just a simple example.
// it's also generally good practice to normalize your inputs between -1..1,
// but NEAT is usually flexible enough to still work anyways
let inputs = [1.0, 2.0, 3.0, 4.0, 5.0];
let outputs = net.predict(inputs);
// simple fitness: sum of outputs
// you should replace this with a real fitness test
outputs.iter().sum()
}
fn main() {
let mut rng = rand::rng();
let mut sim = GeneticSim::new(
Vec::gen_random(&mut rng, 100),
FitnessEliminator::new_without_observer(fitness),
CrossoverRepopulator::new(0.25, ReproductionSettings::default()),
);
sim.perform_generations(100);
}Or just a part of a more complex genome:
use neat::*;
#[derive(Clone, Debug)]
struct PhysicalStats {
strength: f32,
speed: f32,
// ...
}
// ... implement `RandomlyMutable`, `GenerateRandom`, `Crossover`, `Default`, etc.
#[derive(Clone, Debug, GenerateRandom, RandomlyMutable, Mitosis, Crossover)]
#[randmut(create_context(name = MyGenomeMutate, derive(Default, Clone, Debug)))]
#[mitosis(create_context(name = MyGenomeReproduce, derive(Default, Clone, Debug)))]
#[crossover(with_context = MyGenomeReproduce)]
struct MyGenome {
brain: NeuralNetwork<4, 2>,
stats: PhysicalStats,
}
fn fitness(genome: &MyGenome) -> f32 {
let inputs = [1.0, 2.0, 3.0, 4.0];
let outputs = genome.brain.predict(inputs);
// fitness uses both brain output and stats
outputs.iter().sum::<f32>() + genome.stats.strength + genome.stats.speed
}
// main is the exact same as before
fn main() {
let mut rng = rand::rng();
let mut sim = GeneticSim::new(
Vec::gen_random(&mut rng, 100),
FitnessEliminator::new_without_observer(fitness),
CrossoverRepopulator::new(0.25, MyGenomeReproduce::default()),
);
sim.perform_generations(100);
}If you want more in-depth examples, look at the examples. You can also check out the genetic-rs docs to see what other options you have to customize your genetic simulation.
This crate falls under the MIT license