Add second genetic algorithm.

This commit is contained in:
hal8174 2024-09-15 14:14:45 +02:00
parent 29450a1c65
commit a52816834f
2 changed files with 65 additions and 8 deletions

View file

@ -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<PathLayout> = 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();
}

View file

@ -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;
}
}