[lab3] Ant algorithm simulation
This commit is contained in:
parent
3a57dee786
commit
88a33d4a72
43
lab3/src/algo/edges.rs
Normal file
43
lab3/src/algo/edges.rs
Normal file
@ -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<usize> },
|
||||||
|
Value { data: Edge },
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EdgesVec {
|
||||||
|
storage: Vec<EdgeCell>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EdgesVec {}
|
||||||
|
|
||||||
|
impl Index<usize> 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<usize> 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
4
lab3/src/algo/mod.rs
Normal file
4
lab3/src/algo/mod.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
mod edges;
|
||||||
|
mod state;
|
||||||
|
|
||||||
|
pub use edges::EdgesVec;
|
||||||
109
lab3/src/algo/state.rs
Normal file
109
lab3/src/algo/state.rs
Normal file
@ -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<usize>,
|
||||||
|
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<HashSet<usize>>,
|
||||||
|
edges: &'a mut EdgesVec,
|
||||||
|
ants: &'a mut [Ant],
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn updateState<Rng: rand::Rng>(
|
||||||
|
state: &mut AntsSimulationState<Rng>,
|
||||||
|
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::<Vec<(usize, (usize, AntDirection), f64)>>();
|
||||||
|
|
||||||
|
let mut accumulator: f64 = allowed_outbounds
|
||||||
|
.iter()
|
||||||
|
.fold(0.0, |a, e| a + e.2)
|
||||||
|
.mul(state.rng.random::<f64>());
|
||||||
|
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()
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user