#[cfg(test)]
mod structures;
use crate::structures::{Chromosome, Gene};
use genetic_algorithms::{fitness::FitnessFnWrapper, population::Population};
#[test]
fn test_add_chromosomes_aga() {
let chromosome_1 = Chromosome {
dna: Vec::<Gene>::new(),
fitness: 20.0,
age: 0,
fitness_fn: FitnessFnWrapper::default(),
};
let chromosome_2 = Chromosome {
dna: Vec::<Gene>::new(),
fitness: 40.0,
age: 0,
fitness_fn: FitnessFnWrapper::default(),
};
let chromosome_3 = Chromosome {
dna: Vec::<Gene>::new(),
fitness: 120.0,
age: 0,
fitness_fn: FitnessFnWrapper::default(),
};
let mut chromosomes = vec![chromosome_1, chromosome_2, chromosome_3];
let mut population = Population::new_empty();
population.add_chromosomes(&mut chromosomes);
population.recalculate_aga();
assert_eq!(population.f_max, 120.0);
assert_eq!(population.f_avg, 60.0);
assert_eq!(population.size(), 3);
}
#[test]
fn test_add_chromosomes() {
let chromosome_1 = Chromosome {
dna: Vec::<Gene>::new(),
fitness: 20.0,
age: 0,
fitness_fn: FitnessFnWrapper::default(),
};
let chromosome_2 = Chromosome {
dna: Vec::<Gene>::new(),
fitness: 40.0,
age: 0,
fitness_fn: FitnessFnWrapper::default(),
};
let chromosome_3 = Chromosome {
dna: Vec::<Gene>::new(),
fitness: 120.0,
age: 0,
fitness_fn: FitnessFnWrapper::default(),
};
let mut chromosomes = vec![chromosome_1, chromosome_2, chromosome_3];
let mut population = Population::new_empty();
population.add_chromosomes(&mut chromosomes);
assert_eq!(population.size(), 3);
}
#[test]
fn test_fitness_zero_is_preserved() {
use genetic_algorithms::configuration::ProblemSolving;
let chromosome = Chromosome {
dna: vec![Gene { id: 5 }, Gene { id: 10 }],
fitness: 0.0, age: 0,
fitness_fn: FitnessFnWrapper::default(),
};
let mut population = Population::new(vec![chromosome.clone()]);
population.fitness_calculation(1, ProblemSolving::Maximization);
assert_eq!(
population.chromosomes[0].fitness, 0.0,
"Chromosome with fitness 0.0 should not be recalculated (NaN sentinel)"
);
}
#[test]
fn test_nan_fitness_triggers_recalculation() {
use genetic_algorithms::configuration::ProblemSolving;
let chromosome = Chromosome {
dna: vec![Gene { id: 5 }, Gene { id: 10 }],
fitness: f64::NAN,
age: 0,
fitness_fn: FitnessFnWrapper::default(),
};
let mut population = Population::new(vec![chromosome]);
population.fitness_calculation(1, ProblemSolving::Maximization);
assert_eq!(
population.chromosomes[0].fitness, 10.0,
"Chromosome with NaN fitness should be recalculated"
);
}
#[test]
fn test_fmax_all_negative_fitness() {
let mut chromosomes: Vec<Chromosome> = vec![
Chromosome {
dna: Vec::<Gene>::new(),
fitness: -100.0,
age: 0,
fitness_fn: FitnessFnWrapper::default(),
},
Chromosome {
dna: Vec::<Gene>::new(),
fitness: -50.0,
age: 0,
fitness_fn: FitnessFnWrapper::default(),
},
Chromosome {
dna: Vec::<Gene>::new(),
fitness: -200.0,
age: 0,
fitness_fn: FitnessFnWrapper::default(),
},
];
let mut population = Population::new_empty();
population.add_chromosomes(&mut chromosomes);
population.recalculate_aga();
assert_eq!(
population.f_max, -50.0,
"f_max should correctly identify the largest negative fitness"
);
assert!(
(population.f_avg - (-350.0 / 3.0)).abs() < 1e-10,
"f_avg should be the mean of negative fitness values"
);
}
#[test]
fn test_fmax_mixed_negative_and_positive() {
let mut chromosomes: Vec<Chromosome> = vec![
Chromosome {
dna: Vec::<Gene>::new(),
fitness: -10.0,
age: 0,
fitness_fn: FitnessFnWrapper::default(),
},
Chromosome {
dna: Vec::<Gene>::new(),
fitness: 5.0,
age: 0,
fitness_fn: FitnessFnWrapper::default(),
},
Chromosome {
dna: Vec::<Gene>::new(),
fitness: -30.0,
age: 0,
fitness_fn: FitnessFnWrapper::default(),
},
];
let mut population = Population::new_empty();
population.add_chromosomes(&mut chromosomes);
population.recalculate_aga();
assert_eq!(population.f_max, 5.0);
assert!((population.f_avg - (-35.0 / 3.0)).abs() < 1e-10);
}
#[test]
fn test_fmax_single_chromosome() {
let mut chromosomes = vec![Chromosome {
dna: Vec::<Gene>::new(),
fitness: 42.0,
age: 0,
fitness_fn: FitnessFnWrapper::default(),
}];
let mut population = Population::new_empty();
population.add_chromosomes(&mut chromosomes);
population.recalculate_aga();
assert_eq!(population.f_max, 42.0);
assert_eq!(population.f_avg, 42.0);
}