vectorize mutation

This commit is contained in:
mos 2025-01-11 13:51:03 +01:00
parent 2e1f524476
commit 89b3e6e983
3 changed files with 41 additions and 30 deletions

4
Cargo.lock generated
View File

@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 4
[[package]] [[package]]
name = "anstream" name = "anstream"
@ -53,7 +53,7 @@ dependencies = [
[[package]] [[package]]
name = "bano" name = "bano"
version = "0.1.0" version = "0.2.0"
dependencies = [ dependencies = [
"clap", "clap",
"rand", "rand",

View File

@ -1,9 +1,12 @@
[package] [package]
name = "bano" name = "bano"
version = "0.1.0" version = "0.2.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
clap = { version = "4.5.19", features = ["derive"] } clap = { version = "4.5.19", features = ["derive"] }
rand = "0.8.5" rand = "0.8.5"
rayon = "1.10.0" rayon = "1.10.0"
[features]
simd = []

View File

@ -1,5 +1,8 @@
#![cfg_attr(feature = "simd", feature(portable_simd))]
use rayon::prelude::*; use rayon::prelude::*;
use std::ops::{Add, Index, IndexMut, Sub}; use std::ops::{Add, Index, IndexMut, Sub};
#[cfg(feature = "simd")]
use std::simd::{u32x8, Simd};
pub enum ReadError { pub enum ReadError {
BadSymbol, BadSymbol,
@ -15,14 +18,6 @@ pub enum Error {
type Result<T> = std::result::Result<T, Error>; type Result<T> = std::result::Result<T, Error>;
#[derive(PartialEq, Copy, Clone)]
enum Direction {
U,
D,
L,
R,
}
#[derive(PartialEq, Copy, Clone)] #[derive(PartialEq, Copy, Clone)]
enum Cell { enum Cell {
Wall, Wall,
@ -249,13 +244,8 @@ impl State {
Ok((false, false)) Ok((false, false))
} }
fn move_dir(&mut self, dir: Direction) -> Result<(bool, bool)> { fn move_dir(&mut self, dir: u32) -> Result<(bool, bool)> {
match dir { self.move_pos(Self::DIR_POS[dir as usize])
Direction::U => self.move_pos(Self::DIR_POS[0]),
Direction::D => self.move_pos(Self::DIR_POS[1]),
Direction::L => self.move_pos(Self::DIR_POS[2]),
Direction::R => self.move_pos(Self::DIR_POS[3]),
}
} }
fn test_box(&self, pos: Pos, bt: bool) -> bool { fn test_box(&self, pos: Pos, bt: bool) -> bool {
@ -337,7 +327,7 @@ impl State {
#[derive(Clone)] #[derive(Clone)]
struct Agent { struct Agent {
state: State, state: State,
dna: Vec<Direction>, dna: Vec<u32>,
score: f32, score: f32,
dir: usize, dir: usize,
goal: Solution, goal: Solution,
@ -357,14 +347,14 @@ impl Agent {
const INACTIVE_PENALTY: f32 = 0.0010; const INACTIVE_PENALTY: f32 = 0.0010;
const BOX_DIFF: f32 = 1024.0; const BOX_DIFF: f32 = 1024.0;
const DIR_TABLE: &'static [Direction] = const DIR_TABLE: &'static [u32] = &[0, 1, 2, 3];
&[Direction::U, Direction::D, Direction::L, Direction::R]; const DIR_STR: &[&str] = &["U", "D", "L", "R"];
fn chromo() -> Direction { fn chromo() -> u32 {
Self::DIR_TABLE[rnd!(Self::DIR_TABLE.len())] Self::DIR_TABLE[rnd!(Self::DIR_TABLE.len())]
} }
fn with_dna(state: State, dna: Vec<Direction>) -> Self { fn with_dna(state: State, dna: Vec<u32>) -> Self {
Self { Self {
state, state,
dna, dna,
@ -375,7 +365,7 @@ impl Agent {
} }
fn new(state: State, size: usize) -> Self { fn new(state: State, size: usize) -> Self {
let dna: Vec<Direction> = (0..size).map(|_| Self::chromo()).collect(); let dna: Vec<u32> = (0..size).map(|_| Self::chromo()).collect();
Self::with_dna(state, dna) Self::with_dna(state, dna)
} }
@ -386,6 +376,29 @@ impl Agent {
self.dna[..ratio].copy_from_slice(&seed.dna[..ratio]); self.dna[..ratio].copy_from_slice(&seed.dna[..ratio]);
} }
#[cfg(feature = "simd")]
fn mutate(&mut self, max: usize) {
let len = self.dna.len();
let (ni, nd) = (rnd!(max) + 8, rnd!(len));
for x in 0..ni / 8 {
let d = u32x8::from_array([Agent::chromo(); 8]);
let si = Simd::from_array([
nd + x,
nd + x + 1,
nd + x + 2,
nd + x + 3,
nd + x + 4,
nd + x + 5,
nd + x + 6,
nd + x + 7,
]);
d.scatter(&mut self.dna, si);
}
}
#[cfg(not(feature = "simd"))]
fn mutate(&mut self, max: usize) { fn mutate(&mut self, max: usize) {
let len = self.dna.len(); let len = self.dna.len();
let (ni, nd) = (rnd!(max), rnd!(len)); let (ni, nd) = (rnd!(max), rnd!(len));
@ -443,12 +456,7 @@ impl Agent {
fn solution(&self) -> String { fn solution(&self) -> String {
(0..self.dir) (0..self.dir)
.map(|i| match self.dna[i] { .map(|i| Self::DIR_STR[self.dna[i] as usize])
Direction::U => "U",
Direction::D => "D",
Direction::L => "L",
Direction::R => "R",
})
.collect() .collect()
} }
} }