Bug fixes
This commit is contained in:
		
							parent
							
								
									be1d26ebd0
								
							
						
					
					
						commit
						a11b39cf9f
					
				
					 8 changed files with 336 additions and 70 deletions
				
			
		|  | @ -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 { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue