diff --git a/.github/workflows/basic.yml b/.github/workflows/basic.yml index 4fe8468..449dec6 100644 --- a/.github/workflows/basic.yml +++ b/.github/workflows/basic.yml @@ -8,44 +8,43 @@ jobs: name: Check normal examples runs-on: ubuntu-latest steps: + - uses: actions/checkout@v5 - uses: Swatinem/rust-cache@v2 - - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@stable + - name: Install system dependencies + uses: ./.github/workflows/install-deps - run: cargo check --release checkmpi: name: Check mpi examples runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 - uses: Swatinem/rust-cache@v2 - uses: mpi4py/setup-mpi@v1 with: mpi: openmpi - uses: dtolnay/rust-toolchain@stable + - name: Install system dependencies + uses: ./.github/workflows/install-deps - run: cargo check --release --features distributed_mpi checkvis: name: Check visualization examples runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 - uses: Swatinem/rust-cache@v2 - uses: dtolnay/rust-toolchain@stable - - run: | - sudo apt update - sudo apt install pkg-config libx11-dev libasound2-dev libudev-dev - sudo apt install libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev libxcb-shape0-dev libxcb-xkb-dev - sudo apt install libxcb-render0-dev libxcb-xfixes0-dev libxcb1-dev - sudo apt install libudev-dev libasound2-dev portaudio19-dev build-essential libpulse-dev libdbus-1-dev - sudo apt install libfontconfig libfontconfig1-dev + - name: Install system dependencies + uses: ./.github/workflows/install-deps - run: cargo check --release --features visualization fmt: name: Rustfmt runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 - uses: dtolnay/rust-toolchain@stable with: components: rustfmt @@ -55,46 +54,37 @@ jobs: name: Clippy runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 - uses: dtolnay/rust-toolchain@stable with: components: clippy + - name: Install system dependencies + uses: ./.github/workflows/install-deps - run: cargo clippy clippyvis: - name: Clippy visualization + name: Clippy visualization bayesian runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 - uses: dtolnay/rust-toolchain@stable with: - command: clippy - args: --features bayesian + components: clippy + - name: Install system dependencies + uses: ./.github/workflows/install-deps + - run: cargo clippy --features "visualization, bayesian" clippympi: - name: Clippy visualization and mpi + name: Clippy mpi runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@stable with: - profile: minimal - toolchain: stable - override: true + components: clippy - uses: mpi4py/setup-mpi@v1 with: mpi: openmpi - - run: rustup component add clippy - - uses: actions-rs/cargo@v1 - with: - command: clippy - args: --features distributed_mpi - components: rustfmt - - run: | - sudo apt update - sudo apt install pkg-config libx11-dev libasound2-dev libudev-dev - sudo apt install libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev libxcb-shape0-dev libxcb-xkb-dev - sudo apt install libxcb-render0-dev libxcb-xfixes0-dev libxcb1-dev - sudo apt install libudev-dev libasound2-dev portaudio19-dev build-essential libpulse-dev libdbus-1-dev - sudo apt install libfontconfig libfontconfig1-dev - - run: cargo clippy --features "visualization, bayesian" + - name: Install system dependencies + uses: ./.github/workflows/install-deps + - run: cargo clippy --features distributed_mpi \ No newline at end of file diff --git a/.github/workflows/install-deps/action.yml b/.github/workflows/install-deps/action.yml new file mode 100644 index 0000000..54e13c1 --- /dev/null +++ b/.github/workflows/install-deps/action.yml @@ -0,0 +1,37 @@ +name: 'Install System Dependencies' +description: 'Install required system dependencies with caching' + +runs: + using: 'composite' + steps: + - name: Cache APT packages + uses: actions/cache@v4 + id: cache-apt + with: + path: /var/cache/apt/archives/*.deb + key: ${{ runner.os }}-apt-${{ hashFiles('**/action.yml') }}-v1 + restore-keys: | + ${{ runner.os }}-apt- + + - name: Install system dependencies + if: steps.cache-apt.outputs.cache-hit != 'true' + shell: bash + run: | + sudo apt update + sudo apt install -y --download-only \ + pkg-config libx11-dev libasound2-dev libudev-dev \ + libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev libxcb-shape0-dev libxcb-xkb-dev \ + libxcb-render0-dev libxcb-xfixes0-dev libxcb1-dev \ + portaudio19-dev build-essential libpulse-dev libdbus-1-dev \ + libfontconfig libfontconfig1-dev + + - name: Install cached packages + shell: bash + run: | + sudo apt update + sudo apt install -y \ + pkg-config libx11-dev libasound2-dev libudev-dev \ + libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev libxcb-shape0-dev libxcb-xkb-dev \ + libxcb-render0-dev libxcb-xfixes0-dev libxcb1-dev \ + portaudio19-dev build-essential libpulse-dev libdbus-1-dev \ + libfontconfig libfontconfig1-dev \ No newline at end of file diff --git a/antsforaging/src/model/ant.rs b/antsforaging/src/model/ant.rs index 6f655bc..f35ce5a 100644 --- a/antsforaging/src/model/ant.rs +++ b/antsforaging/src/model/ant.rs @@ -104,7 +104,7 @@ impl Ant { // with a probability of MOMENTUM_PROBABILITY. Otherwise, step in a random direction with a // probability of RANDOM_ACTION_PROBABILITY. pub fn act(&mut self, state: &ModelState) { - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); let mut max = -1.; // An initial, impossible pheromone. let x = self.loc.x; @@ -145,7 +145,7 @@ impl Ant { // A new maximum is found, or the maximux hasn't changed. In the latter case, we // randomly choose whether to consider the new cell for the next step or not with an // equal chance. - if m > max || (m == max && rng.gen_bool(1. / count as f64)) { + if m > max || (m == max && rng.random_bool(1. / count as f64)) { // Latter expression is to take a random step towards paths with a good pheromone max = m; max_x = new_x; @@ -158,7 +158,7 @@ impl Ant { if max == 0. && self.last.is_some() { // No tips from pheromones, consider stepping in the same direction if let Some(last_loc) = self.last { - if rng.gen_bool(MOMENTUM_PROBABILITY) { + if rng.random_bool(MOMENTUM_PROBABILITY) { let xm = x + (x - last_loc.x); let ym = y + (y - last_loc.y); // Don't go outside the field or in an obstacle @@ -171,10 +171,10 @@ impl Ant { } } } - } else if rng.gen_bool(RANDOM_ACTION_PROBABILITY) { + } else if rng.random_bool(RANDOM_ACTION_PROBABILITY) { // All other ideas have failed, just choose a random direction - let xd: i32 = rng.gen_range(-1..2); - let yd: i32 = rng.gen_range(-1..2); + let xd: i32 = rng.random_range(-1..2); + let yd: i32 = rng.random_range(-1..2); let xm = x + xd; let ym = y + yd; // Don't go outside the field, in an obstacle and do not stay still diff --git a/antsforaging/src/model/state.rs b/antsforaging/src/model/state.rs index 805b067..b62038b 100644 --- a/antsforaging/src/model/state.rs +++ b/antsforaging/src/model/state.rs @@ -95,18 +95,18 @@ impl State for ModelState { self.food_source_found = RwLock::new(false); self.food_returned_home = RwLock::new(false); - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); // Food generation let x: i32 = if FOOD_XMIN == FOOD_XMAX { FOOD_XMIN } else { - rng.gen_range(FOOD_XMIN..FOOD_XMAX) + rng.random_range(FOOD_XMIN..FOOD_XMAX) }; let y: i32 = if FOOD_YMIN == FOOD_YMAX { FOOD_YMIN } else { - rng.gen_range(FOOD_YMIN..FOOD_YMAX) + rng.random_range(FOOD_YMIN..FOOD_YMAX) }; let food_location = Int2D { x, y }; @@ -122,12 +122,12 @@ impl State for ModelState { let x: i32 = if HOME_XMIN == HOME_XMAX { HOME_XMIN } else { - rng.gen_range(HOME_XMIN..HOME_XMAX) + rng.random_range(HOME_XMIN..HOME_XMAX) }; let y: i32 = if HOME_YMIN == HOME_YMAX { HOME_YMIN } else { - rng.gen_range(HOME_YMIN..HOME_YMAX) + rng.random_range(HOME_YMIN..HOME_YMAX) }; let nest_location = Int2D { x, y }; self.obstacles_grid.set_object_location( diff --git a/flockers/src/main.rs b/flockers/src/main.rs index a07569d..b02f364 100644 --- a/flockers/src/main.rs +++ b/flockers/src/main.rs @@ -1,8 +1,8 @@ // No visualization specific imports #[cfg(not(any(feature = "visualization", feature = "visualization_wasm")))] use { - krabmaga::engine::schedule::Schedule, krabmaga::engine::state::State, krabmaga::Info, - krabmaga::*, std::time::Duration, + krabmaga::simulate, + // krabmaga::engine::state::State, krabmaga::*, std::time::Duration, krabmaga::engine::schedule::Schedule, krabmaga::Info, }; // Visualization specific imports #[cfg(any(feature = "visualization", feature = "visualization_wasm"))] @@ -35,7 +35,8 @@ fn main() { let dim = (800., 800.); let num_agents = 64000; let state = Flocker::new(dim, num_agents); - let _ = simulate_old!(state, step, 1, Info::Normal); + // let _ = simulate!(state, step, 1, Info::Normal); + let _ = simulate!(state, step, 1); } // Main used when a visualization feature is applied. diff --git a/flockers/src/model/bird.rs b/flockers/src/model/bird.rs index 34fd1dd..2aafd2a 100644 --- a/flockers/src/model/bird.rs +++ b/flockers/src/model/bird.rs @@ -100,10 +100,10 @@ impl Agent for Bird { }; //randomness - let mut rng = rand::thread_rng(); - let r1: f32 = rng.gen(); + let mut rng = rand::rng(); + let r1: f32 = rng.random(); let x_rand = r1 * 2.0 - 1.0; - let r2: f32 = rng.gen(); + let r2: f32 = rng.random(); let y_rand = r2 * 2.0 - 1.0; let square = (x_rand * x_rand + y_rand * y_rand).sqrt(); diff --git a/flockers/src/model/state.rs b/flockers/src/model/state.rs index f9c53e0..da6cc0c 100644 --- a/flockers/src/model/state.rs +++ b/flockers/src/model/state.rs @@ -35,11 +35,11 @@ impl State for Flocker { } fn init(&mut self, schedule: &mut Schedule) { - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); // Should be moved in the init method on the model exploration changes for bird_id in 0..self.initial_flockers { - let r1: f32 = rng.gen(); - let r2: f32 = rng.gen(); + let r1: f32 = rng.random(); + let r2: f32 = rng.random(); let last_d = Real2D { x: 0., y: 0. }; let loc = Real2D { x: self.dim.0 * r1, diff --git a/flockers_mpi/src/main.rs b/flockers_mpi/src/main.rs index a6544d4..b79f415 100644 --- a/flockers_mpi/src/main.rs +++ b/flockers_mpi/src/main.rs @@ -10,24 +10,13 @@ cfg_if! { mod model; // No visualization specific imports - #[cfg(not(any(feature = "visualization", feature = "visualization_wasm")))] + #[cfg(any(feature = "distributed_mpi"))] use { krabmaga::engine::schedule::Schedule, krabmaga::engine::state::State, krabmaga::simulate_mpi, krabmaga::Info, /* krabmaga::ProgressBar, */ krabmaga::*, std::time::Duration, }; - //use krabmaga::*; - - // Visualization specific imports - #[cfg(any(feature = "visualization", feature = "visualization_wasm"))] - use { - crate::visualization::vis_state::VisState, krabmaga::bevy::prelude::Color, - krabmaga::visualization::visualization::Visualization, - }; - - #[cfg(any(feature = "visualization", feature = "visualization_wasm"))] - mod visualization; pub static COHESION: f32 = 0.8; pub static AVOIDANCE: f32 = 1.0; @@ -46,28 +35,14 @@ cfg_if! { #[cfg(any(feature = "distributed_mpi"))] fn main() { - let step = 200; + let step = 100; - let dim = (1131., 1131.); - let num_agents = 128000; + let dim = (100., 100.); + let num_agents = 1000; let state = Flocker::new(dim, num_agents); let _ = simulate_mpi!(state, step, 1, Info::Normal); } - - // Main used when a visualization feature is applied. - #[cfg(any(feature = "visualization", feature = "visualization_wasm"))] - fn main() { - let dim = (200., 200.); - let num_agents = 100; - let state = Flocker::new(dim, num_agents); - Visualization::default() - .with_window_dimensions(1000., 700.) - .with_simulation_dimensions(dim.0 as f32, dim.1 as f32) - .with_background_color(Color::rgb(0., 0., 0.)) - .with_name("Flockers") - .start::(VisState, state); - } } else { fn main() {} diff --git a/flockers_mpi/src/model/bird.rs b/flockers_mpi/src/model/bird.rs index 06b825c..3ef1ad9 100644 --- a/flockers_mpi/src/model/bird.rs +++ b/flockers_mpi/src/model/bird.rs @@ -143,10 +143,10 @@ cfg_if! { }; //randomness - let mut rng = rand::thread_rng(); - let r1: f32 = rng.gen(); + let mut rng = rand::rng(); + let r1: f32 = rng.random(); let x_rand = r1 * 2.0 - 1.0; - let r2: f32 = rng.gen(); + let r2: f32 = rng.random(); let y_rand = r2 * 2.0 - 1.0; let square = (x_rand * x_rand + y_rand * y_rand).sqrt(); diff --git a/flockers_mpi/src/model/state.rs b/flockers_mpi/src/model/state.rs index 9395612..babc5b8 100644 --- a/flockers_mpi/src/model/state.rs +++ b/flockers_mpi/src/model/state.rs @@ -50,7 +50,7 @@ cfg_if! { ///The other processes, instead, will be waiting to receive the agents from process 0. fn init(&mut self, schedule: &mut Schedule) { let world = UNIVERSE.world(); - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); //Process 0 creates the agents if world.rank() == 0 { @@ -63,8 +63,8 @@ cfg_if! { //For each initial agent... for bird_id in 0..self.initial_flockers { - let r1: f32 = rng.gen(); - let r2: f32 = rng.gen(); + let r1: f32 = rng.random(); + let r2: f32 = rng.random(); let last_d = Real2D { x: 0., y: 0. }; let loc = Real2D { x: self.dim.0 * r1, diff --git a/flockers_mpi/src/visualization/bird_vis.rs b/flockers_mpi/src/visualization/bird_vis.rs deleted file mode 100644 index 433e0f7..0000000 --- a/flockers_mpi/src/visualization/bird_vis.rs +++ /dev/null @@ -1,69 +0,0 @@ -use crate::model::bird::Bird; -use crate::model::state::Flocker; -use krabmaga::bevy::ecs as bevy_ecs; -use krabmaga::bevy::prelude::{Component, Quat, Transform, Visibility}; -use krabmaga::engine::agent::Agent; -use krabmaga::engine::state::State; -use krabmaga::visualization::agent_render::{AgentRender, SpriteType}; -use std::f32::consts::PI; - -#[derive(Component)] -pub struct BirdVis { - pub(crate) id: u32, -} - -impl AgentRender for BirdVis { - fn sprite(&self, _agent: &Box, _state: &Box<&dyn State>) -> SpriteType { - SpriteType::Emoji(String::from("bird")) - } - - fn location(&self, agent: &Box, state: &Box<&dyn State>) -> (f32, f32, f32) { - let state = state.as_any().downcast_ref::().unwrap(); - let agent = agent.downcast_ref::().unwrap(); - let loc = state.field1.get_location(*agent); - match loc { - Some(loc) => (loc.x as f32, loc.y as f32, 0.), - None => (agent.loc.x as f32, agent.loc.y as f32, 0.), - } - } - - fn scale(&self, _agent: &Box, _state: &Box<&dyn State>) -> (f32, f32) { - (0.1, 0.1) - } - - /// The bird emoji points to left by default, so we calculate the rotation - /// and offset it by pi radians - fn rotation(&self, agent: &Box, _state: &Box<&dyn State>) -> f32 { - let concrete_agent = agent.downcast_ref::().unwrap(); - let rotation = if concrete_agent.last_d.x == 0. || concrete_agent.last_d.y == 0. { - 0. - } else { - concrete_agent.last_d.y.atan2(concrete_agent.last_d.x) - }; - (rotation + PI) as f32 - } - - fn update( - &mut self, - agent: &Box, - transform: &mut Transform, - state: &Box<&dyn State>, - _visible: &mut Visibility, - ) { - let (loc_x, loc_y, z) = self.location(agent, state); - let rotation = self.rotation(agent, state); - let (scale_x, scale_y) = self.scale(agent, state); - - let translation = &mut transform.translation; - translation.x = loc_x; - translation.y = loc_y; - translation.z = z; - transform.scale.x = scale_x; - transform.scale.y = scale_y; - transform.rotation = Quat::from_rotation_z(rotation); - } - - fn get_id(&self) -> u32 { - self.id - } -} diff --git a/flockers_mpi/src/visualization/mod.rs b/flockers_mpi/src/visualization/mod.rs deleted file mode 100644 index b6ccfee..0000000 --- a/flockers_mpi/src/visualization/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod bird_vis; -pub mod vis_state; diff --git a/flockers_mpi/src/visualization/vis_state.rs b/flockers_mpi/src/visualization/vis_state.rs deleted file mode 100644 index f458f02..0000000 --- a/flockers_mpi/src/visualization/vis_state.rs +++ /dev/null @@ -1,59 +0,0 @@ -use krabmaga::bevy::prelude::Commands; -use krabmaga::engine::agent::Agent; -use krabmaga::engine::location::Real2D; -use krabmaga::engine::schedule::Schedule; -use krabmaga::engine::state::State; -use krabmaga::visualization::agent_render::AgentRender; -use krabmaga::visualization::asset_handle_factory::AssetHandleFactoryResource; -use krabmaga::visualization::simulation_descriptor::SimulationDescriptor; -use krabmaga::visualization::visualization_state::VisualizationState; - -use crate::model::bird::Bird; -use crate::model::state::Flocker; -use crate::visualization::bird_vis::BirdVis; - -#[derive(Clone)] -pub struct VisState; - -impl VisualizationState for VisState { - fn on_init( - &self, - _commands: &mut Commands, - _sprite_render_factory: &mut AssetHandleFactoryResource, - _state: &mut Flocker, - _schedule: &mut Schedule, - _sim: &mut SimulationDescriptor, - ) { - } - - fn get_agent_render( - &self, - agent: &Box, - _state: &Flocker, - ) -> Option> { - // In a multi-agent model, you may want to do so - // if let Some(bird) = agent.as_any().downcast_ref::() {Box::new(BirdVis);} etc... - // We only have one agent here so we can directly return the correct AgentRender - Some(Box::new(BirdVis { - id: agent.downcast_ref::().unwrap().id, - })) - } - - fn get_agent( - &self, - agent_render: &Box, - state: &Box<&dyn State>, - ) -> Option> { - // TODO we don't just need the agent associated to the agent render, we need the correct one so that we - // can access data such as location etc... - let state = state.as_any().downcast_ref::().unwrap(); - match state.field1.get(&Bird::new( - agent_render.get_id(), - Real2D { x: 0., y: 0. }, - Real2D { x: 0., y: 0. }, - )) { - Some(matching_agent) => Some(Box::new(*matching_agent)), - None => None, - } - } -} diff --git a/forestfire/src/model/forest.rs b/forestfire/src/model/forest.rs index 25cba27..99b573a 100644 --- a/forestfire/src/model/forest.rs +++ b/forestfire/src/model/forest.rs @@ -109,12 +109,12 @@ impl State for Forest { fn init(&mut self, schedule: &mut Schedule) { self.step = 0; - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); let mut ids = 0; // generate the trees to populate the forest for i in 0..self.dim.0 { for j in 0..self.dim.1 { - if rng.gen_bool(self.density) { + if rng.random_bool(self.density) { let mut status_tree = Status::Green; if i == 0 { // Set the trees at the left edge on fire @@ -156,46 +156,46 @@ impl State for Forest { self.step += 1; } - fn end_condition(&mut self, _schedule: &mut Schedule) -> bool { - // for i in 0..self.field.width { - // for j in 0..self.field.height { - // let tree = match self.field.get_objects(&Int2D { x: i, y: j }) { - // Some(t) => t[0], - // None => { - // continue; - // } - // }; - // if tree.status == Status::Burned { - // self.burned += 1; - // } else if tree.status == Status::Green { - // self.green += 1; - // } else { - // self.burning += 1 - // } - // } - // } - - // if (self.before_burned == self.burned) - // && self.before_burning == self.burning - // && self.before_green == self.green - // { - // println!("-- Simulation finished at step {:?} --\nTotal trees in the forest: Green {:?}, Burning {:?}, Burned {:?}\n", - // schedule.step, self.green, self.burning, self.burned - // ); - // return true; - // } else { - // println!("-- Simulation continues at step {:?} --\nTotal trees in the forest: Green {:?}, Burning {:?}, Burned {:?}\n", - // schedule.step, self.green, self.burning, self.burned - // ); - // } - - // self.before_burned = self.burned; - // self.before_green = self.green; - // self.before_burning = self.burning; - - // self.burned = 0; - // self.green = 0; - // self.burning = 0; + fn end_condition(&mut self, schedule: &mut Schedule) -> bool { + for i in 0..self.field.width { + for j in 0..self.field.height { + let tree = match self.field.get_objects(&Int2D { x: i, y: j }) { + Some(t) => t[0], + None => { + continue; + } + }; + if tree.status == Status::Burned { + self.burned += 1; + } else if tree.status == Status::Green { + self.green += 1; + } else { + self.burning += 1 + } + } + } + + if (self.before_burned == self.burned) + && self.before_burning == self.burning + && self.before_green == self.green + { + println!("-- Simulation finished at step {:?} --\nTotal trees in the forest: Green {:?}, Burning {:?}, Burned {:?}\n", + schedule.step, self.green, self.burning, self.burned + ); + return true; + } else { + println!("-- Simulation continues at step {:?} --\nTotal trees in the forest: Green {:?}, Burning {:?}, Burned {:?}\n", + schedule.step, self.green, self.burning, self.burned + ); + } + + self.before_burned = self.burned; + self.before_green = self.green; + self.before_burning = self.burning; + + self.burned = 0; + self.green = 0; + self.burning = 0; false } diff --git a/forestfire_bayesian/src/main.rs b/forestfire_bayesian/src/main.rs index faeacc6..3f6c9a7 100644 --- a/forestfire_bayesian/src/main.rs +++ b/forestfire_bayesian/src/main.rs @@ -43,7 +43,7 @@ fn init_population() -> Vec> { let mut rng = RNG.lock().unwrap(); for _ in 0..INIT_ELEMENTS { - let density = rng.gen_range(0.01..=1.0_f64); // forest density + let density = rng.random_range(0.01..=1.0_f64); // forest density x_init.push(vec![density]); } @@ -85,7 +85,7 @@ fn get_points(_x: &[Vec]) -> Vec> { let trial_x: Vec> = (0..BATCH_SIZE) .into_iter() .map(|_| { - let density = rng.gen_range(0.1..=1.0_f64); // density + let density = rng.random_range(0.1..=1.0_f64); // density vec![density] }) .collect(); diff --git a/forestfire_bayesian/src/model/forest.rs b/forestfire_bayesian/src/model/forest.rs index 455073b..bb462a9 100644 --- a/forestfire_bayesian/src/model/forest.rs +++ b/forestfire_bayesian/src/model/forest.rs @@ -100,12 +100,12 @@ impl State for Forest { fn init(&mut self, schedule: &mut Schedule) { self.step = 0; - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); let mut ids = 0; // generate the trees to populate the forest for i in 0..self.dim.0 { for j in 0..self.dim.1 { - if rng.gen_bool(self.density) { + if rng.random_bool(self.density) { let mut status_tree = Status::Green; if i == 0 { // Set the trees at the left edge on fire diff --git a/schelling/src/model/world.rs b/schelling/src/model/world.rs index 53eda9f..18b76e8 100644 --- a/schelling/src/model/world.rs +++ b/schelling/src/model/world.rs @@ -97,11 +97,11 @@ impl State for World { //println!("init system by state"); self.step = 0; - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); for i in 0..self.num_agents { - let xx: i32 = rng.gen_range(0..self.dim.0); - let yy: i32 = rng.gen_range(0..self.dim.1); + let xx: i32 = rng.random_range(0..self.dim.0); + let yy: i32 = rng.random_range(0..self.dim.1); if i < ((self.num_agents as f32) * PERC).ceil() as u32 { self.field.set_object_location( diff --git a/sir_ga_exploration/Cargo.toml b/sir_ga_exploration/Cargo.toml index b67984b..51e8a05 100644 --- a/sir_ga_exploration/Cargo.toml +++ b/sir_ga_exploration/Cargo.toml @@ -18,7 +18,7 @@ readme = "README.md" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -krabmaga = "0.4.*" +krabmaga = "0.5.*" [features] distributed_mpi = ["krabmaga/distributed_mpi"] diff --git a/sir_ga_exploration/src/main.rs b/sir_ga_exploration/src/main.rs index d621bf9..c6f0728 100644 --- a/sir_ga_exploration/src/main.rs +++ b/sir_ga_exploration/src/main.rs @@ -106,10 +106,10 @@ fn init_population() -> Vec { // create n=INDIVIDUALS individuals for _ in 0..INDIVIDUALS { // create the individual - let x = rng.gen_range(0.0..=1.0_f32).to_string(); // spread chance - let y = rng.gen_range(0.0..=1.0_f32).to_string(); // recovery chance - let x2 = rng.gen_range(0.0..=1.0_f32).to_string(); // recovery chance - let day = rng.gen_range(0..=DAY).to_string(); // recovery chance + let x = rng.random_range(0.0..=1.0_f32).to_string(); // spread chance + let y = rng.random_range(0.0..=1.0_f32).to_string(); // recovery chance + let x2 = rng.random_range(0.0..=1.0_f32).to_string(); // recovery chance + let day = rng.random_range(0..=DAY).to_string(); // recovery chance population.push(format!("{};{};{};{}", x, y, x2, day)); } @@ -156,11 +156,11 @@ fn crossover(population: &mut Vec) { for _ in 0..(children_num as usize) { // select two random individuals - let idx_one = RNG.lock().unwrap().gen_range(0..population.len()); + let idx_one = RNG.lock().unwrap().random_range(0..population.len()); let parent_one = population[idx_one].clone(); - let mut idx_two = RNG.lock().unwrap().gen_range(0..population.len()); + let mut idx_two = RNG.lock().unwrap().random_range(0..population.len()); while idx_one == idx_two { - idx_two = RNG.lock().unwrap().gen_range(0..population.len()); + idx_two = RNG.lock().unwrap().random_range(0..population.len()); } let parent_two = population[idx_two].clone(); @@ -219,7 +219,7 @@ fn crossover(population: &mut Vec) { p_min = 0.; p_max = 1.; } - let new_spread = RNG.lock().unwrap().gen_range(p_min..=p_max); + let new_spread = RNG.lock().unwrap().random_range(p_min..=p_max); // new_recovery if one_recovery <= two_recovery { @@ -242,7 +242,7 @@ fn crossover(population: &mut Vec) { p_min = 0.; p_max = 1.; } - let new_recovery = RNG.lock().unwrap().gen_range(p_min..=p_max); + let new_recovery = RNG.lock().unwrap().random_range(p_min..=p_max); // new_spread2 if one_spread2 <= two_spread2 { @@ -265,7 +265,7 @@ fn crossover(population: &mut Vec) { p_min = 0.; p_max = 1.; } - let new_spread2 = RNG.lock().unwrap().gen_range(p_min..=p_max); + let new_spread2 = RNG.lock().unwrap().random_range(p_min..=p_max); // new_day let min_day; @@ -290,7 +290,7 @@ fn crossover(population: &mut Vec) { p_min = 0.; p_max = DAY as f32; } - let new_day = RNG.lock().unwrap().gen_range(p_min..=p_max).ceil(); + let new_day = RNG.lock().unwrap().random_range(p_min..=p_max).ceil(); let new_individual = format!( "{};{};{};{}", @@ -313,7 +313,11 @@ fn mutation(individual: &mut String) { // mutate one random parameter // randomly increase or decrease spread orrecovery - if RNG.lock().unwrap().gen_bool(*MUTATION_RATE.lock().unwrap()) { + if RNG + .lock() + .unwrap() + .random_bool(*MUTATION_RATE.lock().unwrap()) + { // mutate spread let mut new_spread = one_spread .parse::() @@ -333,7 +337,7 @@ fn mutation(individual: &mut String) { min = 0.; max = 1.; } - new_spread = RNG.lock().unwrap().gen_range(min..=max); + new_spread = RNG.lock().unwrap().random_range(min..=max); let mut new_spread2 = one_spread2 .parse::() @@ -352,7 +356,7 @@ fn mutation(individual: &mut String) { min = 0.; max = 1.; } - new_spread2 = RNG.lock().unwrap().gen_range(min..=max); + new_spread2 = RNG.lock().unwrap().random_range(min..=max); let mut new_recovery = one_recovery .parse::() @@ -371,7 +375,7 @@ fn mutation(individual: &mut String) { min = 0.; max = 1.; } - new_recovery = RNG.lock().unwrap().gen_range(min..=max); + new_recovery = RNG.lock().unwrap().random_range(min..=max); let mut new_day = one_day.parse::().expect("Unable to parse str to u64!"); let alpha: u64 = 1; @@ -391,7 +395,7 @@ fn mutation(individual: &mut String) { min = 0; max = DAY as u64; } - new_day = RNG.lock().unwrap().gen_range(min..=max); + new_day = RNG.lock().unwrap().random_range(min..=max); new_ind = format!( "{};{};{};{}", diff --git a/sir_ga_exploration/src/model/node.rs b/sir_ga_exploration/src/model/node.rs index 5f31502..e27b1d6 100644 --- a/sir_ga_exploration/src/model/node.rs +++ b/sir_ga_exploration/src/model/node.rs @@ -18,7 +18,7 @@ pub enum NodeStatus { pub struct NetNode { pub id: u32, pub status: NodeStatus, - pub virus_detected: bool, + // pub virus_detected: bool, } impl NetNode { @@ -26,7 +26,7 @@ impl NetNode { NetNode { id, status: init_status, - virus_detected: false, + // virus_detected: false, } } } @@ -39,7 +39,7 @@ impl Agent for NetNode { .unwrap(); match self.status { NodeStatus::Infected => { - if state.rng.lock().unwrap().gen_bool(state.recovery as f64) { + if state.rng.lock().unwrap().random_bool(state.recovery as f64) { self.status = NodeStatus::Resistant; } } @@ -63,7 +63,7 @@ impl Agent for NetNode { } else { spread = state.spread; } - if state.rng.lock().unwrap().gen_bool(spread as f64) { + if state.rng.lock().unwrap().random_bool(spread as f64) { self.status = NodeStatus::Infected; // increase count of how many nodes node has infected state.infected_nodes[node.id as usize] += 1; diff --git a/sir_ga_exploration/src/model/state.rs b/sir_ga_exploration/src/model/state.rs index e0ddcf0..2b94180 100644 --- a/sir_ga_exploration/src/model/state.rs +++ b/sir_ga_exploration/src/model/state.rs @@ -89,7 +89,7 @@ impl State for EpidemicNetworkState { let mut positions = vec![0; NUM_NODES as usize]; let infected = - StdRng::seed_from_u64(self.initial_infected as u64).gen_range(0..NUM_NODES) as usize; + StdRng::seed_from_u64(self.initial_infected as u64).random_range(0..NUM_NODES) as usize; positions[infected] = 1; // positions[self.initial_infected] = 1; diff --git a/sugarscape/src/model/eater.rs b/sugarscape/src/model/eater.rs index 06d893b..9ea362b 100644 --- a/sugarscape/src/model/eater.rs +++ b/sugarscape/src/model/eater.rs @@ -5,7 +5,8 @@ use krabmaga::engine::agent::Agent; use krabmaga::engine::location::Int2D; use krabmaga::engine::schedule::{Schedule, ScheduleOptions}; use krabmaga::engine::state::State; -use krabmaga::Rng; +use krabmaga::rand; +use krabmaga::rand::Rng; use std::hash::{Hash, Hasher}; /// The most basic agent should implement Clone, Copy and Agent to be able to be inserted in a Schedule. @@ -25,17 +26,17 @@ impl Agent for Eater { //If a free patch has been found, the agent moves inside it. //The agent then updates its state fn step(&mut self, state: &mut dyn State) { - let mut rng = krabmaga::rand::thread_rng(); + let mut rng = rand::rng(); let state = state.as_any_mut().downcast_mut::().unwrap(); if self.age == self.max_age || self.wealth <= 0 { - let rand_x = rng.gen_range(0..state.dim.0); - let rand_y = rng.gen_range(0..state.dim.1); + let rand_x = rng.random_range(0..state.dim.0); + let rand_y = rng.random_range(0..state.dim.1); let new_pos = Int2D { x: rand_x, y: rand_y, }; - let new_wealth = rng.gen_range(20..50); + let new_wealth = rng.random_range(20..50); self.position = new_pos; self.wealth = new_wealth; @@ -102,7 +103,7 @@ impl Agent for Eater { //Updates the agent state and position into the field let len = near_patches.len(); if len > 0 { - let rand = rng.gen_range(0..len); + let rand = rng.random_range(0..len); let nearest_patch = near_patches[rand].0; let nearest_pos = near_patches[rand].1; // let p = state.field.get_value(&nearest_pos).unwrap(); diff --git a/sugarscape/src/model/state.rs b/sugarscape/src/model/state.rs index 4a9a3fe..0499350 100644 --- a/sugarscape/src/model/state.rs +++ b/sugarscape/src/model/state.rs @@ -95,7 +95,7 @@ impl State for Environment { fn init(&mut self, schedule: &mut Schedule) { self.step = 0; let mut id = 0; - let mut rng = krabmaga::rand::thread_rng(); + let mut rng = krabmaga::rand::rng(); let bottom_left_mid = ( (self.dim.0 as f32 * 0.25) as i32, @@ -149,7 +149,7 @@ impl State for Environment { } let pos = Int2D { x: i, y: j }; - let sugar_growback = rng.gen_range(0..4); + let sugar_growback = rng.random_range(0..4); let patch = Patch::new(id, sugar_amount, sugar_growback); id += 1; self.field.set_value_location(patch, &pos); @@ -158,14 +158,14 @@ impl State for Environment { //Initializes the Agents for i in 0..self.num_agents { - let xx = rng.gen_range(0..self.dim.0); - let yy = rng.gen_range(0..self.dim.1); + let xx = rng.random_range(0..self.dim.0); + let yy = rng.random_range(0..self.dim.1); let pos = Int2D { x: xx, y: yy }; let agent = Eater { id: i, position: pos, - vision: rng.gen_range(1..4), - metabolism: rng.gen_range(1..4), + vision: rng.random_range(1..4), + metabolism: rng.random_range(1..4), age: 0, max_age: 20, wealth: 20, diff --git a/sugarscape/src/visualization/environment_vis.rs b/sugarscape/src/visualization/environment_vis.rs index 5c3f6d4..a3042b7 100644 --- a/sugarscape/src/visualization/environment_vis.rs +++ b/sugarscape/src/visualization/environment_vis.rs @@ -47,13 +47,13 @@ impl VisualizationState for EnvironmentVis { agent_render: &Box, state: &Box<&dyn State>, ) -> Option> { - let mut rng = krabmaga::rand::thread_rng(); + let mut rng = krabmaga::rand::rng(); let state = state.as_any().downcast_ref::().unwrap(); match state.eaters.get(&Eater { id: agent_render.get_id(), position: Int2D { - x: rng.gen_range(0..20), - y: rng.gen_range(0..20), + x: rng.random_range(0..20), + y: rng.random_range(0..20), }, vision: 4, metabolism: 50, diff --git a/template/src/model/crab.rs b/template/src/model/crab.rs index d78a7e2..1e7415b 100644 --- a/template/src/model/crab.rs +++ b/template/src/model/crab.rs @@ -22,15 +22,18 @@ impl Agent for Crab { /// Put the code that should happen for each step, for each agent here. fn step(&mut self, state: &mut dyn State) { let state = state.as_any().downcast_ref::().unwrap(); - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); - if rng.gen_bool(0.5) { + if rng.random_bool(0.5) { self.dir_x -= 1.0; } - if rng.gen_bool(0.5) { + if rng.random_bool(0.5) { self.dir_y -= 1.0; } - + self.last_d = Real2D { + x: self.dir_x, + y: self.dir_y, + }; let loc_x = toroidal_transform(self.loc.x + self.dir_x, state.field.width); let loc_y = toroidal_transform(self.loc.y + self.dir_y, state.field.height); self.loc = Real2D { x: loc_x, y: loc_y }; diff --git a/template/src/model/sea.rs b/template/src/model/sea.rs index 8dc97c2..4c1845d 100644 --- a/template/src/model/sea.rs +++ b/template/src/model/sea.rs @@ -46,16 +46,16 @@ impl State for Sea { fn init(&mut self, schedule: &mut Schedule) { self.step = 0; - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); for i in 0..self.num_agents { - let r1: f32 = rng.gen(); - let r2: f32 = rng.gen(); - let last_d = Real2D { x: 0., y: 0. }; + let r1: f32 = rng.random(); + let r2: f32 = rng.random(); let loc = Real2D { x: self.dim.0 * r1, y: self.dim.1 * r2, }; + let last_d = Real2D { x: 1.0, y: 1.0 }; let agent = Crab { id: i, loc, diff --git a/virusnetwork/src/model/node.rs b/virusnetwork/src/model/node.rs index 39f29b6..b5b7216 100644 --- a/virusnetwork/src/model/node.rs +++ b/virusnetwork/src/model/node.rs @@ -50,15 +50,15 @@ impl Agent for NetNode { NodeStatus::Infected => { if !self.virus_detected { //Scan Virus - let mut rng = rand::thread_rng(); - self.virus_detected = rng.gen_bool(VIRUS_CHECK_FREQUENCY); + let mut rng = rand::rng(); + self.virus_detected = rng.random_bool(VIRUS_CHECK_FREQUENCY); } if self.virus_detected { - let mut rng = rand::thread_rng(); - if rng.gen_bool(RECOVERY_CHANCE) { + let mut rng = rand::rng(); + if rng.random_bool(RECOVERY_CHANCE) { self.virus_detected = false; - if rng.gen_bool(GAIN_RESISTANCE_CHANCE) { + if rng.random_bool(GAIN_RESISTANCE_CHANCE) { self.status = NodeStatus::Resistant; } else { self.status = NodeStatus::Susceptible; @@ -72,10 +72,12 @@ impl Agent for NetNode { if neighborhood.is_none() { return; }; - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); let neighborhood = neighborhood.unwrap(); for edge in &neighborhood { - if rng.gen_bool(VIRUS_SPREAD_CHANCE) && self.status == NodeStatus::Susceptible { + if rng.random_bool(VIRUS_SPREAD_CHANCE) + && self.status == NodeStatus::Susceptible + { let node = state.network.get_object(edge.v).unwrap(); match node.status { NodeStatus::Infected => { diff --git a/virusnetwork/src/model/state.rs b/virusnetwork/src/model/state.rs index 099ca0a..757317a 100644 --- a/virusnetwork/src/model/state.rs +++ b/virusnetwork/src/model/state.rs @@ -42,13 +42,14 @@ impl State for EpidemicNetworkState { fn init(&mut self, schedule: &mut Schedule) { let mut node_set = Vec::new(); - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); self.reset(); for node_id in 0..self.num_nodes { - let r1: f32 = rng.gen(); - let r2: f32 = rng.gen(); + let r1: f32 = rng.random(); + let r2: f32 = rng.random(); - let init_status: NodeStatus = if rng.gen_bool(INITIAL_INFECTED_PROB) || node_id == 0 { + let init_status: NodeStatus = if rng.random_bool(INITIAL_INFECTED_PROB) || node_id == 0 + { NodeStatus::Infected } else { NodeStatus::Susceptible diff --git a/wolfsheepgrass/src/main.rs b/wolfsheepgrass/src/main.rs index 8349562..521c651 100644 --- a/wolfsheepgrass/src/main.rs +++ b/wolfsheepgrass/src/main.rs @@ -30,11 +30,11 @@ pub const MOMENTUM_PROBABILITY: f64 = 0.8; fn main() { let step = 200; - let dim: (i32, i32) = (50, 50); - let initial_animals: (u32, u32) = ((200. * 0.6) as u32, (200. * 0.4) as u32); + let dim: (i32, i32) = (5000, 5000); + let initial_animals: (u32, u32) = ((2000000. * 0.6) as u32, (2000000. * 0.4) as u32); let state = WsgState::new(dim, initial_animals); - let _ = simulate!(state, step, 10); + let _ = simulate!(state, step, 1); } #[cfg(any(feature = "visualization", feature = "visualization_wasm"))] diff --git a/wolfsheepgrass/src/model/sheep.rs b/wolfsheepgrass/src/model/sheep.rs index bad9799..52e896a 100644 --- a/wolfsheepgrass/src/model/sheep.rs +++ b/wolfsheepgrass/src/model/sheep.rs @@ -55,10 +55,10 @@ impl Agent for Sheep { //MOVE let x = self.loc.x; let y = self.loc.y; - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); let mut moved = false; - if self.last.is_some() && rng.gen_bool(MOMENTUM_PROBABILITY) { + if self.last.is_some() && rng.random_bool(MOMENTUM_PROBABILITY) { if let Some(last_loc) = self.last { let xm = x + (x - last_loc.x); let ym = y + (y - last_loc.y); @@ -78,10 +78,10 @@ impl Agent for Sheep { let ymin = if y > 0 { -1 } else { 0 }; let ymax = i32::from(y < state.dim.1 - 1); - // let nx = if rng.gen_bool(0.5) { xmin } else { xmax }; - // let ny = if rng.gen_bool(0.5) { ymin } else { ymax }; - let nx = rng.gen_range(xmin..=xmax); - let ny = rng.gen_range(ymin..=ymax); + // let nx = if rng.random_bool(0.5) { xmin } else { xmax }; + // let ny = if rng.random_bool(0.5) { ymin } else { ymax }; + let nx = rng.random_range(xmin..=xmax); + let ny = rng.random_range(ymin..=ymax); self.loc = Int2D { x: x + nx, @@ -107,7 +107,7 @@ impl Agent for Sheep { self.animal_state = LifeState::Dead; } else { //REPRODUCE - if rng.gen_bool(self.prob_reproduction) { + if rng.random_bool(self.prob_reproduction) { self.energy /= 2.0; //let mut new_id = state.next_id; diff --git a/wolfsheepgrass/src/model/state.rs b/wolfsheepgrass/src/model/state.rs index d5237ac..10c7faa 100644 --- a/wolfsheepgrass/src/model/state.rs +++ b/wolfsheepgrass/src/model/state.rs @@ -14,8 +14,7 @@ use krabmaga::engine::fields::grid_option::GridOption; use krabmaga::rand; use krabmaga::rand::Rng; use std::any::Any; -pub use std::time::Duration; -pub use std::time::Instant; +// pub use std::time::{Duration,Instant}; #[derive(Clone, Copy, PartialEq)] pub enum LifeState { @@ -208,14 +207,14 @@ impl State for WsgState { fn generate_grass(state: &mut WsgState) { (0..state.dim.1).into_iter().for_each(|x| { (0..state.dim.0).into_iter().for_each(|y| { - let mut rng = rand::thread_rng(); - let fully_growth = rng.gen_bool(0.5); + let mut rng = rand::rng(); + let fully_growth = rng.random_bool(0.5); if fully_growth { state .grass_field .set_value_location(FULL_GROWN, &Int2D { x, y }); } else { - let grass_init_value = rng.gen_range(0..FULL_GROWN + 1); + let grass_init_value = rng.random_range(0..FULL_GROWN + 1); state .grass_field .set_value_location(grass_init_value, &Int2D { x, y }); @@ -225,14 +224,14 @@ fn generate_grass(state: &mut WsgState) { } fn generate_sheep(state: &mut WsgState, schedule: &mut Schedule) { - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); for id in 0..state.initial_animals.0 { let loc = Int2D { - x: rng.gen_range(0..state.dim.0), - y: rng.gen_range(0..state.dim.1), + x: rng.random_range(0..state.dim.0), + y: rng.random_range(0..state.dim.1), }; - let init_energy = rng.gen_range(0..(2 * GAIN_ENERGY_SHEEP as usize)); + let init_energy = rng.random_range(0..(2 * GAIN_ENERGY_SHEEP as usize)); let sheep = Sheep::new( id + state.initial_animals.1, loc, @@ -247,13 +246,13 @@ fn generate_sheep(state: &mut WsgState, schedule: &mut Schedule) { } fn generate_wolves(state: &mut WsgState, schedule: &mut Schedule) { - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); for id in 0..state.initial_animals.1 { let loc = Int2D { - x: rng.gen_range(0..state.dim.0), - y: rng.gen_range(0..state.dim.1), + x: rng.random_range(0..state.dim.0), + y: rng.random_range(0..state.dim.1), }; - let init_energy = rng.gen_range(0..(2 * GAIN_ENERGY_WOLF as usize)); + let init_energy = rng.random_range(0..(2 * GAIN_ENERGY_WOLF as usize)); let wolf = Wolf::new(id, loc, init_energy as f64, GAIN_ENERGY_WOLF, WOLF_REPR); state.wolves_grid.set_object_location(wolf, &loc); diff --git a/wolfsheepgrass/src/model/wolf.rs b/wolfsheepgrass/src/model/wolf.rs index 1fdceff..0052bd1 100644 --- a/wolfsheepgrass/src/model/wolf.rs +++ b/wolfsheepgrass/src/model/wolf.rs @@ -44,7 +44,7 @@ impl Agent for Wolf { let state = state.as_any_mut().downcast_mut::().unwrap(); let x = self.loc.x; let y = self.loc.y; - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); // CHECK IF I AM DEAD if self.animal_state == LifeState::Dead { @@ -52,7 +52,7 @@ impl Agent for Wolf { } let mut moved = false; - if self.last.is_some() && rng.gen_bool(MOMENTUM_PROBABILITY) { + if self.last.is_some() && rng.random_bool(MOMENTUM_PROBABILITY) { if let Some(last_loc) = self.last { let xm = x + (x - last_loc.x); let ym = y + (y - last_loc.y); @@ -71,8 +71,8 @@ impl Agent for Wolf { let ymin = if y > 0 { -1 } else { 0 }; let ymax = i32::from(y < state.dim.1 - 1); - let nx = rng.gen_range(xmin..=xmax); - let ny = rng.gen_range(ymin..=ymax); + let nx = rng.random_range(xmin..=xmax); + let ny = rng.random_range(ymin..=ymax); self.loc = Int2D { x: x + nx, y: y + ny, @@ -103,7 +103,7 @@ impl Agent for Wolf { self.animal_state = LifeState::Dead; } else { //REPRODUCE - if rng.gen_bool(self.prob_reproduction) { + if rng.random_bool(self.prob_reproduction) { self.energy /= 2.0; let new_wolf = Wolf::new(