fmt
This commit is contained in:
parent
bec6340607
commit
32bfd1b27e
@ -1,4 +1,3 @@
|
|||||||
unstable_features = true
|
unstable_features = true
|
||||||
imports_granularity = "Crate"
|
imports_granularity = "Crate"
|
||||||
wrap_comments = true
|
wrap_comments = false
|
||||||
comment_width = 100
|
|
||||||
@ -10,7 +10,7 @@ impl Clone for Blur {
|
|||||||
fn clone(&self) -> Blur {
|
fn clone(&self) -> Blur {
|
||||||
return Blur {
|
return Blur {
|
||||||
row_buffer: self.row_buffer.clone(),
|
row_buffer: self.row_buffer.clone(),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
14
src/grid.rs
14
src/grid.rs
@ -25,7 +25,7 @@ impl Clone for PopulationConfig {
|
|||||||
rotation_angle: self.rotation_angle,
|
rotation_angle: self.rotation_angle,
|
||||||
decay_factor: self.decay_factor,
|
decay_factor: self.decay_factor,
|
||||||
deposition_amount: self.deposition_amount,
|
deposition_amount: self.deposition_amount,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,13 +93,13 @@ pub struct Grid {
|
|||||||
impl Clone for Grid {
|
impl Clone for Grid {
|
||||||
fn clone(&self) -> Grid {
|
fn clone(&self) -> Grid {
|
||||||
return Grid {
|
return Grid {
|
||||||
config: self.config.clone(),
|
config: self.config.clone(),
|
||||||
width: self.width.clone(),
|
width: self.width.clone(),
|
||||||
height: self.height.clone(),
|
height: self.height.clone(),
|
||||||
data: self.data.clone(),
|
data: self.data.clone(),
|
||||||
buf: self.buf.clone(),
|
buf: self.buf.clone(),
|
||||||
blur: self.blur.clone(),
|
blur: self.blur.clone(),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,4 @@
|
|||||||
use crate::{
|
use crate::{grid::Grid, palette::Palette};
|
||||||
grid::{Grid},
|
|
||||||
palette::{Palette},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Class for storing data that will be used to create images
|
// Class for storing data that will be used to create images
|
||||||
pub struct ImgData {
|
pub struct ImgData {
|
||||||
@ -17,16 +13,16 @@ impl Clone for ImgData {
|
|||||||
grids: self.grids.clone(),
|
grids: self.grids.clone(),
|
||||||
palette: self.palette.clone(),
|
palette: self.palette.clone(),
|
||||||
iteration: self.iteration.clone(),
|
iteration: self.iteration.clone(),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImgData {
|
impl ImgData {
|
||||||
pub fn new(in_grids: Vec<Grid>, in_palette: Palette, in_iteration: i32) -> Self {
|
pub fn new(in_grids: Vec<Grid>, in_palette: Palette, in_iteration: i32) -> Self {
|
||||||
ImgData {
|
ImgData {
|
||||||
grids: in_grids,
|
grids: in_grids,
|
||||||
palette: in_palette,
|
palette: in_palette,
|
||||||
iteration: in_iteration,
|
iteration: in_iteration,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
mod blur;
|
mod blur;
|
||||||
mod grid;
|
mod grid;
|
||||||
|
mod imgdata; // for storing image data
|
||||||
|
mod math;
|
||||||
pub mod model;
|
pub mod model;
|
||||||
mod palette;
|
mod palette;
|
||||||
mod util;
|
mod util; // for math things
|
||||||
mod imgdata; // for storing image data
|
|
||||||
mod math; // for math things
|
|
||||||
|
|||||||
@ -17,18 +17,16 @@ fn main() {
|
|||||||
// `n_populations` is the # of types of agents
|
// `n_populations` is the # of types of agents
|
||||||
let n_populations = 1;
|
let n_populations = 1;
|
||||||
// let n_populations = 1 + rng.gen_range(1..4); // make # of populations between 2 and 5
|
// let n_populations = 1 + rng.gen_range(1..4); // make # of populations between 2 and 5
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let mut model = model::Model::new(width, height, n_particles, n_populations, diffusivity); // Create the model
|
let mut model = model::Model::new(width, height, n_particles, n_populations, diffusivity); // Create the model
|
||||||
|
|
||||||
model.print_configurations(); // Print config for model
|
model.print_configurations(); // Print config for model
|
||||||
|
|
||||||
model.run(n_iterations); // Actually run the model
|
model.run(n_iterations); // Actually run the model
|
||||||
|
|
||||||
// export saved image data
|
// export saved image data
|
||||||
println!("Rendering all saved image data....");
|
println!("Rendering all saved image data....");
|
||||||
model.render_all_imgdata();
|
model.render_all_imgdata();
|
||||||
model.flush_image_data();
|
model.flush_image_data();
|
||||||
println!("Done!");
|
println!("Done!");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,4 +36,4 @@ pub fn cos(mut x: f32) -> f32 {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn sin(x: f32) -> f32 {
|
pub fn sin(x: f32) -> f32 {
|
||||||
return cos(x - std::f32::consts::FRAC_PI_2);
|
return cos(x - std::f32::consts::FRAC_PI_2);
|
||||||
}
|
}
|
||||||
|
|||||||
73
src/model.rs
73
src/model.rs
@ -1,19 +1,16 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
grid::{combine, Grid, PopulationConfig},
|
grid::{combine, Grid, PopulationConfig},
|
||||||
palette::{random_palette, Palette},
|
|
||||||
imgdata::ImgData,
|
imgdata::ImgData,
|
||||||
|
palette::{random_palette, Palette},
|
||||||
util::wrap,
|
util::wrap,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use indicatif::{ParallelProgressIterator, ProgressBar, ProgressStyle};
|
||||||
|
use itertools::multizip;
|
||||||
use rand::{seq::SliceRandom, Rng};
|
use rand::{seq::SliceRandom, Rng};
|
||||||
use rand_distr::{Distribution, Normal};
|
use rand_distr::{Distribution, Normal};
|
||||||
use rayon::prelude::*;
|
use rayon::{iter::ParallelIterator, prelude::*};
|
||||||
use itertools::multizip;
|
use std::{f32::consts::TAU, path::Path, time::Instant};
|
||||||
use std::f32::consts::TAU;
|
|
||||||
use std::time::{Instant};
|
|
||||||
use rayon::iter::ParallelIterator;
|
|
||||||
use indicatif::{ParallelProgressIterator, ProgressBar, ProgressStyle};
|
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
// A single Physarum agent. The x and y positions are continuous, hence we use floating point numbers instead of integers.
|
// A single Physarum agent. The x and y positions are continuous, hence we use floating point numbers instead of integers.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -39,7 +36,7 @@ impl Agent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn tick(&mut self, grid: &Grid) {
|
pub fn tick(&mut self, grid: &Grid) {
|
||||||
let (width, height) = (grid.width, grid.height);
|
let (width, height) = (grid.width, grid.height);
|
||||||
let PopulationConfig {
|
let PopulationConfig {
|
||||||
sensor_distance,
|
sensor_distance,
|
||||||
@ -51,7 +48,7 @@ impl Agent {
|
|||||||
|
|
||||||
let xc = self.x + fastapprox::faster::cos(self.angle) * sensor_distance;
|
let xc = self.x + fastapprox::faster::cos(self.angle) * sensor_distance;
|
||||||
let yc = self.y + fastapprox::faster::sin(self.angle) * sensor_distance;
|
let yc = self.y + fastapprox::faster::sin(self.angle) * sensor_distance;
|
||||||
|
|
||||||
let agent_add_sens = self.angle + sensor_angle;
|
let agent_add_sens = self.angle + sensor_angle;
|
||||||
let agent_sub_sens = self.angle - sensor_angle;
|
let agent_sub_sens = self.angle - sensor_angle;
|
||||||
|
|
||||||
@ -68,7 +65,7 @@ impl Agent {
|
|||||||
// Rotate and move logic
|
// Rotate and move logic
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let mut direction: f32 = 0.0;
|
let mut direction: f32 = 0.0;
|
||||||
|
|
||||||
if (center > left) && (center > right) {
|
if (center > left) && (center > right) {
|
||||||
direction = 0.0;
|
direction = 0.0;
|
||||||
} else if (center < left) && (center < right) {
|
} else if (center < left) && (center < right) {
|
||||||
@ -82,8 +79,14 @@ impl Agent {
|
|||||||
let delta_angle = rotation_angle * direction;
|
let delta_angle = rotation_angle * direction;
|
||||||
|
|
||||||
self.angle = wrap(self.angle + delta_angle, TAU);
|
self.angle = wrap(self.angle + delta_angle, TAU);
|
||||||
self.x = wrap(self.x + step_distance * fastapprox::faster::cos(self.angle), width as f32);
|
self.x = wrap(
|
||||||
self.y = wrap(self.y + step_distance * fastapprox::faster::sin(self.angle), height as f32);
|
self.x + step_distance * fastapprox::faster::cos(self.angle),
|
||||||
|
width as f32,
|
||||||
|
);
|
||||||
|
self.y = wrap(
|
||||||
|
self.y + step_distance * fastapprox::faster::sin(self.angle),
|
||||||
|
height as f32,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,17 +98,20 @@ impl Clone for Agent {
|
|||||||
angle: self.angle,
|
angle: self.angle,
|
||||||
population_id: self.population_id,
|
population_id: self.population_id,
|
||||||
i: self.i,
|
i: self.i,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for Agent {
|
impl PartialEq for Agent {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
return self.x == other.x && self.y == other.y && self.angle == other.angle && self.population_id == other.population_id && self.i == other.i;
|
return self.x == other.x
|
||||||
|
&& self.y == other.y
|
||||||
|
&& self.angle == other.angle
|
||||||
|
&& self.population_id == other.population_id
|
||||||
|
&& self.i == other.i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Top-level simulation class.
|
// Top-level simulation class.
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
// Physarum agents.
|
// Physarum agents.
|
||||||
@ -188,7 +194,6 @@ impl Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Simulates `steps` # of steps
|
// Simulates `steps` # of steps
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn run(&mut self, steps: usize) {
|
pub fn run(&mut self, steps: usize) {
|
||||||
@ -206,7 +211,9 @@ impl Model {
|
|||||||
let mut time_per_agent_list: Vec<f64> = Vec::new();
|
let mut time_per_agent_list: Vec<f64> = Vec::new();
|
||||||
let mut time_per_step_list: Vec<f64> = Vec::new();
|
let mut time_per_step_list: Vec<f64> = Vec::new();
|
||||||
for i in 0..steps {
|
for i in 0..steps {
|
||||||
if debug {println!("Starting tick for all agents...")};
|
if debug {
|
||||||
|
println!("Starting tick for all agents...")
|
||||||
|
};
|
||||||
|
|
||||||
// Combine grids
|
// Combine grids
|
||||||
let grids = &mut self.grids;
|
let grids = &mut self.grids;
|
||||||
@ -237,16 +244,26 @@ impl Model {
|
|||||||
time_per_agent_list.push(ms_per_agent);
|
time_per_agent_list.push(ms_per_agent);
|
||||||
time_per_step_list.push(agents_tick_elapsed);
|
time_per_step_list.push(agents_tick_elapsed);
|
||||||
|
|
||||||
if debug {println!("Finished tick for all agents. took {}ms\nTime per agent: {}ms\n", agents_tick_elapsed, ms_per_agent)};
|
if debug {
|
||||||
|
println!(
|
||||||
|
"Finished tick for all agents. took {}ms\nTime per agent: {}ms\n",
|
||||||
|
agents_tick_elapsed, ms_per_agent
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
self.iteration += 1;
|
self.iteration += 1;
|
||||||
pb.set_position(i as u64);
|
pb.set_position(i as u64);
|
||||||
}
|
}
|
||||||
pb.finish();
|
pb.finish();
|
||||||
|
|
||||||
let avg_per_step: f64 = time_per_step_list.iter().sum::<f64>() as f64 / time_per_step_list.len() as f64;
|
let avg_per_step: f64 =
|
||||||
let avg_per_agent: f64 = time_per_agent_list.iter().sum::<f64>() as f64 / time_per_agent_list.len() as f64;
|
time_per_step_list.iter().sum::<f64>() as f64 / time_per_step_list.len() as f64;
|
||||||
println!("Average time per step: {}ms\nAverage time per agent: {}ms", avg_per_step, avg_per_agent);
|
let avg_per_agent: f64 =
|
||||||
|
time_per_agent_list.iter().sum::<f64>() as f64 / time_per_agent_list.len() as f64;
|
||||||
|
println!(
|
||||||
|
"Average time per step: {}ms\nAverage time per agent: {}ms",
|
||||||
|
avg_per_step, avg_per_agent
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_image_data(&mut self) {
|
fn save_image_data(&mut self) {
|
||||||
@ -260,7 +277,6 @@ impl Model {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn flush_image_data(&mut self) {
|
pub fn flush_image_data(&mut self) {
|
||||||
@ -285,7 +301,9 @@ impl Model {
|
|||||||
pb.finish();
|
pb.finish();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
(&self.img_data_vec).par_iter().progress_with(pb)
|
(&self.img_data_vec)
|
||||||
|
.par_iter()
|
||||||
|
.progress_with(pb)
|
||||||
.for_each(|img| {
|
.for_each(|img| {
|
||||||
Self::save_to_image(img.to_owned());
|
Self::save_to_image(img.to_owned());
|
||||||
});
|
});
|
||||||
@ -306,7 +324,8 @@ impl Model {
|
|||||||
let i = y * width + x;
|
let i = y * width + x;
|
||||||
let (mut r, mut g, mut b) = (0.0_f32, 0.0_f32, 0.0_f32);
|
let (mut r, mut g, mut b) = (0.0_f32, 0.0_f32, 0.0_f32);
|
||||||
for (grid, max_value, color) in
|
for (grid, max_value, color) in
|
||||||
multizip((&imgdata.grids, &max_values, &imgdata.palette.colors)) {
|
multizip((&imgdata.grids, &max_values, &imgdata.palette.colors))
|
||||||
|
{
|
||||||
let mut t = (grid.data()[i] / max_value).clamp(0.0, 1.0);
|
let mut t = (grid.data()[i] / max_value).clamp(0.0, 1.0);
|
||||||
t = t.powf(1.0 / 2.2); // gamma correction
|
t = t.powf(1.0 / 2.2); // gamma correction
|
||||||
r += color.0[0] as f32 * t;
|
r += color.0[0] as f32 * t;
|
||||||
@ -320,7 +339,7 @@ impl Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
img.save(format!("./tmp/out_{}.png", imgdata.iteration).as_str())
|
||||||
img.save(format!("./tmp/out_{}.png", imgdata.iteration).as_str()).unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn wrap(x: f32, max: f32) -> f32 {
|
pub fn wrap(x: f32, max: f32) -> f32 {
|
||||||
return x - max * ((x > max) as i32 as f32 - (x < 0.0_f32) as i32 as f32);
|
return x - max * ((x > max) as i32 as f32 - (x < 0.0_f32) as i32 as f32);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user