[lab3] Extracted add/remove vertex to complex graph

This commit is contained in:
Andrew Golovashevich 2026-02-16 00:29:27 +03:00
parent 178007edee
commit ed55515d26
7 changed files with 110 additions and 88 deletions

View File

@ -1,8 +1,8 @@
use super::EdgesVec; use super::{EdgeExtraData, EdgesVec};
use rand::Rng; use rand::Rng;
use std::collections::HashSet; use std::collections::HashSet;
use std::ops::Mul; use std::ops::Mul;
use bgtu_ai_utility::graph::VerticesVec; use bgtu_ai_utility::graph::{CompleteGraph, VerticesVec};
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum AntDirection { pub enum AntDirection {
@ -40,8 +40,7 @@ pub enum AntLocation {
} }
pub struct AntsSimulationState { pub struct AntsSimulationState {
pub vertices: VerticesVec, pub graph: CompleteGraph<EdgeExtraData>,
pub edges: EdgesVec,
pub ants: Vec<Ant>, pub ants: Vec<Ant>,
} }
@ -74,7 +73,7 @@ fn _updateState(
offset, offset,
direction, direction,
} => { } => {
let edge = &mut state.edges[*edge_index]; let edge = &mut state.graph.edges[*edge_index];
edge.extra.ferment_intensity += (cfg.q / edge.length) * cfg.r; edge.extra.ferment_intensity += (cfg.q / edge.length) * cfg.r;
let vertex_index; let vertex_index;
match direction { match direction {
@ -84,9 +83,9 @@ fn _updateState(
ant.location = AntLocation::OnVertex { vertex_index } ant.location = AntLocation::OnVertex { vertex_index }
} }
AntLocation::OnVertex { vertex_index } => { AntLocation::OnVertex { vertex_index } => {
let allowed_outbounds = state.vertices[*vertex_index] let allowed_outbounds = state.graph.vertices[*vertex_index]
.iter() .iter()
.map(|ei| (*ei, &state.edges[*ei])) .map(|ei| (*ei, &state.graph.edges[*ei]))
.map(|(ei, e)| { .map(|(ei, e)| {
if *vertex_index == e.vertex1_index { if *vertex_index == e.vertex1_index {
return (ei, e, e.vertex2_index, AntDirection::ToSecond); return (ei, e, e.vertex2_index, AntDirection::ToSecond);

View File

@ -3,22 +3,22 @@
mod algo; mod algo;
use crate::algo::{ use crate::algo::{
updateState, Ant, AntsSimulationConfig, AntsSimulationState, EdgeExtraData, EdgesVec, Ant, AntsSimulationConfig, AntsSimulationState, EdgeExtraData, EdgesVec, VerticesVec,
VerticesVec, updateState,
}; };
use bgtu_ai_utility::gui::lengths_table::{draw_lengths_table}; use bgtu_ai_utility::UpdatePending;
use bgtu_ai_utility::gui::lengths_table::draw_lengths_table;
use bgtu_ai_utility::gui::render::render_graph; use bgtu_ai_utility::gui::render::render_graph;
use bgtu_ai_utility::gui::{boot_eframe, labeled_slider}; use bgtu_ai_utility::gui::{boot_eframe, labeled_slider};
use eframe::egui; use eframe::egui;
use eframe::egui::{Frame, Ui}; use eframe::egui::{Frame, Ui};
use std::collections::HashSet; use std::collections::HashSet;
use bgtu_ai_utility::UpdatePending; use bgtu_ai_utility::graph::CompleteGraph;
fn main() -> eframe::Result { fn main() -> eframe::Result {
return boot_eframe(|| MyApp::new()); return boot_eframe(|| MyApp::new());
} }
enum GlobalState { enum GlobalState {
Edit, Edit,
Running, Running,
@ -37,8 +37,7 @@ impl MyApp {
fn new() -> Self { fn new() -> Self {
return Self { return Self {
simulation: AntsSimulationState { simulation: AntsSimulationState {
edges: EdgesVec::new(), graph: CompleteGraph::new(),
vertices: VerticesVec::new(),
ants: Vec::new(), ants: Vec::new(),
}, },
vertex_update: UpdatePending::NoChange, vertex_update: UpdatePending::NoChange,
@ -55,7 +54,6 @@ impl MyApp {
} }
} }
impl eframe::App for MyApp { impl eframe::App for MyApp {
fn update(&mut self, ui: &eframe::egui::Context, _frame: &mut eframe::Frame) { fn update(&mut self, ui: &eframe::egui::Context, _frame: &mut eframe::Frame) {
egui::CentralPanel::default().show(ui, |ui| match self.state { egui::CentralPanel::default().show(ui, |ui| match self.state {
@ -63,37 +61,13 @@ impl eframe::App for MyApp {
match self.vertex_update { match self.vertex_update {
UpdatePending::NoChange => {} UpdatePending::NoChange => {}
UpdatePending::Add => { UpdatePending::Add => {
let new_vi = self.simulation.vertices.add(HashSet::new()); self.simulation.graph.add_vertex(|| EdgeExtraData {
let mut newEdgesSet = HashSet::new(); ferment_intensity: 0.0,
for (vi, v) in self.simulation.vertices.iter_indexed_mut() { });
if (vi == new_vi) {
continue;
}
let ei = self.simulation.edges.add(
new_vi,
vi,
1.0,
EdgeExtraData {
ferment_intensity: 0.0,
},
);
newEdgesSet.insert(ei);
v.insert(ei);
}
self.simulation.vertices[new_vi] = newEdgesSet;
self.vertex_update = UpdatePending::NoChange; self.vertex_update = UpdatePending::NoChange;
} }
UpdatePending::Remove(vi) => { UpdatePending::Remove(vi) => {
let mut eis = Vec::with_capacity(self.simulation.vertices[vi].len()); self.simulation.graph.remove_vertex(vi);
for ei in self.simulation.vertices[vi].iter() {
eis.push(*ei)
}
for ei in eis {
self.simulation.vertices[self.simulation.edges[ei].another(vi)]
.remove(&ei);
self.simulation.edges.remove(ei);
}
self.simulation.vertices.remove(vi);
self.vertex_update = UpdatePending::NoChange; self.vertex_update = UpdatePending::NoChange;
} }
} }
@ -159,15 +133,15 @@ fn edit_panel(data: &mut MyApp, ui: &mut Ui) {
draw_lengths_table( draw_lengths_table(
ui, ui,
&mut data.simulation.vertices, &mut data.simulation.graph.vertices,
&mut data.simulation.edges, &mut data.simulation.graph.edges,
&mut data.vertex_update, &mut data.vertex_update,
); );
if run { if run {
let mut coords = vec![(0.0, 0.0); data.simulation.vertices.capacity()]; let mut coords = vec![(0.0, 0.0); data.simulation.graph.vertices.capacity()];
for (i, _) in data.simulation.vertices.iter_indexed() { for (i, _) in data.simulation.graph.vertices.iter_indexed() {
coords[i] = ( coords[i] = (
rand::random::<f32>() * 0.8 + 0.1, rand::random::<f32>() * 0.8 + 0.1,
rand::random::<f32>() * 0.8 + 0.1, rand::random::<f32>() * 0.8 + 0.1,
@ -179,13 +153,13 @@ fn edit_panel(data: &mut MyApp, ui: &mut Ui) {
let allowed_locations = data let allowed_locations = data
.simulation .simulation
.vertices .graph.vertices
.iter_indexed() .iter_indexed()
.map(|(i, _)| i) .map(|(i, _)| i)
.collect::<HashSet<usize>>(); .collect::<HashSet<usize>>();
let mut ants = Vec::new(); let mut ants = Vec::new();
for (i, _) in data.simulation.vertices.iter_indexed() { for (i, _) in data.simulation.graph.vertices.iter_indexed() {
for _ in 0..data.ants_per_vertex { for _ in 0..data.ants_per_vertex {
ants.push(Ant::new(i, allowed_locations.clone())) ants.push(Ant::new(i, allowed_locations.clone()))
} }
@ -218,7 +192,7 @@ fn draw_ants(data: &mut MyApp, ui: &mut Ui) {
for w in data for w in data
.simulation .simulation
.edges .graph.edges
.iter() .iter()
.map(|e| e.extra.ferment_intensity) .map(|e| e.extra.ferment_intensity)
{ {
@ -229,9 +203,9 @@ fn draw_ants(data: &mut MyApp, ui: &mut Ui) {
render_graph( render_graph(
ui, ui,
&data.simulation.vertices, &data.simulation.graph.vertices,
data.vertex_locations.as_mut_slice(), data.vertex_locations.as_mut_slice(),
&data.simulation.edges, &data.simulation.graph.edges,
|e| e.extra.ferment_intensity / cap, |e| e.extra.ferment_intensity / cap,
) )
} }

View File

@ -23,17 +23,23 @@ impl<T> _PreserveIndexVec<T> {
return self.len; return self.len;
} }
pub fn add(&mut self, value: T) -> usize { pub fn add(&mut self, constructor: impl FnOnce(&mut Self, usize) -> T) -> usize {
match self.next_free { match self.next_free {
None => { None => {
self.buffer.push(Cell::Value { value }); let cell = Cell::Value {
value: constructor(self, self.len),
};
self.buffer.push(cell);
self.len += 1; self.len += 1;
return self.buffer.len() - 1; return self.buffer.len() - 1;
} }
Some(i) => match self.buffer[i] { Some(i) => match self.buffer[i] {
Cell::Free { next_free_cell_id } => { Cell::Free { next_free_cell_id } => {
self.next_free = next_free_cell_id; self.next_free = next_free_cell_id;
self.buffer[i] = Cell::Value { value }; let cell = Cell::Value {
value: constructor(self, i),
};
self.buffer[i] = cell;
self.len += 1; self.len += 1;
return i; return i;
} }
@ -55,41 +61,36 @@ impl<T> _PreserveIndexVec<T> {
} }
} }
pub fn iter(&self) -> impl Iterator<Item = &T> {
pub fn iter(&self) -> impl Iterator<Item=&T>{ return self.buffer.iter().filter_map(|c| match c {
return self.buffer.iter().filter_map(|c| { Cell::Free { .. } => return None,
match c { Cell::Value { value } => return Some(value),
Cell::Free { .. } => return None, });
Cell::Value { value } => return Some(value)
}
})
} }
pub fn iter_mut(&mut self) -> impl Iterator<Item=&mut T>{ pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
return self.buffer.iter_mut().filter_map(|c| { return self.buffer.iter_mut().filter_map(|c| match c {
match c { Cell::Free { .. } => return None,
Cell::Free { .. } => return None, Cell::Value { value } => return Some(value),
Cell::Value { value } => return Some(value) });
}
})
} }
pub fn iter_indexed(&self) -> impl Iterator<Item=(usize, &T)>{ pub fn iter_indexed(&self) -> impl Iterator<Item = (usize, &T)> {
return self.buffer.iter().enumerate().filter_map(|(i, c)| { return self.buffer.iter().enumerate().filter_map(|(i, c)| match c {
match c { Cell::Free { .. } => return None,
Cell::Free { .. } => return None, Cell::Value { value } => return Some((i, value)),
Cell::Value { value } => return Some((i, value)) });
}
})
} }
pub fn iter_indexed_mut(&mut self) -> impl Iterator<Item=(usize, &mut T)>{ pub fn iter_indexed_mut(&mut self) -> impl Iterator<Item = (usize, &mut T)> {
return self.buffer.iter_mut().enumerate().filter_map(|(i, c)| { return self
match c { .buffer
.iter_mut()
.enumerate()
.filter_map(|(i, c)| match c {
Cell::Free { .. } => return None, Cell::Free { .. } => return None,
Cell::Value { value } => return Some((i, value)) Cell::Value { value } => return Some((i, value)),
} });
})
} }
pub fn capacity(&self) -> usize { pub fn capacity(&self) -> usize {
@ -120,4 +121,3 @@ impl<T> IndexMut<usize> for _PreserveIndexVec<T> {
} }
} }
} }

View File

@ -0,0 +1,39 @@
use super::{EdgesVec, VerticesVec};
use std::collections::HashSet;
pub struct CompleteGraph<E> {
pub vertices: VerticesVec,
pub edges: EdgesVec<E>,
}
impl<E> CompleteGraph<E> {
pub fn new() -> Self {
return Self {
vertices: VerticesVec::new(),
edges: EdgesVec::new(),
};
}
}
impl<E> CompleteGraph<E> {
pub fn add_vertex(&mut self, edge_constructor: impl Fn() -> E) {
self.vertices.add(|vertices, new_vi| {
let mut new_edges_set = HashSet::new();
for (vi, v) in vertices {
let ei = self.edges.add(new_vi, vi, 1.0, edge_constructor());
new_edges_set.insert(ei);
v.insert(ei);
}
return new_edges_set;
});
}
pub fn remove_vertex(&mut self, vi: usize) {
for ei in self.vertices[vi].iter().map(|i| *i).collect::<Vec<usize>>() {
self.vertices[self.edges[ei].another(vi)].remove(&ei);
self.edges.remove(ei);
}
self.vertices.remove(vi);
}
}

View File

@ -38,7 +38,7 @@ impl<D> EdgesVec<D> {
length, length,
extra extra
}; };
return self.data.add(data); return self.data.add(|_, _| data);
} }
pub fn remove(&mut self, edge_index: usize) { pub fn remove(&mut self, edge_index: usize) {

View File

@ -1,7 +1,9 @@
mod _preserve_index_vec; mod _preserve_index_vec;
mod complete_graph;
pub mod edges; pub mod edges;
pub mod vertices; pub mod vertices;
use _preserve_index_vec::_PreserveIndexVec; use _preserve_index_vec::_PreserveIndexVec;
pub use complete_graph::CompleteGraph;
pub use edges::{Edge, EdgesVec}; pub use edges::{Edge, EdgesVec};
pub use vertices::VerticesVec; pub use vertices::VerticesVec;

View File

@ -16,8 +16,16 @@ impl VerticesVec {
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
return self.data.len(); return self.data.len();
} }
pub fn add(&mut self, edges: HashSet<usize>) -> usize { pub fn add(
return self.data.add(edges); &mut self,
edges_constructor: impl FnOnce(
&mut dyn Iterator<Item = (usize, &mut HashSet<usize>)>,
usize,
) -> HashSet<usize>,
) -> usize {
return self
.data
.add(|r, x| edges_constructor(&mut r.iter_indexed_mut(), x));
} }
pub fn remove(&mut self, edge_index: usize) { pub fn remove(&mut self, edge_index: usize) {
@ -35,7 +43,7 @@ impl VerticesVec {
} }
pub fn capacity(&self) -> usize { pub fn capacity(&self) -> usize {
return self.data.capacity() return self.data.capacity();
} }
} }