use std::cmp::Ordering;
use genetic_rs::prelude::*;
#[derive(Clone, Debug)]
struct Genome(f32);
impl GenerateRandom for Genome {
fn gen_random(rng: &mut impl rand::Rng) -> Self {
Self(rng.random())
}
}
fn smaller_wins(a: &Genome, b: &Genome) -> KnockoutWinner {
a.0.total_cmp(&b.0).into()
}
#[test]
fn knockout_winner_not_impl() {
assert_eq!(!KnockoutWinner::First, KnockoutWinner::Second);
assert_eq!(!KnockoutWinner::Second, KnockoutWinner::First);
}
#[test]
fn knockout_winner_from_ordering() {
assert_eq!(KnockoutWinner::from(Ordering::Less), KnockoutWinner::First);
assert_eq!(KnockoutWinner::from(Ordering::Equal), KnockoutWinner::First);
assert_eq!(
KnockoutWinner::from(Ordering::Greater),
KnockoutWinner::Second
);
}
#[test]
fn knockout_winner_into_usize() {
assert_eq!(usize::from(KnockoutWinner::First), 0usize);
assert_eq!(usize::from(KnockoutWinner::Second), 1usize);
}
#[test]
fn knockout_output_half_size_even_input() {
let genomes: Vec<Genome> = (0..10).map(|i| Genome(i as f32)).collect();
let mut elim = KnockoutEliminator::new(smaller_wins, ActionIfOdd::Panic);
let survivors = elim.eliminate(genomes);
assert_eq!(survivors.len(), 5);
}
#[test]
fn knockout_action_if_odd_keep_single() {
let genomes: Vec<Genome> = (0..11).map(|i| Genome(i as f32)).collect();
let mut elim = KnockoutEliminator::new(smaller_wins, ActionIfOdd::KeepSingle);
let survivors = elim.eliminate(genomes);
assert_eq!(survivors.len(), 6);
}
#[test]
fn knockout_action_if_odd_delete_single() {
let genomes: Vec<Genome> = (0..11).map(|i| Genome(i as f32)).collect();
let mut elim = KnockoutEliminator::new(smaller_wins, ActionIfOdd::DeleteSingle);
let survivors = elim.eliminate(genomes);
assert_eq!(survivors.len(), 5);
}
#[test]
#[should_panic]
fn knockout_action_if_odd_panic_panics() {
let genomes: Vec<Genome> = (0..11).map(|i| Genome(i as f32)).collect();
let mut elim = KnockoutEliminator::new(smaller_wins, ActionIfOdd::Panic);
let _ = elim.eliminate(genomes);
}
#[test]
fn knockout_single_genome_returns_unchanged() {
let genomes = vec![Genome(42.0)];
let mut elim = KnockoutEliminator::new(smaller_wins, ActionIfOdd::Panic);
let survivors = elim.eliminate(genomes);
assert_eq!(survivors.len(), 1);
assert!((survivors[0].0 - 42.0).abs() < 1e-6);
}
#[test]
fn knockout_correct_genome_survives() {
let genomes: Vec<Genome> = (0..10).map(|i| Genome(i as f32)).collect();
let mut elim = KnockoutEliminator::new(smaller_wins, ActionIfOdd::Panic);
let survivors = elim.eliminate(genomes);
for g in &survivors {
assert!(
(g.0 as i32) % 2 == 0,
"expected even (smaller) value to survive each pair, got {}",
g.0
);
}
}
#[test]
fn fitness_knockout_fn_delegates_to_fitness_fn() {
let ko_fn = FitnessKnockoutFn::new(|g: &Genome| g.0);
let a = Genome(1.0);
let b = Genome(9.0);
assert_eq!(ko_fn.knockout(&a, &b), KnockoutWinner::First);
assert_eq!(ko_fn.knockout(&b, &a), KnockoutWinner::Second);
}