From 88a33d4a727e92fdd404092d07697f24c6da5ee2 Mon Sep 17 00:00:00 2001 From: Andrew Golovashevich Date: Sun, 8 Feb 2026 07:38:24 +0300 Subject: [PATCH] [lab3] Ant algorithm simulation --- lab3/src/algo/edges.rs | 43 ++++++++++++++++ lab3/src/algo/mod.rs | 4 ++ lab3/src/algo/state.rs | 109 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 lab3/src/algo/edges.rs create mode 100644 lab3/src/algo/mod.rs create mode 100644 lab3/src/algo/state.rs diff --git a/lab3/src/algo/edges.rs b/lab3/src/algo/edges.rs new file mode 100644 index 0000000..732bfbb --- /dev/null +++ b/lab3/src/algo/edges.rs @@ -0,0 +1,43 @@ +use std::ops::{Index, IndexMut}; + +pub struct Edge { + pub vertex1_index: usize, + pub vertex2_index: usize, + pub length: f64, + pub ferment_intensity: f64, +} + +enum EdgeCell { + Free { next_free_cell_id: Option }, + Value { data: Edge }, +} + +pub struct EdgesVec { + storage: Vec, +} + +impl EdgesVec {} + +impl Index for EdgesVec { + type Output = Edge; + + fn index(&self, index: usize) -> &Self::Output { + match self.storage.get(index).expect("Edge index out of bounds") { + EdgeCell::Free { .. } => panic!("Referenced edge doesn't exists"), + EdgeCell::Value { data } => return data, + } + } +} + +impl IndexMut for EdgesVec { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + match self + .storage + .get_mut(index) + .expect("Edge index out of bounds") + { + EdgeCell::Free { .. } => panic!("Referenced edge doesn't exists"), + EdgeCell::Value { data } => return data, + } + } +} diff --git a/lab3/src/algo/mod.rs b/lab3/src/algo/mod.rs new file mode 100644 index 0000000..b280f2d --- /dev/null +++ b/lab3/src/algo/mod.rs @@ -0,0 +1,4 @@ +mod edges; +mod state; + +pub use edges::EdgesVec; \ No newline at end of file diff --git a/lab3/src/algo/state.rs b/lab3/src/algo/state.rs new file mode 100644 index 0000000..9eb6a67 --- /dev/null +++ b/lab3/src/algo/state.rs @@ -0,0 +1,109 @@ +use crate::algo::EdgesVec; +use std::collections::HashSet; +use std::ops::Mul; + +#[derive(Clone, Copy)] +pub enum AntDirection { + ToSecond, + ToFirst, +} + +pub struct Ant { + allowed_vertices: HashSet, + location: AntLocation, +} + +pub enum AntLocation { + OnEdge { + edge_index: usize, + offset: u16, + direction: AntDirection, + }, + OnVertex { + vertex_index: usize, + }, +} + +pub struct AntsSimulationState<'a, Rng: rand::Rng> { + rng: Rng, + vertices: &'a Vec>, + edges: &'a mut EdgesVec, + ants: &'a mut [Ant], +} + +pub fn updateState( + state: &mut AntsSimulationState, + ferment_weight: f64, + heuristic_coefficient: f64, + q: f64, + r: f64, + speed: u16, +) -> bool { + let mut finished_ants_count = 0usize; + for ant in state.ants.iter_mut() { + match &mut ant.location { + AntLocation::OnEdge { + edge_index, + offset, + direction, + } => match offset.checked_add(speed) { + Some(newOffset) => *offset = newOffset, + None => { + let edge = &mut state.edges[*edge_index]; + edge.ferment_intensity += (q / edge.length) * r; + let vertex_index; + match direction { + AntDirection::ToSecond => vertex_index = edge.vertex2_index, + AntDirection::ToFirst => vertex_index = edge.vertex1_index, + } + ant.location = AntLocation::OnVertex { vertex_index } + } + }, + AntLocation::OnVertex { vertex_index } => { + let allowed_outbounds = state.vertices[*vertex_index] + .iter() + .map(|ei| (*ei, &state.edges[*ei])) + .map(|(ei, e)| { + if *vertex_index == e.vertex1_index { + return (ei, e, e.vertex2_index, AntDirection::ToSecond); + } else { + return (ei, e, e.vertex1_index, AntDirection::ToFirst); + } + }) + .filter(|e| ant.allowed_vertices.contains(&e.2)) + .map(|e| { + return ( + e.0, + (e.2, e.3), + e.1.ferment_intensity.powf(ferment_weight) + * (1.0 / e.1.length).powf(heuristic_coefficient), + ); + }) + .collect::>(); + + let mut accumulator: f64 = allowed_outbounds + .iter() + .fold(0.0, |a, e| a + e.2) + .mul(state.rng.random::()); + let target_vertex_index = allowed_outbounds.iter().find(|e| { + accumulator -= e.2; + return accumulator <= 0.0; + }); + + match target_vertex_index { + None => finished_ants_count += 1, + Some((ei, (vi, dir), _)) => { + ant.allowed_vertices.remove(vi); + ant.location = AntLocation::OnEdge { + edge_index: *ei, + offset: 0, + direction: *dir + } + } + }; + } + } + } + + return finished_ants_count == state.ants.len() +}