Bug fixes
This commit is contained in:
parent
a11b39cf9f
commit
f20a1841c9
6 changed files with 75 additions and 25 deletions
|
|
@ -44,7 +44,7 @@ blocks:
|
||||||
output:
|
output:
|
||||||
- offset:
|
- offset:
|
||||||
x: 0
|
x: 0
|
||||||
y: 2
|
y: 3
|
||||||
dir: Left
|
dir: Left
|
||||||
connections:
|
connections:
|
||||||
- startblock: 1
|
- startblock: 1
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ impl PathField {
|
||||||
|
|
||||||
pub fn cost(&self) -> usize {
|
pub fn cost(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
PathField::Belt { pos: _, dir: _ } => 300,
|
PathField::Belt { pos: _, dir: _ } => 150,
|
||||||
PathField::Underground {
|
PathField::Underground {
|
||||||
pos: _,
|
pos: _,
|
||||||
dir: _,
|
dir: _,
|
||||||
|
|
|
||||||
|
|
@ -213,12 +213,16 @@ impl ConflictAvoidance {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let start_pos_offset = start_pos - offset;
|
if xrange.contains(&(start_pos.x as usize))
|
||||||
b.set_blocked(
|
&& yrange.contains(&(start_pos.y as usize))
|
||||||
start_pos_offset.x as usize,
|
{
|
||||||
start_pos_offset.y as usize,
|
let p = start_pos - offset;
|
||||||
true,
|
// 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] {
|
if let PathField::Underground { pos, dir, len } = path[start_index] {
|
||||||
for l in 1..len {
|
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));
|
b.add_path((start_pos_offset, start_dir), (end_pos - offset, end_dir));
|
||||||
|
|
||||||
mapping.push((i, start_index, end_index));
|
mapping.push((i, start_index, end_index));
|
||||||
|
|
@ -255,6 +260,7 @@ impl ConflictAvoidance {
|
||||||
|
|
||||||
while b.next_finish_state() {
|
while b.next_finish_state() {
|
||||||
// println!("{}", b);
|
// println!("{}", b);
|
||||||
|
// b.print();
|
||||||
let c = b.cost();
|
let c = b.cost();
|
||||||
if c < min_cost {
|
if c < min_cost {
|
||||||
min_cost = c;
|
min_cost = c;
|
||||||
|
|
@ -363,6 +369,7 @@ impl ConflictAvoidance {
|
||||||
let yrange = c.min.y as usize..=c.max.y as usize;
|
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);
|
let offset = Position::new(*xrange.start() as i32 - 1, *yrange.start() as i32 - 1);
|
||||||
if let Some(r) = result {
|
if let Some(r) = result {
|
||||||
|
// println!("Here");
|
||||||
for BruteForceEntry {
|
for BruteForceEntry {
|
||||||
path_id,
|
path_id,
|
||||||
start,
|
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
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -215,7 +215,7 @@ impl<'a> WheightedGraph for MapInternal<'a> {
|
||||||
count += 1;
|
count += 1;
|
||||||
if count == num {
|
if count == num {
|
||||||
let penalty = penalty + self.map.get(n.x as usize, n.y as usize).weight;
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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());
|
println!("Best score: {}", population[0].score());
|
||||||
population[0].print_visualization();
|
population[0].print_visualization();
|
||||||
|
|
@ -56,14 +56,16 @@ impl<'a> GeneticAlgorithm<'a> {
|
||||||
for i in (self.population_keep + self.population_new)..self.population_size {
|
for i in (self.population_keep + self.population_new)..self.population_size {
|
||||||
let j = i - (self.population_keep + self.population_new);
|
let j = i - (self.population_keep + self.population_new);
|
||||||
loop {
|
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;
|
self.population[i] = p;
|
||||||
break;
|
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());
|
println!("Best score: {}", self.population[0].score());
|
||||||
self.population[0].print_visualization();
|
self.population[0].print_visualization();
|
||||||
}
|
}
|
||||||
|
|
@ -122,20 +124,26 @@ pub struct PathLayout<'a> {
|
||||||
|
|
||||||
impl<'a> PathLayout<'a> {
|
impl<'a> PathLayout<'a> {
|
||||||
pub fn new(layout: Layout<'a>) -> Option<PathLayout<'a>> {
|
pub fn new(layout: Layout<'a>) -> Option<PathLayout<'a>> {
|
||||||
layout.print_visualization();
|
|
||||||
let mut p = crate::belt_finding::Problem::from_layout(&layout);
|
let mut p = crate::belt_finding::Problem::from_layout(&layout);
|
||||||
|
|
||||||
|
// let start = std::time::Instant::now();
|
||||||
|
|
||||||
if !p.find_path() {
|
if !p.find_path() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
p.print();
|
|
||||||
|
// println!("Find Path: {:.2}", start.elapsed().as_secs_f32());
|
||||||
|
|
||||||
let mut c = ConflictAvoidance::new(p);
|
let mut c = ConflictAvoidance::new(p);
|
||||||
|
|
||||||
|
// let start = std::time::Instant::now();
|
||||||
|
|
||||||
if !c.remove_all_conflicts() {
|
if !c.remove_all_conflicts() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// println!("Conflict avoidance: {:.2}", start.elapsed().as_secs_f32());
|
||||||
|
|
||||||
let paths = c.get_paths().to_vec();
|
let paths = c.get_paths().to_vec();
|
||||||
|
|
||||||
let score = paths
|
let score = paths
|
||||||
|
|
@ -302,13 +310,13 @@ impl Layout<'_> {
|
||||||
let r: &[(&dyn Fn(&mut Layout, &mut R) -> bool, _)] = &[
|
let r: &[(&dyn Fn(&mut Layout, &mut R) -> bool, _)] = &[
|
||||||
(&Self::mutate_replace::<R>, 30),
|
(&Self::mutate_replace::<R>, 30),
|
||||||
(&Self::mutate_flip::<R>, 50),
|
(&Self::mutate_flip::<R>, 50),
|
||||||
(&Self::mutate_jiggle::<R>, 80),
|
(&Self::mutate_jiggle::<R>, 160),
|
||||||
];
|
];
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let p = r.choose_weighted(rng, |i| i.1).unwrap();
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,13 @@ where
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BinaryHeap<Item> {
|
pub struct BinaryHeap<Item> {
|
||||||
nextfree: usize,
|
nextfree: usize,
|
||||||
data: Vec<(usize, Item)>,
|
data: Vec<BinaryHeapEntry<Item>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct BinaryHeapEntry<Item> {
|
||||||
|
id: usize,
|
||||||
|
item: Item,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Item> BinaryHeap<Item>
|
impl<Item> BinaryHeap<Item>
|
||||||
|
|
@ -31,16 +37,16 @@ where
|
||||||
let right = 2 * index + 2;
|
let right = 2 * index + 2;
|
||||||
|
|
||||||
if right < self.data.len() {
|
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
|
left
|
||||||
} else {
|
} else {
|
||||||
right
|
right
|
||||||
};
|
};
|
||||||
if self.data[index] > self.data[smaller] {
|
if self.data[index].item > self.data[smaller].item {
|
||||||
self.data.swap(index, smaller);
|
self.data.swap(index, smaller);
|
||||||
self.downheap(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.data.swap(index, left);
|
||||||
self.downheap(left);
|
self.downheap(left);
|
||||||
}
|
}
|
||||||
|
|
@ -49,7 +55,7 @@ where
|
||||||
fn upheap(&mut self, index: usize) {
|
fn upheap(&mut self, index: usize) {
|
||||||
if index > 0 {
|
if index > 0 {
|
||||||
let parent = (index - 1) / 2;
|
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.data.swap(parent, index);
|
||||||
self.upheap(parent);
|
self.upheap(parent);
|
||||||
}
|
}
|
||||||
|
|
@ -58,7 +64,7 @@ where
|
||||||
|
|
||||||
fn search(&self, id: usize) -> Option<usize> {
|
fn search(&self, id: usize) -> Option<usize> {
|
||||||
for (i, d) in self.data.iter().enumerate() {
|
for (i, d) in self.data.iter().enumerate() {
|
||||||
if d.0 == id {
|
if d.id == id {
|
||||||
return Some(i);
|
return Some(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -73,7 +79,10 @@ where
|
||||||
type Handle = usize;
|
type Handle = usize;
|
||||||
|
|
||||||
fn insert(&mut self, item: Item) -> Self::Handle {
|
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.upheap(self.data.len() - 1);
|
||||||
self.nextfree += 1;
|
self.nextfree += 1;
|
||||||
self.nextfree - 1
|
self.nextfree - 1
|
||||||
|
|
@ -85,13 +94,13 @@ where
|
||||||
} else {
|
} else {
|
||||||
let d = self.data.swap_remove(0);
|
let d = self.data.swap_remove(0);
|
||||||
self.downheap(0);
|
self.downheap(0);
|
||||||
Some(d.1)
|
Some(d.item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decrease_key(&mut self, handle: &Self::Handle, f: impl Fn(&mut Item)) {
|
fn decrease_key(&mut self, handle: &Self::Handle, f: impl Fn(&mut Item)) {
|
||||||
if let Some(index) = self.search(*handle) {
|
if let Some(index) = self.search(*handle) {
|
||||||
f(&mut self.data[index].1);
|
f(&mut self.data[index].item);
|
||||||
self.upheap(index);
|
self.upheap(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue