diff --git a/src/lib.rs b/src/lib.rs index ee9f769..0dd0b8c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,3 +23,68 @@ pub use topology::*; #[cfg(feature = "serde")] pub use nnt_serde::*; + +#[cfg(test)] +mod tests { + use super::*; + use rand::prelude::*; + + #[derive(RandomlyMutable, DivisionReproduction, Clone)] + struct AgentDNA { + network: NeuralNetworkTopology<2, 1>, + } + + impl Prunable for AgentDNA {} + + impl GenerateRandom for AgentDNA { + fn gen_random(rng: &mut impl Rng) -> Self { + Self { + network: NeuralNetworkTopology::new(0.01, 3, rng), + } + } + } + + #[test] + fn basic_test() { + let fitness = |g: &AgentDNA| { + let network = NeuralNetwork::from(&g.network); + let mut fitness = 0.; + let mut rng = rand::thread_rng(); + + for _ in 0..100 { + let n = rng.gen::() * 10000.; + let base = rng.gen::() * 10.; + let expected = n.log(base); + + let [answer] = network.predict([n, base]); + network.flush_state(); + + fitness += 5. / (answer - expected).abs(); + } + + fitness + }; + + #[cfg(not(feature = "rayon"))] + let mut rng = rand::thread_rng(); + + let mut sim = GeneticSim::new( + #[cfg(not(feature = "rayon"))] + Vec::gen_random(&mut rng, 100), + #[cfg(feature = "rayon")] + Vec::gen_random(100), + fitness, + division_pruning_nextgen, + ); + + for _ in 0..100 { + sim.next_generation(); + } + + let mut fits: Vec<_> = sim.genomes.iter().map(fitness).collect(); + + fits.sort_by(|a, b| a.partial_cmp(&b).unwrap()); + + dbg!(fits); + } +}