Skip to content

Freezes at random iterations #97

@Nikita-Gz

Description

@Nikita-Gz

Hi. I was editing the example code provided in the documentation into an XOR task as an exercise for myself, and I noticed that sometimes the program freezes at a random iterations. I made the simulation loop print out the current iteration, and sometimes it would freeze at iteration 15, another time - 59, another - 72, etc. Here is the code to reproduce the error:

use neat::rand::Rng;
use neat::*;

const INPUT_SIZE: usize = 2;
const OUTPUT_SIZE: usize = 1;

#[derive(Clone, RandomlyMutable, DivisionReproduction)]
struct MyAgentDNA {
    network: NeuralNetworkTopology<INPUT_SIZE, OUTPUT_SIZE>,
}

impl GenerateRandom for MyAgentDNA {
    fn gen_random(rng: &mut impl rand::Rng) -> Self {
        Self {
            network: NeuralNetworkTopology::new(0.01, 3, rng),
        }
    }
}

struct MyAgent {
    network: NeuralNetwork<INPUT_SIZE, OUTPUT_SIZE>,
}

impl From<&MyAgentDNA> for MyAgent {
    fn from(value: &MyAgentDNA) -> Self {
        Self {
            network: NeuralNetwork::from(&value.network),
        }
    }
}

fn fitness(dna: &MyAgentDNA) -> f32 {
    // task: XOR
    // Example:
    // input A > 0.5 && input B > 0.5 -> output must be 0
    // input A < 0.5 && input B < 0.5 -> output must be 0
    // input A > 0.5 && input B < 0.5 -> output must be 1
    // input A < 0.5 && input B > 0.5 -> output must be 1

    let agent = MyAgent::from(dna);
    let mut rng = rand::thread_rng();
    let mut fitness: f32 = 0.0;
    let max_iter = 100;

    for _ in 0..max_iter {
        let a = rng.r#gen::<f32>();
        let b = rng.r#gen::<f32>();
        let a_enabled = a > 0.5;
        let b_enabled = b > 0.5;
        let expected_result: f32 = match a_enabled != b_enabled {
            true => 1.0,
            false => 0.0,
        };

        let predictions = agent.network.predict([a, b]);
        let prediction = predictions[0];

        // Distance between the expected result and the prediction will be
        // deducted from fitness
        let mistake: f32 = (expected_result - prediction).abs();
        fitness += 1.0 - (mistake);
    }
    return fitness / (max_iter as f32); // Normalize fitness
}

impl Prunable for MyAgentDNA {}

fn main() {
    let mut rng = rand::thread_rng();

    let mut sim = GeneticSim::new(
        Vec::gen_random(&mut rng, 100),
        fitness,
        division_pruning_nextgen,
    );

    // simulate 100 generations
    for iteration in 0..1000 {
        println!("Doing iteration {iteration}");
        sim.next_generation();
    }

    // display fitness results
    let fits: Vec<f32> = sim.genomes.iter().map(fitness).collect();
    let comparator = |a: &&f32, b: &&f32| a.partial_cmp(b).unwrap();

    dbg!(&fits, fits.iter().max_by(comparator));

    // Test out the best genome
    let best_genome = &sim.genomes[fits.iter().max_index()];
    let best_agent = MyAgent::from(best_genome);
    let preds_x = [[0.1, 0.1], [0.8, 0.1], [0.1, 0.8], [0.8, 0.8]];
    for x_set in preds_x {
        let result = best_agent.network.predict(x_set)[0];
        println!("X: {x_set:?}, Y: {result}");
    }
}

Does anyone have any idea as to why this happens and how to fix it?

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions