Some FD code and supporting infra

This commit is contained in:
Joshua Coles 2023-03-10 20:32:05 +00:00
parent 10c7450c8a
commit 4a5fca6837
17 changed files with 359246 additions and 15 deletions

16
Cargo.lock generated
View File

@ -1353,6 +1353,12 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
[[package]]
name = "either"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]] [[package]]
name = "encase" name = "encase"
version = "0.4.1" version = "0.4.1"
@ -1887,6 +1893,15 @@ dependencies = [
"windows-sys 0.45.0", "windows-sys 0.45.0",
] ]
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.5" version = "1.0.5"
@ -2842,6 +2857,7 @@ dependencies = [
"cbindgen", "cbindgen",
"clap 4.1.8", "clap 4.1.8",
"csv", "csv",
"itertools",
"kd-tree", "kd-tree",
"kiddo", "kiddo",
"nalgebra 0.32.2", "nalgebra 0.32.2",

View File

@ -18,6 +18,10 @@ path = "src/main.rs"
name = "ui" name = "ui"
path = "src/ui.rs" path = "src/ui.rs"
[[bin]]
name = "fd-calc"
path = "src/fd.rs"
# Set the default for crate. # Set the default for crate.
[profile.dev] [profile.dev]
opt-level = 1 opt-level = 1
@ -43,6 +47,7 @@ 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" anyhow = "1.0.69"
itertools = "0.10.5"
[build-dependencies] [build-dependencies]
cbindgen = "0.24.3" cbindgen = "0.24.3"

100002
balls-10000.json Normal file

File diff suppressed because it is too large Load Diff

1
big-3d-1.json Normal file

File diff suppressed because one or more lines are too long

1
g2kt-2.json Normal file

File diff suppressed because one or more lines are too long

200002
g2kt-3.json Normal file

File diff suppressed because it is too large Load Diff

50002
g2kt.json Normal file

File diff suppressed because it is too large Load Diff

1
h33big.json Normal file

File diff suppressed because one or more lines are too long

174
src/fd.rs Normal file
View File

@ -0,0 +1,174 @@
#![feature(generic_const_exprs)]
mod system;
use std::fs::File;
use std::os::unix::fs::symlink;
use bevy::tasks::ParallelSlice;
use crate::system::spaces::square_grid::{Grid2D, Grid3D};
use itertools::Itertools;
use clap::Parser;
use crate::system::{GriddedPosition, Position};
use crate::system::model::HistoryLine;
fn box_count_2d(data: &Vec<Grid2D>, size: u32) -> usize {
let n = data.len();
let x_min = data
.iter()
.min_by(|Grid2D { x: x1, y: y1 }, Grid2D { x: x2, y: y2 }| x1.cmp(x2))
.unwrap().x;
let x_max = data
.iter()
.max_by(|Grid2D { x: x1, y: y1 }, Grid2D { x: x2, y: y2 }| x1.cmp(x2))
.unwrap().x;
let y_min = data
.iter()
.min_by(|Grid2D { x: x1, y: y1 }, Grid2D { x: x2, y: y2 }| y1.cmp(y2))
.unwrap().y;
let y_max = data
.iter()
.max_by(|Grid2D { x: x1, y: y1 }, Grid2D { x: x2, y: y2 }| y1.cmp(y2))
.unwrap().y;
let x_range = (x_max - x_min) as f64;
let y_range = (y_max - y_min) as f64;
let w: f64 = x_range / (size as f64);
// let n_x = size;
// let n_y = (y_range / w).ceil() as u32;
let grid_points = data.iter()
.map(|Grid2D { x, y }| [((x - x_min) as f64 / w) as u32, ((y - y_min) as f64 / w) as u32])
.collect::<Vec<_>>();
return grid_points.iter()
.unique()
.count();
}
fn box_count_3d(data: &Vec<Grid3D>, size: u32) -> usize {
let n = data.len();
let x_min = data
.iter()
.min_by(|Grid3D { x: x1, .. }, Grid3D { x: x2, .. }| x1.cmp(x2))
.unwrap().x;
let x_max = data
.iter()
.max_by(|Grid3D { x: x1, .. }, Grid3D { x: x2, .. }| x1.cmp(x2))
.unwrap().x;
let y_min = data
.iter()
.min_by(|Grid3D { y: v1, .. }, Grid3D { y: v2, .. }| v1.cmp(v2))
.unwrap().y;
let y_max = data
.iter()
.max_by(|Grid3D { y: v1, .. }, Grid3D { y: v2, .. }| v1.cmp(v2))
.unwrap().y;
let z_min = data
.iter()
.min_by(|Grid3D { z: v1, .. }, Grid3D { z: v2, .. }| v1.cmp(v2))
.unwrap().y;
let z_max = data
.iter()
.max_by(|Grid3D { z: v1, .. }, Grid3D { z: v2, .. }| v1.cmp(v2))
.unwrap().y;
let x_range = (x_max - x_min) as f64;
let y_range = (y_max - y_min) as f64;
let z_range = (z_max - z_min) as f64;
let w: f64 = x_range / (size as f64);
let grid_points = data.iter()
.map(|Grid3D { x, y, z }| [
((x - x_min) as f64 / w) as u32,
((y - y_min) as f64 / w) as u32,
((z - z_min) as f64 / w) as u32,
])
.collect::<Vec<_>>();
return grid_points.iter()
.unique()
.count();
}
fn box_count_nd<const N: usize, P: Position>(data: &Vec<P>, size: u32) -> usize {
let n = data.len();
let pp = data.iter().map(|op| op.to_cartesian()).collect::<Vec<P::Cartesian>>();
let x_min = data
.iter()
.min_by(|Grid3D { x: x1, .. }, Grid3D { x: x2, .. }| x1.cmp(x2))
.unwrap().x;
let x_max = data
.iter()
.max_by(|Grid3D { x: x1, .. }, Grid3D { x: x2, .. }| x1.cmp(x2))
.unwrap().x;
let y_min = data
.iter()
.min_by(|Grid3D { y: v1, .. }, Grid3D { y: v2, .. }| v1.cmp(v2))
.unwrap().y;
let y_max = data
.iter()
.max_by(|Grid3D { y: v1, .. }, Grid3D { y: v2, .. }| v1.cmp(v2))
.unwrap().y;
let z_min = data
.iter()
.min_by(|Grid3D { z: v1, .. }, Grid3D { z: v2, .. }| v1.cmp(v2))
.unwrap().y;
let z_max = data
.iter()
.max_by(|Grid3D { z: v1, .. }, Grid3D { z: v2, .. }| v1.cmp(v2))
.unwrap().y;
let x_range = (x_max - x_min) as f64;
let y_range = (y_max - y_min) as f64;
let z_range = (z_max - z_min) as f64;
let w: f64 = x_range / (size as f64);
let grid_points = data.iter()
.map(|Grid3D { x, y, z }| [
((x - x_min) as f64 / w) as u32,
((y - y_min) as f64 / w) as u32,
((z - z_min) as f64 / w) as u32,
])
.collect::<Vec<_>>();
return grid_points.iter()
.unique()
.count();
}
#[derive(Parser)]
struct FDArgs {
path: std::path::PathBuf,
}
fn main() {
let args = FDArgs::parse();
let lines: Vec<HistoryLine<Grid3D>> = serde_json::from_reader(File::open(args.path).unwrap())
.expect("Failed to read json");
let a = lines.iter()
.map(|l| l.position.clone())
.collect::<Vec<_>>();
for size in 1..250 {
println!("[{}, {:?}],", size, box_count_3d(&a, size));
}
}

View File

@ -8,11 +8,13 @@ pub mod model;
pub mod spaces; pub mod spaces;
pub trait Position: Add<Output=Self> + Serialize + Clone { pub trait Position: Add<Output=Self> + Serialize + Clone {
const DIM: usize; // const DIM: usize;
type Cartesian;
fn zero() -> Self; fn zero() -> Self;
fn abs(&self) -> f32; fn abs(&self) -> f32;
fn from_cartesian(cartesian: [f32; Self::DIM]) -> Self; fn from_cartesian(cartesian: Self::Cartesian) -> Self;
fn to_cartesian(&self) -> Self::Cartesian;
} }
pub trait GriddedPosition: Position { pub trait GriddedPosition: Position {

View File

@ -1,11 +1,11 @@
use rand::prelude::*; use rand::prelude::*;
use serde::Serialize; use serde::{Deserialize, Serialize};
use crate::system::{Position, Storage}; use crate::system::{Position, Storage};
use crate::system::spawner::Spawner; use crate::system::spawner::Spawner;
use crate::system::sticker::Sticker; use crate::system::sticker::Sticker;
use crate::system::walker::Walker; use crate::system::walker::Walker;
#[derive(Serialize)] #[derive(Serialize, Deserialize)]
pub struct HistoryLine<P: Position> { pub struct HistoryLine<P: Position> {
pub frame: usize, pub frame: usize,
pub cluster_radius: f32, pub cluster_radius: f32,

View File

@ -51,7 +51,7 @@ pub struct ContinuousStorage {
} }
impl Position for P3 { impl Position for P3 {
const DIM: usize = 3; type Cartesian = [f32; 3];
fn zero() -> Self { fn zero() -> Self {
P3 { x: 0f32, y: 0f32, z: 0f32 } P3 { x: 0f32, y: 0f32, z: 0f32 }
@ -61,9 +61,13 @@ impl Position for P3 {
(self.x.powi(2) + self.y.powi(2) + self.z.powi(2)).powf(0.5) (self.x.powi(2) + self.y.powi(2) + self.z.powi(2)).powf(0.5)
} }
fn from_cartesian(cartesian: [f32; Self::DIM]) -> Self { fn from_cartesian(cartesian: Self::Cartesian) -> Self {
P3 { x: cartesian[0], y: cartesian[1], z: cartesian[3] } P3 { x: cartesian[0], y: cartesian[1], z: cartesian[3] }
} }
fn to_cartesian(&self) -> Self::Cartesian {
[self.x, self.y, self.z]
}
} }
impl Storage<P3> for ContinuousStorage { impl Storage<P3> for ContinuousStorage {

View File

@ -1,4 +1,5 @@
use std::ops::Add; use std::ops::Add;
use num_integer::Roots;
use crate::system::{GriddedPosition, Position}; use crate::system::{GriddedPosition, Position};
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
@ -39,7 +40,8 @@ impl GriddedPosition for HexPosition {
} }
impl Position for HexPosition { impl Position for HexPosition {
const DIM: usize = 2; // const DIM: usize = 2;
type Cartesian = [f32; 2];
fn zero() -> Self { fn zero() -> Self {
HexPosition { q: 0, r: 0 } HexPosition { q: 0, r: 0 }
@ -49,10 +51,19 @@ impl Position for HexPosition {
((self.q.pow(2) + self.r.pow(2) + self.q * self.r) as f32).sqrt() ((self.q.pow(2) + self.r.pow(2) + self.q * self.r) as f32).sqrt()
} }
fn from_cartesian(cartesian: [f32; Self::DIM]) -> Self { fn from_cartesian(cartesian: Self::Cartesian) -> Self {
let q = (1.0f32/3.0f32).sqrt() * cartesian[0] - 1.0/3.0 * cartesian[1]; let q = (1.0f32 / 3.0f32).sqrt() * cartesian[0] - 1.0 / 3.0 * cartesian[1];
let r = 2.0/3.0 * cartesian[1]; let r = 2.0 / 3.0 * cartesian[1];
Self { q: q as i32, r: r as i32 } Self { q: q as i32, r: r as i32 }
} }
fn to_cartesian(&self) -> Self::Cartesian {
let q = self.q as f32;
let r = self.r as f32;
[
3f32.sqrt() * q + 3f32.sqrt() / 2f32 * r,
(3. / 2.) * r
]
}
} }

View File

@ -28,7 +28,7 @@ impl Add for Grid2D {
} }
impl Position for Grid2D { impl Position for Grid2D {
const DIM: usize = 2; type Cartesian = [f32; 2];
fn zero() -> Self { fn zero() -> Self {
Grid2D { x: 0, y: 0 } Grid2D { x: 0, y: 0 }
@ -38,12 +38,16 @@ impl Position for Grid2D {
(((self.x * self.x) + (self.y * self.y)) as f32).powf(0.5) (((self.x * self.x) + (self.y * self.y)) as f32).powf(0.5)
} }
fn from_cartesian(cartesian: [f32; Self::DIM]) -> Self { fn from_cartesian(cartesian: Self::Cartesian) -> Self {
Grid2D { Grid2D {
x: cartesian[0] as i32, x: cartesian[0] as i32,
y: cartesian[1] as i32, y: cartesian[1] as i32,
} }
} }
fn to_cartesian(&self) -> Self::Cartesian {
[self.x as f32, self.y as f32]
}
} }
impl GriddedPosition for Grid2D { impl GriddedPosition for Grid2D {
@ -103,7 +107,7 @@ impl Add for Grid3D {
} }
impl Position for Grid3D { impl Position for Grid3D {
const DIM: usize = 3; type Cartesian = [f32; 3];
fn zero() -> Self { fn zero() -> Self {
Grid3D { x: 0, y: 0, z: 0 } Grid3D { x: 0, y: 0, z: 0 }
@ -113,13 +117,17 @@ impl Position for Grid3D {
(((self.x * self.x) + (self.y * self.y) + (self.z * self.z)) as f32).powf(0.5) (((self.x * self.x) + (self.y * self.y) + (self.z * self.z)) as f32).powf(0.5)
} }
fn from_cartesian(cartesian: [f32; Self::DIM]) -> Self { fn from_cartesian(cartesian: Self::Cartesian) -> Self {
Self { Self {
x: cartesian[0] as i32, x: cartesian[0] as i32,
y: cartesian[1] as i32, y: cartesian[1] as i32,
z: cartesian[2] as i32, z: cartesian[2] as i32,
} }
} }
fn to_cartesian(&self) -> Self::Cartesian {
[self.x as f32, self.y as f32, self.z as f32]
}
} }
impl GriddedPosition for Grid3D { impl GriddedPosition for Grid3D {

View File

@ -29,7 +29,6 @@ impl Walker<Grid3D> for DiagonalRandomWalker {
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, Grid3D}; use crate::system::spaces::square_grid::{Grid2D, Grid3D};
use crate::system::walker::{DiagonalRandomWalker, LocalRandomWalker, Walker}; use crate::system::walker::{DiagonalRandomWalker, LocalRandomWalker, Walker};

1
t333big.json Normal file

File diff suppressed because one or more lines are too long

9002
x.json Normal file

File diff suppressed because it is too large Load Diff