diff --git a/examples/layout.rs b/examples/layout.rs index aa6bf71..1d3d667 100644 --- a/examples/layout.rs +++ b/examples/layout.rs @@ -1,5 +1,8 @@ use clap::Parser; -use factorio_blueprint::layout::GeneticAlgorithm; +use factorio_blueprint::{ + common::visualize::Visualize, + layout::{genetic_algorithm2, GeneticAlgorithm, PathLayout}, +}; use rand::{rngs::SmallRng, SeedableRng}; #[derive(Debug, Parser)] @@ -19,12 +22,24 @@ fn main() { dbg!(&p); - let mut g = GeneticAlgorithm::new(&p, 20, 2, 0, &mut rng); + // let mut g = GeneticAlgorithm::new(&p, 20, 2, 0, &mut rng); - for i in 0..100 { - println!("Generatrion {i}"); - g.generation(&mut rng); - } + // for i in 0..100 { + // println!("Generatrion {i}"); + // g.generation(&mut rng); + // } // g.output_population(); + + let mut m: Option = None; + for _ in 0..20 { + let g = genetic_algorithm2(&p, 10, 320, &mut rng); + + g.print_visualization(); + if m.as_ref().is_none_or(|m| g.score() < m.score()) { + m = Some(g); + } + } + + m.unwrap().print_visualization(); } diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 309aaaf..2cd5def 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -105,6 +105,48 @@ impl<'a> GeneticAlgorithm<'a> { } } +pub fn genetic_algorithm2<'a, R: Rng + ?Sized>( + problem: &'a Problem, + new_layouts: usize, + mutation_timeout: usize, + rng: &'_ mut R, +) -> PathLayout<'a> { + let mut m = (0..new_layouts) + .map(|_| valid_path_layout(problem, rng)) + .min_by_key(|p| p.score()) + .unwrap(); + + m.print_visualization(); + + let mut last_improvement = 0; + let mut count = 0; + + while last_improvement < mutation_timeout { + last_improvement += 1; + count += 1; + if let Some(p) = PathLayout::new(m.layout.mutate(rng)) { + if p.score() < m.score() { + m = p; + println!("Step: {count}"); + m.print_visualization(); + last_improvement = 0; + } + } + } + m +} + +pub fn valid_path_layout<'a, R: Rng + ?Sized>( + problem: &'a Problem, + rng: &'_ mut R, +) -> PathLayout<'a> { + loop { + if let Some(p) = PathLayout::new(Layout::new(problem, rng)) { + return p; + } + } +} + #[derive(Debug, Serialize, Deserialize)] pub(crate) struct Block { pub(crate) size: Position, @@ -189,7 +231,7 @@ impl<'a> PathLayout<'a> { }) } - fn score(&self) -> usize { + pub fn score(&self) -> usize { self.score } } @@ -347,7 +389,7 @@ impl Layout<'_> { loop { let p = r.choose_weighted(rng, |i| i.1).unwrap(); - if p.0(&mut s, rng) && rng.gen_bool(0.2) { + if p.0(&mut s, rng) && rng.gen_bool(0.05) { break; } }