We can create a new single-population model
This commit is contained in:
parent
bb1b5ddac0
commit
6a2d19e984
@ -63,7 +63,7 @@ impl Blur {
|
||||
for j in 0..radius {
|
||||
value += src_row[width - radius + j] + src_row[j];
|
||||
}
|
||||
// At this point "value" contains the unweighted sum for the right-most row element.
|
||||
|
||||
for i in 0..width {
|
||||
let left = (i + width - radius - 1) & (width - 1);
|
||||
let right = (i + radius) & (width - 1);
|
||||
@ -82,7 +82,6 @@ impl Blur {
|
||||
// We don't replicate the horizontal filter logic because of the cache-unfriendly memory
|
||||
// access patterns of sequential iteration over individual columns. Instead, we iterate over
|
||||
// rows via loop interchange.
|
||||
|
||||
let offset = (height - radius - 1) * width;
|
||||
self.row_buffer
|
||||
.copy_from_slice(&src[offset..offset + width]);
|
||||
@ -97,7 +96,6 @@ impl Blur {
|
||||
*buf += bottom + top;
|
||||
}
|
||||
}
|
||||
// At this point row_buffer contains the unweighted sum for all top elements.
|
||||
|
||||
for (i, dst_row) in dst.chunks_exact_mut(width).enumerate() {
|
||||
let bottom_off = ((i + height - radius - 1) & (height - 1)) * width;
|
||||
@ -128,7 +126,7 @@ mod tests {
|
||||
blur.box_blur_h(&src, &mut dst, 1);
|
||||
assert_eq!(
|
||||
dst,
|
||||
&[
|
||||
[
|
||||
2.3333335, 2.0, 3.0, 2.6666667, 6.3333335, 6.0, 7.0, 6.666667, 10.333334, 10.0,
|
||||
11.0, 10.666667, 14.333334, 14.0, 15.0, 14.666667
|
||||
]
|
||||
|
||||
@ -2,4 +2,7 @@ mod blur;
|
||||
mod grid;
|
||||
mod model;
|
||||
|
||||
fn main() {}
|
||||
fn main() {
|
||||
let model = model::Model::new(4, 4, 20, 1);
|
||||
println!("{:#?}", model);
|
||||
}
|
||||
|
||||
89
src/model.rs
89
src/model.rs
@ -1,32 +1,97 @@
|
||||
use crate::grid::Grid;
|
||||
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
/// A single Physarum agent. The x and y positions are continuous, hence we use floating point
|
||||
/// numbers instead of integers.
|
||||
#[derive(Debug)]
|
||||
pub struct Agent {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub angle: f32,
|
||||
struct Agent {
|
||||
x: f32,
|
||||
y: f32,
|
||||
angle: f32,
|
||||
}
|
||||
|
||||
impl Agent {
|
||||
fn new(width: usize, height: usize) -> Self {
|
||||
let mut rng = rand::thread_rng();
|
||||
let (x, y, angle) = rng.gen::<(f32, f32, f32)>();
|
||||
Agent {
|
||||
x: x * width as f32,
|
||||
y: y * height as f32,
|
||||
angle: angle * std::f32::consts::TAU,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A model configuration. We make it into a separate type, because we will eventually have multiple
|
||||
/// configurations in one model.
|
||||
#[derive(Debug)]
|
||||
pub struct PopulationConfig {
|
||||
pub sensor_angle: f32,
|
||||
pub sensor_distance: f32,
|
||||
pub rotation_angle: f32,
|
||||
pub step_distance: f32,
|
||||
pub decay_factor: f32,
|
||||
struct PopulationConfig {
|
||||
sensor_distance: f32,
|
||||
step_distance: f32,
|
||||
decay_factor: f32,
|
||||
sensor_angle: f32,
|
||||
rotation_angle: f32,
|
||||
}
|
||||
|
||||
impl PopulationConfig {}
|
||||
impl PopulationConfig {
|
||||
const SENSOR_ANGLE_MIN: f32 = 0.0;
|
||||
const SENSOR_ANGLE_MAX: f32 = 120.0;
|
||||
const SENSOR_DISTANCE_MIN: f32 = 0.0;
|
||||
const SENSOR_DISTANCE_MAX: f32 = 64.0;
|
||||
const ROTATION_ANGLE_MIN: f32 = 0.0;
|
||||
const ROTATION_ANGLE_MAX: f32 = 120.0;
|
||||
const STEP_DISTANCE_MIN: f32 = 0.2;
|
||||
const STEP_DISTANCE_MAX: f32 = 2.0;
|
||||
const DEPOSITION_AMOUNT_MIN: f32 = 5.0;
|
||||
const DEPOSITION_AMOUNT_MAX: f32 = 5.0;
|
||||
const DECAY_FACTOR_MIN: f32 = 0.1;
|
||||
const DECAY_FACTOR_MAX: f32 = 0.1;
|
||||
|
||||
/// Generate a random configuration.
|
||||
pub fn new() -> Self {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
PopulationConfig {
|
||||
sensor_distance: rng.gen_range(Self::SENSOR_DISTANCE_MIN..=Self::SENSOR_DISTANCE_MAX),
|
||||
step_distance: rng.gen_range(Self::STEP_DISTANCE_MIN..=Self::STEP_DISTANCE_MAX),
|
||||
decay_factor: rng.gen_range(Self::DECAY_FACTOR_MIN..=Self::DECAY_FACTOR_MAX),
|
||||
sensor_angle: rng
|
||||
.gen_range(Self::SENSOR_ANGLE_MIN..=Self::SENSOR_ANGLE_MAX)
|
||||
.to_radians(),
|
||||
rotation_angle: rng
|
||||
.gen_range(Self::ROTATION_ANGLE_MIN..=Self::ROTATION_ANGLE_MAX)
|
||||
.to_radians(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Top-level simulation class.
|
||||
#[derive(Debug)]
|
||||
pub struct Model {
|
||||
grid: Grid,
|
||||
// Physarum agents.
|
||||
agents: Vec<Agent>,
|
||||
|
||||
// The grid they move on.
|
||||
grid: Grid,
|
||||
|
||||
// Simulation parameters.
|
||||
diffusivity: usize,
|
||||
config: PopulationConfig,
|
||||
|
||||
iteration: i32,
|
||||
}
|
||||
|
||||
impl Model {
|
||||
pub fn new(width: usize, height: usize, n_particles: usize, diffusivity: usize) -> Self {
|
||||
Model {
|
||||
agents: (0..n_particles)
|
||||
.map(|_| Agent::new(width, height))
|
||||
.collect(),
|
||||
grid: Grid::new(width, height),
|
||||
diffusivity,
|
||||
config: PopulationConfig::new(),
|
||||
iteration: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user