diff --git a/Cargo.lock b/Cargo.lock index 5586768..2ac76dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "anstream" @@ -53,7 +53,7 @@ dependencies = [ [[package]] name = "bano" -version = "0.1.0" +version = "0.2.0" dependencies = [ "clap", "rand", diff --git a/Cargo.toml b/Cargo.toml index 0aee6f5..977aec4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,12 @@ [package] name = "bano" -version = "0.1.0" +version = "0.2.0" edition = "2021" [dependencies] clap = { version = "4.5.19", features = ["derive"] } rand = "0.8.5" rayon = "1.10.0" + +[features] +simd = [] diff --git a/src/lib.rs b/src/lib.rs index a654508..db3e89a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,8 @@ +#![cfg_attr(feature = "simd", feature(portable_simd))] use rayon::prelude::*; use std::ops::{Add, Index, IndexMut, Sub}; +#[cfg(feature = "simd")] +use std::simd::{u32x8, Simd}; pub enum ReadError { BadSymbol, @@ -15,14 +18,6 @@ pub enum Error { type Result = std::result::Result; -#[derive(PartialEq, Copy, Clone)] -enum Direction { - U, - D, - L, - R, -} - #[derive(PartialEq, Copy, Clone)] enum Cell { Wall, @@ -249,13 +244,8 @@ impl State { Ok((false, false)) } - fn move_dir(&mut self, dir: Direction) -> Result<(bool, bool)> { - match dir { - 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 move_dir(&mut self, dir: u32) -> Result<(bool, bool)> { + self.move_pos(Self::DIR_POS[dir as usize]) } fn test_box(&self, pos: Pos, bt: bool) -> bool { @@ -337,7 +327,7 @@ impl State { #[derive(Clone)] struct Agent { state: State, - dna: Vec, + dna: Vec, score: f32, dir: usize, goal: Solution, @@ -357,14 +347,14 @@ impl Agent { const INACTIVE_PENALTY: f32 = 0.0010; const BOX_DIFF: f32 = 1024.0; - const DIR_TABLE: &'static [Direction] = - &[Direction::U, Direction::D, Direction::L, Direction::R]; + const DIR_TABLE: &'static [u32] = &[0, 1, 2, 3]; + const DIR_STR: &[&str] = &["U", "D", "L", "R"]; - fn chromo() -> Direction { + fn chromo() -> u32 { Self::DIR_TABLE[rnd!(Self::DIR_TABLE.len())] } - fn with_dna(state: State, dna: Vec) -> Self { + fn with_dna(state: State, dna: Vec) -> Self { Self { state, dna, @@ -375,7 +365,7 @@ impl Agent { } fn new(state: State, size: usize) -> Self { - let dna: Vec = (0..size).map(|_| Self::chromo()).collect(); + let dna: Vec = (0..size).map(|_| Self::chromo()).collect(); Self::with_dna(state, dna) } @@ -386,6 +376,29 @@ impl Agent { 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) { let len = self.dna.len(); let (ni, nd) = (rnd!(max), rnd!(len)); @@ -443,12 +456,7 @@ impl Agent { fn solution(&self) -> String { (0..self.dir) - .map(|i| match self.dna[i] { - Direction::U => "U", - Direction::D => "D", - Direction::L => "L", - Direction::R => "R", - }) + .map(|i| Self::DIR_STR[self.dna[i] as usize]) .collect() } }