Add mutation for layouts.
This commit is contained in:
parent
0c1345053b
commit
be1d26ebd0
3 changed files with 132 additions and 11 deletions
|
|
@ -27,15 +27,32 @@ fn main() {
|
||||||
// let s = l.score();
|
// let s = l.score();
|
||||||
l.print_visualization();
|
l.print_visualization();
|
||||||
|
|
||||||
let mut p = Problem::from_layout(&l);
|
let m = l.mutate(&mut rng);
|
||||||
p.print();
|
m.print_visualization();
|
||||||
p.find_path();
|
|
||||||
p.print();
|
|
||||||
let mut c = ConflictAvoidance::new(p);
|
|
||||||
|
|
||||||
c.remove_all_conflicts();
|
let m = m.mutate(&mut rng);
|
||||||
|
m.print_visualization();
|
||||||
|
let m = m.mutate(&mut rng);
|
||||||
|
m.print_visualization();
|
||||||
|
let m = m.mutate(&mut rng);
|
||||||
|
m.print_visualization();
|
||||||
|
let m = m.mutate(&mut rng);
|
||||||
|
m.print_visualization();
|
||||||
|
let m = m.mutate(&mut rng);
|
||||||
|
m.print_visualization();
|
||||||
|
let m = m.mutate(&mut rng);
|
||||||
|
m.print_visualization();
|
||||||
|
let m = m.mutate(&mut rng);
|
||||||
|
m.print_visualization();
|
||||||
|
// let mut p = Problem::from_layout(&l);
|
||||||
|
// p.print();
|
||||||
|
// p.find_path();
|
||||||
|
// p.print();
|
||||||
|
// let mut c = ConflictAvoidance::new(p);
|
||||||
|
|
||||||
c.print();
|
// c.remove_all_conflicts();
|
||||||
|
|
||||||
|
// c.print();
|
||||||
// println!("Seed: {i}, Score {}", s);
|
// println!("Seed: {i}, Score {}", s);
|
||||||
|
|
||||||
// l.print_visualization();
|
// l.print_visualization();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
size:
|
size:
|
||||||
x: 15
|
x: 10
|
||||||
y: 15
|
y: 10
|
||||||
blocks:
|
blocks:
|
||||||
- size:
|
- size:
|
||||||
x: 3
|
x: 3
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::common::visualize::{Color, Symbol, Visualization, Visualize};
|
use crate::common::visualize::{Color, Symbol, Visualization, Visualize};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use rand::Rng;
|
use rand::{seq::SliceRandom, Rng};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
|
@ -143,11 +143,115 @@ impl Layout<'_> {
|
||||||
|
|
||||||
/// Mutate existing layout, creating a valid layout
|
/// Mutate existing layout, creating a valid layout
|
||||||
pub fn mutate<R: Rng + ?Sized>(&self, rng: &mut R) -> Self {
|
pub fn mutate<R: Rng + ?Sized>(&self, rng: &mut R) -> Self {
|
||||||
let s = self.clone();
|
let mut s = self.clone();
|
||||||
|
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
let r: &[(&dyn Fn(&mut Layout, &mut R) -> bool, _)] = &[
|
||||||
|
(&Self::mutate_replace::<R>, 30),
|
||||||
|
(&Self::mutate_flip::<R>, 50),
|
||||||
|
(&Self::mutate_jiggle::<R>, 80),
|
||||||
|
];
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let p = r.choose_weighted(rng, |i| i.1).unwrap();
|
||||||
|
|
||||||
|
if p.0(&mut s, rng) && rng.gen_bool(0.4) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mutate_replace<R: Rng + ?Sized>(layout: &mut Layout, rng: &mut R) -> bool {
|
||||||
|
let i = rng.gen_range(0..layout.blocks.len());
|
||||||
|
|
||||||
|
let dir = rng.gen::<Direction>();
|
||||||
|
|
||||||
|
let b = &layout.problem.blocks[i];
|
||||||
|
|
||||||
|
let pos = match dir {
|
||||||
|
Direction::Up => Position::new(
|
||||||
|
rng.gen_range(0..=(layout.problem.size.x - b.size.x)),
|
||||||
|
rng.gen_range(0..=(layout.problem.size.y - b.size.y)),
|
||||||
|
),
|
||||||
|
Direction::Right => Position::new(
|
||||||
|
rng.gen_range((b.size.y - 1)..layout.problem.size.x),
|
||||||
|
rng.gen_range(0..=(layout.problem.size.y - b.size.x)),
|
||||||
|
),
|
||||||
|
Direction::Down => Position::new(
|
||||||
|
rng.gen_range((b.size.x - 1)..layout.problem.size.x),
|
||||||
|
rng.gen_range((b.size.y - 1)..layout.problem.size.y),
|
||||||
|
),
|
||||||
|
Direction::Left => Position::new(
|
||||||
|
rng.gen_range(0..=(layout.problem.size.x - b.size.y)),
|
||||||
|
rng.gen_range((b.size.x - 1)..layout.problem.size.y),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
if layout.blocks.iter().enumerate().all(|(j, (p, d))| {
|
||||||
|
j == i || !Self::collision((&layout.problem.blocks[j], *p, *d), (b, pos, dir))
|
||||||
|
}) {
|
||||||
|
layout.blocks[i] = (pos, dir);
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mutate_flip<R: Rng + ?Sized>(layout: &mut Layout, rng: &mut R) -> bool {
|
||||||
|
let i = rng.gen_range(0..layout.blocks.len());
|
||||||
|
let b = &mut layout.blocks[i];
|
||||||
|
let block = &layout.problem.blocks[i];
|
||||||
|
|
||||||
|
b.0 = match &b.1 {
|
||||||
|
Direction::Up => b.0 + block.size - Position::new(1, 1),
|
||||||
|
Direction::Right => b.0 + Position::new(1 - block.size.y, block.size.x - 1),
|
||||||
|
Direction::Down => b.0 - block.size + Position::new(1, 1),
|
||||||
|
Direction::Left => b.0 + Position::new(block.size.y - 1, 1 - block.size.x),
|
||||||
|
};
|
||||||
|
b.1 = b.1.reverse();
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mutate_jiggle<R: Rng + ?Sized>(layout: &mut Layout, rng: &mut R) -> bool {
|
||||||
|
let i = rng.gen_range(0..layout.blocks.len());
|
||||||
|
let dir = rng.gen::<Direction>();
|
||||||
|
// let step = [(1, 10), (2, 5), (3, 5)]
|
||||||
|
// .choose_weighted(rng, |i| i.1)
|
||||||
|
// .unwrap()
|
||||||
|
// .0;
|
||||||
|
let step = 1;
|
||||||
|
|
||||||
|
let b = &layout.problem.blocks[i];
|
||||||
|
|
||||||
|
let new_pos = layout.blocks[i].0.in_direction(&dir, step);
|
||||||
|
|
||||||
|
let (npos, nsize) = Self::normalize_pos((b, new_pos, layout.blocks[i].1));
|
||||||
|
|
||||||
|
if npos.x < 0
|
||||||
|
|| npos.y < 0
|
||||||
|
|| npos.x + nsize.x > layout.problem.size.x
|
||||||
|
|| npos.y + nsize.y > layout.problem.size.y
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if layout.blocks.iter().enumerate().all(|(j, (p, d))| {
|
||||||
|
j == i
|
||||||
|
|| !Self::collision(
|
||||||
|
(&layout.problem.blocks[j], *p, *d),
|
||||||
|
(b, new_pos, layout.blocks[i].1),
|
||||||
|
)
|
||||||
|
}) {
|
||||||
|
layout.blocks[i].0 = new_pos;
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn collision(
|
fn collision(
|
||||||
block1: (&Block, Position, Direction),
|
block1: (&Block, Position, Direction),
|
||||||
block2: (&Block, Position, Direction),
|
block2: (&Block, Position, Direction),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue