Bug fixes

This commit is contained in:
hal8174 2024-08-27 13:53:31 +02:00
parent be1d26ebd0
commit a11b39cf9f
8 changed files with 336 additions and 70 deletions

View file

@ -1,8 +1,82 @@
use crate::belt_finding::common::PathField;
use crate::belt_finding::conflict_avoidance::ConflictAvoidance;
use crate::common::visualize::{Color, Symbol, Visualization, Visualize};
use crate::prelude::*;
use rand::{seq::SliceRandom, Rng};
use serde::{Deserialize, Serialize};
pub struct GeneticAlgorithm<'a> {
problem: &'a Problem,
population: Vec<PathLayout<'a>>,
population_size: usize,
population_keep: usize,
population_new: usize,
}
impl<'a> GeneticAlgorithm<'a> {
pub fn new<R: Rng + ?Sized>(
problem: &'a Problem,
population_size: usize,
population_keep: usize,
population_new: usize,
rng: &mut R,
) -> GeneticAlgorithm<'a> {
let mut population = Vec::new();
while population.len() < population_size {
if let Some(p) = PathLayout::new(Layout::new(problem, rng)) {
population.push(p);
}
}
population.sort_by_cached_key(|p| p.score());
println!("Best score: {}", population[0].score());
population[0].print_visualization();
GeneticAlgorithm {
problem,
population,
population_size,
population_keep,
population_new,
}
}
pub fn generation<R: Rng + ?Sized>(&mut self, rng: &mut R) {
for i in self.population_keep..(self.population_keep + self.population_new) {
loop {
if let Some(p) = PathLayout::new(Layout::new(self.problem, rng)) {
self.population[i] = p;
break;
}
}
}
for i in (self.population_keep + self.population_new)..self.population_size {
let j = i - (self.population_keep + self.population_new);
loop {
if let Some(p) = PathLayout::new(self.population[j].layout.mutate(rng)) {
self.population[i] = p;
break;
}
}
}
self.population.sort_by_cached_key(|p| p.score());
println!("Best score: {}", self.population[0].score());
self.population[0].print_visualization();
}
pub fn output_population(&self) {
println!("Population:");
for (i, p) in self.population.iter().enumerate() {
println!("{i:3}: {}", p.score());
p.print_visualization();
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct Block {
pub(crate) size: Position,
@ -40,6 +114,85 @@ pub struct Layout<'a> {
pub(crate) blocks: Vec<(Position, Direction)>,
}
pub struct PathLayout<'a> {
layout: Layout<'a>,
paths: Vec<Vec<PathField>>,
score: usize,
}
impl<'a> PathLayout<'a> {
pub fn new(layout: Layout<'a>) -> Option<PathLayout<'a>> {
layout.print_visualization();
let mut p = crate::belt_finding::Problem::from_layout(&layout);
if !p.find_path() {
return None;
}
p.print();
let mut c = ConflictAvoidance::new(p);
if !c.remove_all_conflicts() {
return None;
}
let paths = c.get_paths().to_vec();
let score = paths
.iter()
.map(|path| path.iter().skip(1).map(|p| p.cost()).sum::<usize>())
.sum();
Some(PathLayout {
layout,
paths,
score,
})
}
fn score(&self) -> usize {
self.score
}
}
impl<'a> Visualize for PathLayout<'a> {
fn visualize(&self) -> Visualization {
let mut v = self.layout.visualize();
let offset = self.layout.blocks.len();
for (i, path) in self.paths.iter().enumerate() {
for p in &path[1..] {
match p {
PathField::Belt { pos, dir } => {
v.add_symbol(
*pos,
Symbol::Arrow(*dir),
Some(Color::index(i + offset)),
None,
);
}
PathField::Underground { pos, dir, len } => {
v.add_symbol(
*pos,
Symbol::ArrowEnter(*dir),
Some(Color::index(i + offset)),
None,
);
v.add_symbol(
pos.in_direction(dir, *len as i32),
Symbol::ArrowEnter(*dir),
Some(Color::index(i + offset)),
None,
);
}
}
}
}
v
}
}
impl Problem {
pub fn new(size: Position) -> Self {
Self {