use std::f64::consts::PI; use eyre::Result; use memega::cfg::{ Cfg, Crossover, Mutation, Niching, Replacement, Species, Stagnation, StagnationCondition, Survival, }; use memega::lgp::asm::lgp_asm; use memega::lgp::exec::LgpExec; use memega::lgp::state::{lgp_runner_fn, LgpGenomeConfig, State}; use memega::util::run::run_evolve; use rand::Rng; fn lgp_cfg() -> Cfg { Cfg::new(2000) .with_mutation(Mutation::Adaptive) .with_crossover(Crossover::Adaptive) .with_survival(Survival::TopProportion(0.1)) .with_species(Species::None) .with_niching(Niching::None) .with_stagnation(Stagnation::ContinuousAfter(100)) .with_stagnation_condition(StagnationCondition::Epsilon(2.0)) .with_replacement(Replacement::ReplaceChildren(0.5)) .with_par_fitness(true) } fn lgp_fitness(s: &State, _gen: usize) -> f64 { let mut fitness = 0.0; for _ in 0..100 { let mut r = rand::thread_rng(); let mut reg = vec![0.0; s.num_reg]; // Space for work and answer. let x = r.gen_range(0.0..100.0); reg[1] = -1.0; reg[2] = 1.0; reg[3] = x; let mut exec = LgpExec::new(®, &s.ops, 200); exec.run(); let mut ans = 0.0; for i in 1..(x as usize) { ans += 1.0 / (i as f64); } fitness += 1.0 / (1.0 + (ans - exec.reg(0)).abs()) } fitness + 1.0 / (1.0 + s.ops.len() as f64) } fn run_lgp() -> Result<()> { use plotters::prelude::*; let code = lgp_asm( "add r0, r3 div r1, r0 abs r3 mul r0, r0 add r0, r3 add r0, r1 ", )?; let xleft = -PI; let xright = PI; let root = BitMapBackend::new("test.png", (640, 480)).into_drawing_area(); root.fill(&WHITE)?; let mut chart = ChartBuilder::on(&root) .caption("stuff", ("sans-serif", 50).into_font()) .margin(5) .x_label_area_size(30) .y_label_area_size(30) .build_cartesian_2d(xleft..xright, -50.0..50.0)?; chart.configure_mesh().draw()?; chart .draw_series(LineSeries::new( (-50..=50).map(|x| x as f64 / 50.0 * (xright - xleft)).map(|x| { let mut lgp = LgpExec::new(&[0.0, -1.0, 1.0, x], &code, 200); lgp.run(); (x, lgp.reg(0)) }), &RED, ))? .label("y = stuff"); chart .configure_series_labels() .background_style(&WHITE.mix(0.8)) .border_style(&BLACK) .draw()?; Ok(()) } #[test] fn test_lgp() -> Result<()> { let cfg = lgp_cfg(); run_evolve(lgp_runner_fn(LgpGenomeConfig::new(4, 6), cfg, lgp_fitness), 10000, 10, 100)?; run_lgp()?; Ok(()) }