#[cfg(test)]
mod engine_tests {
use radiate_core::*;
use radiate_engines::*;
use std::time::Duration;
#[test]
fn engine_can_minimize() {
let engine = GeneticEngine::builder()
.minimizing()
.codec(IntCodec::vector(5, 0..100))
.fitness_fn(|geno: Vec<i32>| geno.iter().sum::<i32>())
.build();
let result = engine.iter().until_score(0).last().unwrap();
let best = result.value();
assert_eq!(best.iter().sum::<i32>(), 0);
}
#[test]
fn engine_can_maximize() {
let mut engine = GeneticEngine::builder()
.codec(IntCodec::vector(5, 0..101))
.fitness_fn(|geno: Vec<i32>| geno.iter().sum::<i32>())
.build();
let result = engine.run(|ctx| ctx.score().as_i32() == 500);
assert_eq!(result.value().iter().sum::<i32>(), 500);
}
#[test]
fn engine_evolves_towards_target() {
let target = [1, 2, 3, 4, 5];
let mut engine = GeneticEngine::builder()
.minimizing()
.codec(IntCodec::vector(target.len(), 0..10))
.fitness_fn(move |geno: Vec<i32>| {
let mut score = 0;
for i in 0..geno.len() {
score += (geno[i] - target[i]).abs();
}
score
})
.build();
let result = engine.run(|ctx| ctx.score().as_i32() == 0);
assert_eq!(result.value(), &vec![1, 2, 3, 4, 5]);
}
#[test]
fn engine_can_eval_batch() {
let mut engine = GeneticEngine::builder()
.codec(IntChromosome::from((5, 0..100)))
.minimizing()
.executor(Executor::FixedSizedWorkerPool(7))
.batch_fitness_fn(|phenotypes: &[Vec<i32>]| {
assert!(
phenotypes.len() > 0,
"Batch should have more than one phenotype"
);
phenotypes
.iter()
.map(|geno| geno.iter().sum::<i32>())
.collect()
})
.build();
let result = engine.run(|ctx| ctx.score().as_i32() == 0);
assert_eq!(result.value().iter().sum::<i32>(), 0);
}
#[test]
fn test_engine_score_iterator() {
let engine = GeneticEngine::builder()
.minimizing()
.codec(IntCodec::vector(5, 0..100))
.fitness_fn(|geno: Vec<i32>| geno.iter().sum::<i32>())
.build();
let result = engine.iter().until_score(0).last().unwrap();
let best = result.value();
assert_eq!(best.iter().sum::<i32>(), 0);
assert_eq!(result.score().as_i32(), 0);
}
#[test]
fn test_engine_seconds_iterator() {
let engine = GeneticEngine::builder()
.minimizing()
.codec(IntCodec::vector(5, 0..100))
.fitness_fn(|geno: Vec<i32>| geno.iter().sum::<i32>())
.build();
let result = engine.iter().until_seconds(2_f64).last().unwrap();
assert_eq!((result.time().as_secs_f64() - 2_f64).abs().round(), 0.0);
}
#[test]
fn test_engine_iterations_iterator() {
let engine = GeneticEngine::builder()
.minimizing()
.codec(IntCodec::vector(5, 0..100))
.fitness_fn(|geno: Vec<i32>| geno.iter().sum::<i32>())
.build();
let result = engine.iter().limit(10).last().unwrap();
assert_eq!(result.index(), 10);
}
#[test]
fn test_engine_custom_iterator() {
let engine = GeneticEngine::builder()
.minimizing()
.codec(IntCodec::vector(5, 0..100))
.fitness_fn(|geno: Vec<i32>| geno.iter().sum::<i32>())
.build();
let result = engine
.iter()
.limit(vec![
Limit::Generation(15),
Limit::Seconds(Duration::from_secs_f64(3_f64)),
])
.last()
.unwrap();
assert_eq!(result.index(), 15);
}
#[test]
fn test_engine_control_pause_resume() {
use std::thread;
use std::time::Duration;
let mut engine = GeneticEngine::builder()
.minimizing()
.codec(IntCodec::vector(5, 0..100))
.fitness_fn(|geno: Vec<i32>| geno.iter().sum::<i32>())
.build();
let control = engine.control();
let handle = thread::spawn(move || {
let result = engine.iter().until_seconds(1_f64).last().unwrap();
assert_eq!((result.seconds() - 1_f64).abs().round(), 0.0);
});
thread::sleep(Duration::from_millis(100));
control.set_paused(true);
thread::sleep(Duration::from_millis(500));
control.set_paused(false);
handle.join().unwrap();
}
#[test]
fn test_engine_control_stop() {
use std::thread;
use std::time::Duration;
let mut engine = GeneticEngine::builder()
.minimizing()
.codec(IntCodec::vector(5, 0..100))
.fitness_fn(|geno: Vec<i32>| geno.iter().sum::<i32>())
.build();
let control = engine.control();
let handle = thread::spawn(move || {
let result = engine.iter().last().unwrap();
assert!(result.seconds() < 5_f64);
});
thread::sleep(Duration::from_millis(100));
control.stop();
handle.join().unwrap();
}
}