Add mutation for layouts.

This commit is contained in:
hal8174 2024-08-26 16:58:31 +02:00
parent 0c1345053b
commit be1d26ebd0
3 changed files with 132 additions and 11 deletions

View file

@ -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();

View file

@ -1,6 +1,6 @@
size: size:
x: 15 x: 10
y: 15 y: 10
blocks: blocks:
- size: - size:
x: 3 x: 3

View file

@ -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),