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 {
|
for j in 0..radius {
|
||||||
value += src_row[width - radius + j] + src_row[j];
|
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 {
|
for i in 0..width {
|
||||||
let left = (i + width - radius - 1) & (width - 1);
|
let left = (i + width - radius - 1) & (width - 1);
|
||||||
let right = (i + radius) & (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
|
// 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
|
// access patterns of sequential iteration over individual columns. Instead, we iterate over
|
||||||
// rows via loop interchange.
|
// rows via loop interchange.
|
||||||
|
|
||||||
let offset = (height - radius - 1) * width;
|
let offset = (height - radius - 1) * width;
|
||||||
self.row_buffer
|
self.row_buffer
|
||||||
.copy_from_slice(&src[offset..offset + width]);
|
.copy_from_slice(&src[offset..offset + width]);
|
||||||
@ -97,7 +96,6 @@ impl Blur {
|
|||||||
*buf += bottom + top;
|
*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() {
|
for (i, dst_row) in dst.chunks_exact_mut(width).enumerate() {
|
||||||
let bottom_off = ((i + height - radius - 1) & (height - 1)) * width;
|
let bottom_off = ((i + height - radius - 1) & (height - 1)) * width;
|
||||||
@ -128,7 +126,7 @@ mod tests {
|
|||||||
blur.box_blur_h(&src, &mut dst, 1);
|
blur.box_blur_h(&src, &mut dst, 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
dst,
|
dst,
|
||||||
&[
|
[
|
||||||
2.3333335, 2.0, 3.0, 2.6666667, 6.3333335, 6.0, 7.0, 6.666667, 10.333334, 10.0,
|
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
|
11.0, 10.666667, 14.333334, 14.0, 15.0, 14.666667
|
||||||
]
|
]
|
||||||
|
|||||||
@ -2,4 +2,7 @@ mod blur;
|
|||||||
mod grid;
|
mod grid;
|
||||||
mod model;
|
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 crate::grid::Grid;
|
||||||
|
|
||||||
|
use rand::{thread_rng, Rng};
|
||||||
|
|
||||||
/// A single Physarum agent. The x and y positions are continuous, hence we use floating point
|
/// A single Physarum agent. The x and y positions are continuous, hence we use floating point
|
||||||
/// numbers instead of integers.
|
/// numbers instead of integers.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Agent {
|
struct Agent {
|
||||||
pub x: f32,
|
x: f32,
|
||||||
pub y: f32,
|
y: f32,
|
||||||
pub angle: 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
|
/// A model configuration. We make it into a separate type, because we will eventually have multiple
|
||||||
/// configurations in one model.
|
/// configurations in one model.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PopulationConfig {
|
struct PopulationConfig {
|
||||||
pub sensor_angle: f32,
|
sensor_distance: f32,
|
||||||
pub sensor_distance: f32,
|
step_distance: f32,
|
||||||
pub rotation_angle: f32,
|
decay_factor: f32,
|
||||||
pub step_distance: f32,
|
sensor_angle: f32,
|
||||||
pub decay_factor: 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.
|
/// Top-level simulation class.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
grid: Grid,
|
// Physarum agents.
|
||||||
agents: Vec<Agent>,
|
agents: Vec<Agent>,
|
||||||
|
|
||||||
|
// The grid they move on.
|
||||||
|
grid: Grid,
|
||||||
|
|
||||||
|
// Simulation parameters.
|
||||||
|
diffusivity: usize,
|
||||||
config: PopulationConfig,
|
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