An neural network-based implementation of the OxiNEAT
crate's Genome
trait.
Provides a GenomeNN
type usable in OxiNEAT
Population
s, 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.
```rust use oxineat::{Population, PopulationConfig}; use oxineatnn::{ genomics::{ActivationType, GeneticConfig, NNGenome}, networks::FunctionApproximatorNetwork, }; use serdejson; 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!: {}", serde_json::to_string(&population.champion()).unwrap());
break;
}
if let Err(e) = population.evolve() {
eprintln!("{}", e);
break;
}
}
} ```
Licensed under the MIT license.