Add DiagonalWalkera and fix 3D KD grid

This commit is contained in:
Joshua Coles 2023-03-10 15:28:42 +00:00
parent 73bb0f8ed1
commit 10c7450c8a
9 changed files with 90 additions and 100 deletions

1
Cargo.lock generated
View File

@ -2837,6 +2837,7 @@ dependencies = [
name = "rust-codebase"
version = "0.1.0"
dependencies = [
"anyhow",
"bevy",
"cbindgen",
"clap 4.1.8",

View File

@ -42,6 +42,7 @@ serde_json = "1.0.93"
kd-tree = { version = "0.5.1", features = ["nalgebra"] }
nalgebra = "0.32.2"
kiddo = "0.2.5"
anyhow = "1.0.69"
[build-dependencies]
cbindgen = "0.24.3"

View File

@ -38,6 +38,7 @@ pub enum PCM {
Initial(InitialCli),
StickProbability(StickProbabilityCli),
Grid3KD(StickProbabilityCli),
Grid3KDTsang(StickProbabilityCli),
Grid3(StickProbabilityCli),
Hex(StickProbabilityCli),
Balls(BallsCli),

View File

@ -39,6 +39,6 @@ fn write_csv_positions<R: Rng, P: Position, S: Storage<P>, W: Walker<P>, Sp: Spa
fn write_json_full_data<R: Rng, P: Position, S: Storage<P>, W: Walker<P>, Sp: Spawner<P>, St: Sticker<P, S>>(sys: &DLASystem<R, P, S, W, Sp, St>, output_path: &Path) {
let file = File::create(output_path).expect("Failed to open file");
serde_json::to_writer(file, &sys.history)
serde_json::to_writer_pretty(file, &sys.history)
.expect("Failed to write json");
}

View File

@ -2,80 +2,3 @@
pub extern "C" fn dla_rust_disabled() -> bool {
true
}
// #![feature(array_zip)]
//
// use system::Storage;
// use crate::system::spaces::square_grid::Grid2D;
// use crate::system::spaces::VectorStorage;
//
// mod system;
//
// #[derive(Eq, PartialEq, Debug)]
// #[repr(C)]
// pub struct CPosition(i32, i32);
//
// pub struct CStorage(VectorStorage);
//
// #[no_mangle]
// pub extern "C" fn storage_new(grid_size: u32) -> &'static mut CStorage {
// let mut pntr = Box::new(CStorage(VectorStorage::new(grid_size)));
// Box::leak(pntr)
// }
//
// #[no_mangle]
// pub extern "C" fn storage_at(storage: &CStorage, i: i32, j: i32) -> bool {
// storage.0.at(&Grid2D { x: i, y: j })
// }
//
// #[no_mangle]
// pub extern "C" fn storage_deposit(storage: &mut CStorage, i: i32, j: i32, val: u8) {
// storage.0.inner.(&Grid2D { x: i, y: j }, val == 1);
// }
//
// #[no_mangle]
// pub extern "C" fn walk(d: u32, i: i32, j: i32) -> CPosition {
// return test::b(d, i, j);
// }
//
// // mod test {
// // use num_integer::Integer;
// // use crate::CPosition;
// // use crate::system::grid::Grid2D;
// //
// // pub(crate) fn a(d: u32, i: i32, j: i32) -> CPosition {
// // match d {
// // 0 => CPosition(i + 1, j),
// // 1 => CPosition(i - 1, j),
// // 2 => CPosition(i, j + 1),
// // 3 => CPosition(i, j - 1),
// // _ => panic!("Ahh"),
// // }
// // }
// //
// // pub(crate) fn b(d: u32, i: i32, j: i32) -> CPosition {
// // let (dim, sign) = d.div_rem(&2);
// // let sign = if sign == 0 { 1 } else { -1 };
// // // HACK: Our conventin and the MVA are different, since we are trying to strangle fig this, quick hack.
// // let offset = Grid2D::in_direction(dim, sign);
// // let next = Grid2D { x: i, y: j } + offset;
// //
// // CPosition(next.x, next.y)
// // }
// //
// // #[test]
// // fn test() {
// // let d = [0, 1, 2, 3];
// // d.iter()
// // .map(|d| d.div_rem(&2))
// // .for_each(|p| println!("{p:?}"));
// // }
// //
// // #[test]
// // fn alignment() {
// // let d = [0, 1, 2, 3];
// // d.iter()
// // .map(|d| (a(*d, 0, 0), b(*d, 0, 0)))
// // .for_each(|p| assert_eq!(p.0, p.1));
// // }
// // }

View File

@ -2,7 +2,6 @@
#![feature(generic_const_exprs)]
#![feature(let_chains)]
use std::ops::Deref;
use clap::Parser;
use rand::prelude::*;
use crate::cli::{drive_system};
@ -12,12 +11,12 @@ use crate::surface_probability_measure::{LoggerSticker, ReadOnlyVectorStorage};
use crate::system::model::DLASystem;
use crate::system::spaces::continuous::{ContinuousSticker, ContinuousStorage, ContinuousWalker};
use crate::system::spaces::hexagonal::HexPosition;
use crate::system::spaces::kd_grid::{KDGrid, KDGrid2Sticker};
use crate::system::spaces::kd_grid::{KDSpace};
use crate::system::spaces::square_grid::{Grid2D, Grid3D};
use crate::system::spaces::VectorStorage;
use crate::system::spawner::UniformSpawner;
use crate::system::sticker::{ProbabilisticSticking, SimpleSticking};
use crate::system::walker::LocalRandomWalker;
use crate::system::walker::{DiagonalRandomWalker, LocalRandomWalker};
mod system;
mod surface_probability_measure;
@ -49,7 +48,7 @@ fn main() {
VectorStorage::new(grid_size, 2),
LocalRandomWalker,
UniformSpawner,
ProbabilisticSticking { stick_probability },
ProbabilisticSticking::new(stick_probability).unwrap(),
cli.max_particles,
);
@ -58,12 +57,26 @@ fn main() {
}
PCM::Grid3KD(StickProbabilityCli { grid_size, stick_probability }) => {
let mut sys = DLASystem::<_, Grid2D, _, _, _, _>::new(
let mut sys = DLASystem::<_, Grid3D, _, _, _, _>::new(
SmallRng::seed_from_u64(cli.seed),
KDGrid { inner: kiddo::KdTree::new() },
KDSpace::new(),
LocalRandomWalker,
UniformSpawner,
KDGrid2Sticker { stick_probability },
ProbabilisticSticking::new(stick_probability).unwrap(),
cli.max_particles,
);
drive_system(&mut sys, cli.max_frames, cli.notify_every);
write(&sys, cli.format, &cli.output);
}
PCM::Grid3KDTsang(StickProbabilityCli { grid_size, stick_probability }) => {
let mut sys = DLASystem::<_, Grid3D, _, _, _, _>::new(
SmallRng::seed_from_u64(cli.seed),
KDSpace::new(),
DiagonalRandomWalker,
UniformSpawner,
ProbabilisticSticking::new(stick_probability).unwrap(),
cli.max_particles,
);
@ -77,7 +90,7 @@ fn main() {
VectorStorage::new(grid_size, 3),
LocalRandomWalker,
UniformSpawner,
ProbabilisticSticking { stick_probability },
ProbabilisticSticking::new(stick_probability).unwrap(),
cli.max_particles,
);
@ -91,7 +104,7 @@ fn main() {
VectorStorage::new(grid_size, 2),
LocalRandomWalker,
UniformSpawner,
ProbabilisticSticking { stick_probability },
ProbabilisticSticking::new(stick_probability).unwrap(),
cli.max_particles,
);

View File

@ -1,3 +1,4 @@
use anyhow::anyhow;
use rand::Rng;
use crate::system::{GriddedPosition, Position, Storage};
use crate::system::spaces::square_grid::{Grid2D, Grid3D};
@ -11,11 +12,17 @@ fn taxicab_grid3(a: &[f32; 3], b: &[f32; 3]) -> f32 {
(a[0] - b[0]).abs() + (a[1] - b[1]).abs() + (a[2] - b[2]).abs()
}
pub struct KDGrid<const N: usize> {
pub struct KDSpace<const N: usize> {
pub(crate) inner: kiddo::KdTree<f32, (), N>,
}
impl Storage<Grid2D> for KDGrid<2> {
impl<const N: usize> KDSpace<N> {
pub fn new() -> KDSpace<N> {
KDSpace { inner: kiddo::KdTree::new() }
}
}
impl Storage<Grid2D> for KDSpace<2> {
fn is_occupied(&self, position: &Grid2D) -> bool {
let a = self.inner.best_n_within(&[position.x as f32, position.y as f32], 0f32, 1, &taxicab_grid2).unwrap();
!a.is_empty()
@ -27,7 +34,7 @@ impl Storage<Grid2D> for KDGrid<2> {
}
}
impl Storage<Grid3D> for KDGrid<3> {
impl Storage<Grid3D> for KDSpace<3> {
fn is_occupied(&self, position: &Grid3D) -> bool {
let a = self.inner.best_n_within(&[position.x as f32, position.y as f32, position.z as f32], 0f32, 1, &taxicab_grid3).unwrap();
!a.is_empty()
@ -39,13 +46,22 @@ impl Storage<Grid3D> for KDGrid<3> {
}
}
pub struct KDGrid2Sticker {
pub struct KDProbabilisticSticking {
pub(crate) stick_probability: f32,
}
impl Sticker<Grid2D, KDGrid<2>> for KDGrid2Sticker {
fn should_stick<R: Rng>(&self, rng: &mut R, space: &KDGrid<2>, position: &Grid2D) -> bool {
impl KDProbabilisticSticking {
fn new(stick_probability: f32) -> anyhow::Result<KDProbabilisticSticking> {
return if 0f32 < stick_probability && stick_probability <= 1f32 {
Ok(KDProbabilisticSticking { stick_probability })
} else {
Err(anyhow!("Sticking probability outside of (0, 1] range."))
}
}
}
impl Sticker<Grid2D, KDSpace<2>> for KDProbabilisticSticking {
fn should_stick<R: Rng>(&self, rng: &mut R, space: &KDSpace<2>, position: &Grid2D) -> bool {
let a = space.inner.best_n_within(&[position.x as f32, position.y as f32], 1f32, Grid2D::NEIGHBOURS as usize, &taxicab_grid2)
.unwrap();
@ -53,14 +69,14 @@ impl Sticker<Grid2D, KDGrid<2>> for KDGrid2Sticker {
return false;
}
let q = (1f32 - self.stick_probability);
let q = 1f32 - self.stick_probability;
let a = q.powi(a.len() as i32);
rng.gen_range(0f32..1f32) > a
}
}
impl Sticker<Grid3D, KDGrid<3>> for KDGrid2Sticker {
fn should_stick<R: Rng>(&self, rng: &mut R, space: &KDGrid<3>, position: &Grid3D) -> bool {
impl Sticker<Grid3D, KDSpace<3>> for KDProbabilisticSticking {
fn should_stick<R: Rng>(&self, rng: &mut R, space: &KDSpace<3>, position: &Grid3D) -> bool {
let a = space.inner.best_n_within(&[position.x as f32, position.y as f32, position.z as f32], 1f32, Grid2D::NEIGHBOURS as usize, &taxicab_grid3)
.unwrap();

View File

@ -1,3 +1,4 @@
use anyhow::anyhow;
use rand::Rng;
use crate::system::{GriddedPosition, Position, Storage};
@ -8,7 +9,17 @@ pub trait Sticker<P: Position, S: Storage<P>> {
pub struct SimpleSticking;
pub struct ProbabilisticSticking {
pub stick_probability: f32
pub(crate) stick_probability: f32
}
impl ProbabilisticSticking {
pub fn new(stick_probability: f32) -> anyhow::Result<ProbabilisticSticking> {
return if 0f32 < stick_probability && stick_probability <= 1f32 {
Ok(ProbabilisticSticking { stick_probability })
} else {
Err(anyhow!("Sticking probability outside of (0, 1] range."))
}
}
}
impl<P: GriddedPosition, S: Storage<P>> Sticker<P, S> for SimpleSticking {

View File

@ -1,5 +1,6 @@
use rand::prelude::Rng;
use crate::system::{GriddedPosition, Position};
use crate::system::spaces::square_grid::Grid3D;
pub trait Walker<P: Position> {
fn walk<R: Rng>(&self, rng: &mut R, position: &P) -> P;
@ -13,12 +14,25 @@ impl<P: GriddedPosition> Walker<P> for LocalRandomWalker {
}
}
pub struct DiagonalRandomWalker;
impl Walker<Grid3D> for DiagonalRandomWalker {
fn walk<R: Rng>(&self, rng: &mut R, position: &Grid3D) -> Grid3D {
let a: Vec<i32> = (0..3)
.map(|r| rng.gen_range(-1..=1))
.collect();
position.clone() + Grid3D::from_cartesian([a[0] as f32, a[1] as f32, a[2] as f32])
}
}
mod test {
use rand::rngs::SmallRng;
use rand::{SeedableRng, thread_rng};
use crate::cli::cli::PCM::Grid3;
use crate::system::{GriddedPosition, Position};
use crate::system::spaces::square_grid::Grid2D;
use crate::system::walker::{LocalRandomWalker, Walker};
use crate::system::spaces::square_grid::{Grid2D, Grid3D};
use crate::system::walker::{DiagonalRandomWalker, LocalRandomWalker, Walker};
#[test]
fn uniformity() {
@ -55,4 +69,14 @@ mod test {
println!("{} {} {} {}", a as f32 / x as f32, b as f32 / x as f32, c as f32 / x as f32, d as f32 / x as f32);
}
#[test]
fn diagonal() {
let drw = DiagonalRandomWalker;
let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
for _ in 0..20 {
println!("{:?}", drw.walk(&mut rng, &Grid3D::zero()))
}
}
}