From f20a1841c92dc28d40ac200e6c016c006776abb3 Mon Sep 17 00:00:00 2001 From: hal8174 Date: Sat, 31 Aug 2024 02:00:28 +0200 Subject: [PATCH] Bug fixes --- layout2.yml | 2 +- src/belt_finding/common.rs | 2 +- src/belt_finding/conflict_avoidance.rs | 45 ++++++++++++++++++++++---- src/belt_finding/mod.rs | 2 +- src/layout/mod.rs | 22 +++++++++---- src/priority_queue/mod.rs | 27 ++++++++++------ 6 files changed, 75 insertions(+), 25 deletions(-) diff --git a/layout2.yml b/layout2.yml index e89adb4..0893db3 100644 --- a/layout2.yml +++ b/layout2.yml @@ -44,7 +44,7 @@ blocks: output: - offset: x: 0 - y: 2 + y: 3 dir: Left connections: - startblock: 1 diff --git a/src/belt_finding/common.rs b/src/belt_finding/common.rs index be3f43a..2010e9c 100644 --- a/src/belt_finding/common.rs +++ b/src/belt_finding/common.rs @@ -65,7 +65,7 @@ impl PathField { pub fn cost(&self) -> usize { match self { - PathField::Belt { pos: _, dir: _ } => 300, + PathField::Belt { pos: _, dir: _ } => 150, PathField::Underground { pos: _, dir: _, diff --git a/src/belt_finding/conflict_avoidance.rs b/src/belt_finding/conflict_avoidance.rs index fd4c955..f648e37 100644 --- a/src/belt_finding/conflict_avoidance.rs +++ b/src/belt_finding/conflict_avoidance.rs @@ -213,12 +213,16 @@ impl ConflictAvoidance { } } - let start_pos_offset = start_pos - offset; - b.set_blocked( - start_pos_offset.x as usize, - start_pos_offset.y as usize, - true, - ); + if xrange.contains(&(start_pos.x as usize)) + && yrange.contains(&(start_pos.y as usize)) + { + let p = start_pos - offset; + // println!("Blocked {:?}", p); + if b.get_blocked(p.x as usize, p.y as usize) { + return None; + } + b.set_blocked(p.x as usize, p.y as usize, true); + } if let PathField::Underground { pos, dir, len } = path[start_index] { for l in 1..len { @@ -231,6 +235,7 @@ impl ConflictAvoidance { } } + let start_pos_offset = start_pos - offset; b.add_path((start_pos_offset, start_dir), (end_pos - offset, end_dir)); mapping.push((i, start_index, end_index)); @@ -255,6 +260,7 @@ impl ConflictAvoidance { while b.next_finish_state() { // println!("{}", b); + // b.print(); let c = b.cost(); if c < min_cost { min_cost = c; @@ -363,6 +369,7 @@ impl ConflictAvoidance { let yrange = c.min.y as usize..=c.max.y as usize; let offset = Position::new(*xrange.start() as i32 - 1, *yrange.start() as i32 - 1); if let Some(r) = result { + // println!("Here"); for BruteForceEntry { path_id, start, @@ -454,6 +461,32 @@ impl ConflictAvoidance { } } + for path in &self.belts { + for p in &path[1..] { + match p { + PathField::Belt { pos, dir: _ } => { + if conflicts.get(pos.x as usize, pos.y as usize) == &true { + return false; + } else { + conflicts.set(pos.x as usize, pos.y as usize, true); + } + } + PathField::Underground { pos, dir, len } => { + if conflicts.get(pos.x as usize, pos.y as usize) == &true { + return false; + } else { + conflicts.set(pos.x as usize, pos.y as usize, true); + } + let end = pos.in_direction(dir, *len as PositionType); + if conflicts.get(end.x as usize, end.y as usize) == &true { + return false; + } else { + conflicts.set(end.x as usize, end.y as usize, true); + } + } + } + } + } true } diff --git a/src/belt_finding/mod.rs b/src/belt_finding/mod.rs index c8e7b9a..78d3629 100644 --- a/src/belt_finding/mod.rs +++ b/src/belt_finding/mod.rs @@ -215,7 +215,7 @@ impl<'a> WheightedGraph for MapInternal<'a> { count += 1; if count == num { let penalty = penalty + self.map.get(n.x as usize, n.y as usize).weight; - return Some(((n, node.1), 17.5 + penalty)); + return Some(((n, node.1), 35.0 + penalty)); } } } diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 5dfc31d..85a14f0 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -29,7 +29,7 @@ impl<'a> GeneticAlgorithm<'a> { } } - population.sort_by_cached_key(|p| p.score()); + population.sort_by_key(|p| p.score()); println!("Best score: {}", population[0].score()); population[0].print_visualization(); @@ -56,14 +56,16 @@ impl<'a> GeneticAlgorithm<'a> { 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)) { + if let Some(p) = + PathLayout::new(self.population[j % self.population_keep].layout.mutate(rng)) + { self.population[i] = p; break; } } } - self.population.sort_by_cached_key(|p| p.score()); + self.population.sort_by_key(|p| p.score()); println!("Best score: {}", self.population[0].score()); self.population[0].print_visualization(); } @@ -122,20 +124,26 @@ pub struct PathLayout<'a> { impl<'a> PathLayout<'a> { pub fn new(layout: Layout<'a>) -> Option> { - layout.print_visualization(); let mut p = crate::belt_finding::Problem::from_layout(&layout); + // let start = std::time::Instant::now(); + if !p.find_path() { return None; } - p.print(); + + // println!("Find Path: {:.2}", start.elapsed().as_secs_f32()); let mut c = ConflictAvoidance::new(p); + // let start = std::time::Instant::now(); + if !c.remove_all_conflicts() { return None; } + // println!("Conflict avoidance: {:.2}", start.elapsed().as_secs_f32()); + let paths = c.get_paths().to_vec(); let score = paths @@ -302,13 +310,13 @@ impl Layout<'_> { let r: &[(&dyn Fn(&mut Layout, &mut R) -> bool, _)] = &[ (&Self::mutate_replace::, 30), (&Self::mutate_flip::, 50), - (&Self::mutate_jiggle::, 80), + (&Self::mutate_jiggle::, 160), ]; loop { let p = r.choose_weighted(rng, |i| i.1).unwrap(); - if p.0(&mut s, rng) && rng.gen_bool(0.4) { + if p.0(&mut s, rng) && rng.gen_bool(0.2) { break; } } diff --git a/src/priority_queue/mod.rs b/src/priority_queue/mod.rs index 5d2b03a..9fcc655 100644 --- a/src/priority_queue/mod.rs +++ b/src/priority_queue/mod.rs @@ -19,7 +19,13 @@ where #[derive(Debug)] pub struct BinaryHeap { nextfree: usize, - data: Vec<(usize, Item)>, + data: Vec>, +} + +#[derive(Debug)] +struct BinaryHeapEntry { + id: usize, + item: Item, } impl BinaryHeap @@ -31,16 +37,16 @@ where let right = 2 * index + 2; if right < self.data.len() { - let smaller = if self.data[left] < self.data[right] { + let smaller = if self.data[left].item < self.data[right].item { left } else { right }; - if self.data[index] > self.data[smaller] { + if self.data[index].item > self.data[smaller].item { self.data.swap(index, smaller); self.downheap(smaller); } - } else if left < self.data.len() && self.data[index] > self.data[left] { + } else if left < self.data.len() && self.data[index].item > self.data[left].item { self.data.swap(index, left); self.downheap(left); } @@ -49,7 +55,7 @@ where fn upheap(&mut self, index: usize) { if index > 0 { let parent = (index - 1) / 2; - if self.data[parent].1 > self.data[index].1 { + if self.data[parent].item > self.data[index].item { self.data.swap(parent, index); self.upheap(parent); } @@ -58,7 +64,7 @@ where fn search(&self, id: usize) -> Option { for (i, d) in self.data.iter().enumerate() { - if d.0 == id { + if d.id == id { return Some(i); } } @@ -73,7 +79,10 @@ where type Handle = usize; fn insert(&mut self, item: Item) -> Self::Handle { - self.data.push((self.nextfree, item.clone())); + self.data.push(BinaryHeapEntry { + id: self.nextfree, + item: item.clone(), + }); self.upheap(self.data.len() - 1); self.nextfree += 1; self.nextfree - 1 @@ -85,13 +94,13 @@ where } else { let d = self.data.swap_remove(0); self.downheap(0); - Some(d.1) + Some(d.item) } } fn decrease_key(&mut self, handle: &Self::Handle, f: impl Fn(&mut Item)) { if let Some(index) = self.search(*handle) { - f(&mut self.data[index].1); + f(&mut self.data[index].item); self.upheap(index); } }