OxiNEAT-NN

An neural network-based implementation of the OxiNEAT crate's Genome trait.

Provides a GenomeNN type usable in OxiNEAT Populations, as well as two neural network implementations which can be generated from a GenomeNN: - RealTimeNetwork: best suited for real-time control tasks, with new inputs set for each activation, and multiple time-steps involved. - FunctionApproximatorNetwork: best suited for more instantaneous single-output-per-input function approximation tasks.

Example usage: evolution of XOR function approximator

```rust use oxineat::{Population, PopulationConfig}; use oxineat_nn::{ genomics::{ActivationType, GeneticConfig, NNGenome}, networks::FunctionApproximatorNetwork, }; use std::num::NonZeroUsize;

// Allowed error margin for neural net answers. const ERROR_MARGIN: f32 = 0.3;

fn evaluate_xor(genome: &NNGenome) -> f32 { let mut network = FunctionApproximatorNetwork::from::<1>(genome);

let values = [
    ([1.0, 0.0, 0.0], 0.0),
    ([1.0, 0.0, 1.0], 1.0),
    ([1.0, 1.0, 0.0], 1.0),
    ([1.0, 1.0, 1.0], 0.0),
];

let mut errors = [0.0, 0.0, 0.0, 0.0];
for (i, (input, output)) in values.iter().enumerate() {
    errors[i] = (network.evaluate_at(input)[0] - output).abs();
    if errors[i] < ERROR_MARGIN {
        errors[i] = 0.0;
    }
}

(4.0 - errors.iter().copied().sum::<f32>()).powf(2.0)

}

fn main() { let geneticconfig = GeneticConfig { inputcount: NonZeroUsize::new(3).unwrap(), outputcount: NonZeroUsize::new(1).unwrap(), activationtypes: vec![ActivationType::Sigmoid], outputactivationtypes: vec![ActivationType::Sigmoid], childmutationchance: 0.65, matebyaveragingchance: 0.4, suppressionresetchance: 1.0, initialexpressionchance: 1.0, weightbound: 5.0, weightresetchance: 0.2, weightnudgechance: 0.9, weightmutationpower: 2.5, nodeadditionmutationchance: 0.03, geneadditionmutationchance: 0.05, maxgeneadditionmutationattempts: 20, recursionchance: 0.0, excessgenefactor: 1.0, disjointgenefactor: 1.0, commonweight_factor: 0.4, ..GeneticConfig::zero() };

let population_config = PopulationConfig {
    size: NonZeroUsize::new(150).unwrap(),
    distance_threshold: 3.0,
    elitism: 1,
    survival_threshold: 0.2,
    sexual_reproduction_chance: 0.6,
    adoption_rate: 1.0,
    interspecies_mating_chance: 0.001,
    stagnation_threshold: NonZeroUsize::new(15).unwrap(),
    stagnation_penalty: 1.0,
};

let mut population = Population::new(population_config, genetic_config);
for _ in 0..100 {
    population.evaluate_fitness(evaluate_xor);
    if (population.champion().fitness() - 16.0).abs() < f32::EPSILON {
        println!("Solution found: {}", population.champion());
        break;
    }
    if let Err(e) = population.evolve() {
        eprintln!("{}", e);
        break;
    }
}

} ```

License

Licensed under the MIT license.