Add DiagonalWalkera and fix 3D KD grid
This commit is contained in:
parent
73bb0f8ed1
commit
10c7450c8a
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -2837,6 +2837,7 @@ dependencies = [
|
|||||||
name = "rust-codebase"
|
name = "rust-codebase"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"bevy",
|
"bevy",
|
||||||
"cbindgen",
|
"cbindgen",
|
||||||
"clap 4.1.8",
|
"clap 4.1.8",
|
||||||
|
|||||||
@ -42,6 +42,7 @@ serde_json = "1.0.93"
|
|||||||
kd-tree = { version = "0.5.1", features = ["nalgebra"] }
|
kd-tree = { version = "0.5.1", features = ["nalgebra"] }
|
||||||
nalgebra = "0.32.2"
|
nalgebra = "0.32.2"
|
||||||
kiddo = "0.2.5"
|
kiddo = "0.2.5"
|
||||||
|
anyhow = "1.0.69"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cbindgen = "0.24.3"
|
cbindgen = "0.24.3"
|
||||||
|
|||||||
@ -38,6 +38,7 @@ pub enum PCM {
|
|||||||
Initial(InitialCli),
|
Initial(InitialCli),
|
||||||
StickProbability(StickProbabilityCli),
|
StickProbability(StickProbabilityCli),
|
||||||
Grid3KD(StickProbabilityCli),
|
Grid3KD(StickProbabilityCli),
|
||||||
|
Grid3KDTsang(StickProbabilityCli),
|
||||||
Grid3(StickProbabilityCli),
|
Grid3(StickProbabilityCli),
|
||||||
Hex(StickProbabilityCli),
|
Hex(StickProbabilityCli),
|
||||||
Balls(BallsCli),
|
Balls(BallsCli),
|
||||||
|
|||||||
@ -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) {
|
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");
|
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");
|
.expect("Failed to write json");
|
||||||
}
|
}
|
||||||
|
|||||||
77
src/clib.rs
77
src/clib.rs
@ -2,80 +2,3 @@
|
|||||||
pub extern "C" fn dla_rust_disabled() -> bool {
|
pub extern "C" fn dla_rust_disabled() -> bool {
|
||||||
true
|
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));
|
|
||||||
// // }
|
|
||||||
// // }
|
|
||||||
|
|||||||
31
src/main.rs
31
src/main.rs
@ -2,7 +2,6 @@
|
|||||||
#![feature(generic_const_exprs)]
|
#![feature(generic_const_exprs)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
|
|
||||||
use std::ops::Deref;
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use crate::cli::{drive_system};
|
use crate::cli::{drive_system};
|
||||||
@ -12,12 +11,12 @@ use crate::surface_probability_measure::{LoggerSticker, ReadOnlyVectorStorage};
|
|||||||
use crate::system::model::DLASystem;
|
use crate::system::model::DLASystem;
|
||||||
use crate::system::spaces::continuous::{ContinuousSticker, ContinuousStorage, ContinuousWalker};
|
use crate::system::spaces::continuous::{ContinuousSticker, ContinuousStorage, ContinuousWalker};
|
||||||
use crate::system::spaces::hexagonal::HexPosition;
|
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::square_grid::{Grid2D, Grid3D};
|
||||||
use crate::system::spaces::VectorStorage;
|
use crate::system::spaces::VectorStorage;
|
||||||
use crate::system::spawner::UniformSpawner;
|
use crate::system::spawner::UniformSpawner;
|
||||||
use crate::system::sticker::{ProbabilisticSticking, SimpleSticking};
|
use crate::system::sticker::{ProbabilisticSticking, SimpleSticking};
|
||||||
use crate::system::walker::LocalRandomWalker;
|
use crate::system::walker::{DiagonalRandomWalker, LocalRandomWalker};
|
||||||
|
|
||||||
mod system;
|
mod system;
|
||||||
mod surface_probability_measure;
|
mod surface_probability_measure;
|
||||||
@ -49,7 +48,7 @@ fn main() {
|
|||||||
VectorStorage::new(grid_size, 2),
|
VectorStorage::new(grid_size, 2),
|
||||||
LocalRandomWalker,
|
LocalRandomWalker,
|
||||||
UniformSpawner,
|
UniformSpawner,
|
||||||
ProbabilisticSticking { stick_probability },
|
ProbabilisticSticking::new(stick_probability).unwrap(),
|
||||||
cli.max_particles,
|
cli.max_particles,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -58,12 +57,26 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PCM::Grid3KD(StickProbabilityCli { grid_size, stick_probability }) => {
|
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),
|
SmallRng::seed_from_u64(cli.seed),
|
||||||
KDGrid { inner: kiddo::KdTree::new() },
|
KDSpace::new(),
|
||||||
LocalRandomWalker,
|
LocalRandomWalker,
|
||||||
UniformSpawner,
|
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,
|
cli.max_particles,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -77,7 +90,7 @@ fn main() {
|
|||||||
VectorStorage::new(grid_size, 3),
|
VectorStorage::new(grid_size, 3),
|
||||||
LocalRandomWalker,
|
LocalRandomWalker,
|
||||||
UniformSpawner,
|
UniformSpawner,
|
||||||
ProbabilisticSticking { stick_probability },
|
ProbabilisticSticking::new(stick_probability).unwrap(),
|
||||||
cli.max_particles,
|
cli.max_particles,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -91,7 +104,7 @@ fn main() {
|
|||||||
VectorStorage::new(grid_size, 2),
|
VectorStorage::new(grid_size, 2),
|
||||||
LocalRandomWalker,
|
LocalRandomWalker,
|
||||||
UniformSpawner,
|
UniformSpawner,
|
||||||
ProbabilisticSticking { stick_probability },
|
ProbabilisticSticking::new(stick_probability).unwrap(),
|
||||||
cli.max_particles,
|
cli.max_particles,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
use anyhow::anyhow;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use crate::system::{GriddedPosition, Position, Storage};
|
use crate::system::{GriddedPosition, Position, Storage};
|
||||||
use crate::system::spaces::square_grid::{Grid2D, Grid3D};
|
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()
|
(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>,
|
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 {
|
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();
|
let a = self.inner.best_n_within(&[position.x as f32, position.y as f32], 0f32, 1, &taxicab_grid2).unwrap();
|
||||||
!a.is_empty()
|
!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 {
|
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();
|
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()
|
!a.is_empty()
|
||||||
@ -39,13 +46,22 @@ impl Storage<Grid3D> for KDGrid<3> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct KDProbabilisticSticking {
|
||||||
pub struct KDGrid2Sticker {
|
|
||||||
pub(crate) stick_probability: f32,
|
pub(crate) stick_probability: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sticker<Grid2D, KDGrid<2>> for KDGrid2Sticker {
|
impl KDProbabilisticSticking {
|
||||||
fn should_stick<R: Rng>(&self, rng: &mut R, space: &KDGrid<2>, position: &Grid2D) -> bool {
|
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)
|
let a = space.inner.best_n_within(&[position.x as f32, position.y as f32], 1f32, Grid2D::NEIGHBOURS as usize, &taxicab_grid2)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@ -53,14 +69,14 @@ impl Sticker<Grid2D, KDGrid<2>> for KDGrid2Sticker {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let q = (1f32 - self.stick_probability);
|
let q = 1f32 - self.stick_probability;
|
||||||
let a = q.powi(a.len() as i32);
|
let a = q.powi(a.len() as i32);
|
||||||
rng.gen_range(0f32..1f32) > a
|
rng.gen_range(0f32..1f32) > a
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sticker<Grid3D, KDGrid<3>> for KDGrid2Sticker {
|
impl Sticker<Grid3D, KDSpace<3>> for KDProbabilisticSticking {
|
||||||
fn should_stick<R: Rng>(&self, rng: &mut R, space: &KDGrid<3>, position: &Grid3D) -> bool {
|
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)
|
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();
|
.unwrap();
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
use anyhow::anyhow;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use crate::system::{GriddedPosition, Position, Storage};
|
use crate::system::{GriddedPosition, Position, Storage};
|
||||||
|
|
||||||
@ -8,7 +9,17 @@ pub trait Sticker<P: Position, S: Storage<P>> {
|
|||||||
pub struct SimpleSticking;
|
pub struct SimpleSticking;
|
||||||
|
|
||||||
pub struct ProbabilisticSticking {
|
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 {
|
impl<P: GriddedPosition, S: Storage<P>> Sticker<P, S> for SimpleSticking {
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
use rand::prelude::Rng;
|
use rand::prelude::Rng;
|
||||||
use crate::system::{GriddedPosition, Position};
|
use crate::system::{GriddedPosition, Position};
|
||||||
|
use crate::system::spaces::square_grid::Grid3D;
|
||||||
|
|
||||||
pub trait Walker<P: Position> {
|
pub trait Walker<P: Position> {
|
||||||
fn walk<R: Rng>(&self, rng: &mut R, position: &P) -> P;
|
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 {
|
mod test {
|
||||||
use rand::rngs::SmallRng;
|
use rand::rngs::SmallRng;
|
||||||
use rand::{SeedableRng, thread_rng};
|
use rand::{SeedableRng, thread_rng};
|
||||||
|
use crate::cli::cli::PCM::Grid3;
|
||||||
use crate::system::{GriddedPosition, Position};
|
use crate::system::{GriddedPosition, Position};
|
||||||
use crate::system::spaces::square_grid::Grid2D;
|
use crate::system::spaces::square_grid::{Grid2D, Grid3D};
|
||||||
use crate::system::walker::{LocalRandomWalker, Walker};
|
use crate::system::walker::{DiagonalRandomWalker, LocalRandomWalker, Walker};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn uniformity() {
|
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);
|
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()))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user