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();
|
||||
l.print_visualization();
|
||||
|
||||
let mut p = Problem::from_layout(&l);
|
||||
p.print();
|
||||
p.find_path();
|
||||
p.print();
|
||||
let mut c = ConflictAvoidance::new(p);
|
||||
let m = l.mutate(&mut rng);
|
||||
m.print_visualization();
|
||||
|
||||
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);
|
||||
|
||||
// l.print_visualization();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
size:
|
||||
x: 15
|
||||
y: 15
|
||||
x: 10
|
||||
y: 10
|
||||
blocks:
|
||||
- size:
|
||||
x: 3
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::common::visualize::{Color, Symbol, Visualization, Visualize};
|
||||
use crate::prelude::*;
|
||||
use rand::Rng;
|
||||
use rand::{seq::SliceRandom, Rng};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
|
|
@ -143,11 +143,115 @@ impl Layout<'_> {
|
|||
|
||||
/// Mutate existing layout, creating a valid layout
|
||||
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
|
||||
}
|
||||
|
||||
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(
|
||||
block1: (&Block, Position, Direction),
|
||||
block2: (&Block, Position, Direction),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue