mirror of
https://github.com/aziis98/asd-2024.git
synced 2026-10-06 14:44:59 +00:00
chore: cleaned up graphs
This commit is contained in:
+5
-204
@@ -5,7 +5,7 @@ use std::{
|
||||
fmt::Debug,
|
||||
};
|
||||
|
||||
use indicatif::{ProgressBar, ProgressIterator};
|
||||
use indicatif::ProgressIterator;
|
||||
|
||||
use super::{AdjacencyGraph, Graph, UndirectedGraph};
|
||||
|
||||
@@ -14,51 +14,6 @@ impl<V> AdjacencyGraph<V>
|
||||
where
|
||||
V: Ord + Eq + Clone + Debug,
|
||||
{
|
||||
// pub fn new() -> Self {
|
||||
// AdjacencyGraph {
|
||||
// nodes: BTreeSet::new(),
|
||||
// adjacencies: BTreeMap::new(),
|
||||
// }
|
||||
// }
|
||||
|
||||
// pub fn add_node(&mut self, node: V) {
|
||||
// self.nodes.insert(node);
|
||||
// }
|
||||
|
||||
// pub fn add_edge(&mut self, from: V, to: V) {
|
||||
// self.add_node(from.clone());
|
||||
// self.add_node(to.clone());
|
||||
|
||||
// self.adjacencies
|
||||
// .entry(from)
|
||||
// .or_insert_with(BTreeSet::new)
|
||||
// .insert(to);
|
||||
// }
|
||||
|
||||
// pub fn remove_edge(&mut self, from: &V, to: &V) {
|
||||
// if let Some(adjacencies) = self.adjacencies.get_mut(from) {
|
||||
// adjacencies.remove(to);
|
||||
// }
|
||||
// }
|
||||
|
||||
// pub fn get_adjacencies(&self, node: &V) -> Option<&BTreeSet<V>> {
|
||||
// self.adjacencies.get(node)
|
||||
// }
|
||||
|
||||
// pub fn adjacencies(&self) -> &BTreeMap<V, BTreeSet<V>> {
|
||||
// &self.adjacencies
|
||||
// }
|
||||
|
||||
// pub fn nodes(&self) -> &BTreeSet<V> {
|
||||
// &self.nodes
|
||||
// }
|
||||
|
||||
// pub fn edges(&self) -> impl Iterator<Item = (&V, &V)> {
|
||||
// self.adjacencies
|
||||
// .iter()
|
||||
// .flat_map(|(from, tos)| tos.iter().map(move |to| (from, to)))
|
||||
// }
|
||||
|
||||
pub fn opposite(&self) -> AdjacencyGraph<V> {
|
||||
let mut opposite = AdjacencyGraph::new();
|
||||
|
||||
@@ -103,25 +58,6 @@ where
|
||||
self.neighbors(from).contains(to)
|
||||
}
|
||||
|
||||
// pub fn dfs<'a>(&'a self, node: &'a V) -> impl Iterator<Item = V> + 'a {
|
||||
// let mut visited = BTreeSet::new();
|
||||
// let mut stack = VecDeque::from([node]);
|
||||
|
||||
// std::iter::from_fn(move || {
|
||||
// while let Some(node) = stack.pop_back() {
|
||||
// if !visited.insert(node.clone()) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// stack.extend(self.neighbors(node).iter());
|
||||
|
||||
// return Some(node.clone());
|
||||
// }
|
||||
|
||||
// None
|
||||
// })
|
||||
// }
|
||||
|
||||
pub fn shortest_path_matrix(&self) -> BTreeMap<V, BTreeMap<V, usize>> {
|
||||
let mut result = BTreeMap::new();
|
||||
|
||||
@@ -161,17 +97,9 @@ where
|
||||
|
||||
let op = self.opposite();
|
||||
|
||||
for node in self
|
||||
.nodes
|
||||
.iter()
|
||||
.progress()
|
||||
.with_style(
|
||||
indicatif::ProgressStyle::default_bar()
|
||||
.template("{prefix} {spinner} [{elapsed_precise}] [{wide_bar}] {pos}/{len}")
|
||||
.unwrap(),
|
||||
)
|
||||
.with_prefix("computing connected components")
|
||||
{
|
||||
println!("Computing connected components...");
|
||||
|
||||
for node in self.nodes.iter().progress() {
|
||||
if visited.contains(node) {
|
||||
continue;
|
||||
}
|
||||
@@ -202,7 +130,7 @@ where
|
||||
result
|
||||
}
|
||||
|
||||
fn gc(&mut self) {
|
||||
pub fn gc(&mut self) {
|
||||
let mut to_remove = Vec::new();
|
||||
|
||||
for node in self.nodes.iter() {
|
||||
@@ -217,130 +145,3 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> UndirectedGraph<V>
|
||||
where
|
||||
V: Ord + Eq + Clone + Debug,
|
||||
{
|
||||
pub fn add_edge(&mut self, from: V, to: V) {
|
||||
self.directed.add_edge(from.clone(), to.clone());
|
||||
self.directed.add_edge(to.clone(), from.clone());
|
||||
}
|
||||
|
||||
pub fn remove_edge(&mut self, from: &V, to: &V) {
|
||||
self.directed.remove_edge(from, to);
|
||||
self.directed.remove_edge(to, from);
|
||||
}
|
||||
|
||||
pub fn connected_components(&self) -> Vec<Vec<V>> {
|
||||
let mut visited = BTreeSet::new();
|
||||
let mut result = Vec::new();
|
||||
|
||||
let pb = ProgressBar::new(self.directed.nodes.len() as u64);
|
||||
|
||||
for node in self.directed.nodes.iter() {
|
||||
if visited.contains(node) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut cc: BTreeSet<V> = BTreeSet::new();
|
||||
let mut stack: Vec<V> = vec![node.clone()];
|
||||
|
||||
while let Some(node) = stack.pop() {
|
||||
if cc.contains(&node) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pb.inc(1);
|
||||
cc.insert(node.clone());
|
||||
|
||||
for adj in self.neighbors(&node) {
|
||||
stack.push(adj);
|
||||
}
|
||||
}
|
||||
|
||||
visited.extend(cc.iter().map(|x| x.to_owned()));
|
||||
result.push(cc.iter().map(|x| x.to_owned()).collect());
|
||||
}
|
||||
|
||||
pb.finish();
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
// This runs a depth-first search on the graph searching for o--o--o paths and removes the middle node
|
||||
// recursively until no more o--o--o paths are found.
|
||||
pub fn compact_chains(&mut self) {
|
||||
let mut visited = BTreeSet::new();
|
||||
|
||||
let nodes = self.directed.nodes.clone();
|
||||
|
||||
let pb = ProgressBar::new(nodes.len() as u64);
|
||||
|
||||
let mut compacted_count = 0;
|
||||
|
||||
for node in nodes {
|
||||
if visited.contains(&node) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut stack = vec![node];
|
||||
|
||||
while let Some(node) = stack.pop() {
|
||||
if visited.contains(&node) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pb.inc(1);
|
||||
visited.insert(node.clone());
|
||||
|
||||
// while adj has only one neighbor
|
||||
let mut curr = node;
|
||||
let mut path = vec![curr.clone()];
|
||||
|
||||
loop {
|
||||
let adjacencies = self.neighbors(&curr);
|
||||
if adjacencies.is_empty() {
|
||||
break;
|
||||
}
|
||||
|
||||
let probes = adjacencies
|
||||
.iter()
|
||||
.filter(|&x| !path.contains(x))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if probes.len() != 1 {
|
||||
break;
|
||||
}
|
||||
|
||||
curr = probes[0].clone();
|
||||
|
||||
visited.insert(curr.clone());
|
||||
path.push(curr.clone());
|
||||
}
|
||||
|
||||
if path.len() < 3 {
|
||||
continue;
|
||||
}
|
||||
|
||||
path.windows(2).for_each(|x| {
|
||||
self.remove_edge(&x[0], &x[1]);
|
||||
});
|
||||
|
||||
self.add_edge(path[0].clone(), path[path.len() - 1].clone());
|
||||
|
||||
compacted_count += path.len() - 2;
|
||||
|
||||
for adj in self.neighbors(&curr) {
|
||||
stack.push(adj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("Compacted {} nodes", compacted_count);
|
||||
|
||||
self.directed.gc();
|
||||
|
||||
pb.finish();
|
||||
}
|
||||
}
|
||||
|
||||
+133
-1
@@ -1,4 +1,9 @@
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::{
|
||||
collections::{BTreeMap, BTreeSet},
|
||||
fmt::Debug,
|
||||
};
|
||||
|
||||
use indicatif::ProgressBar;
|
||||
|
||||
use super::{AdjacencyGraph, Graph, UndirectedGraph};
|
||||
|
||||
@@ -53,3 +58,130 @@ where
|
||||
self.directed.remove_edge(to, from);
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> UndirectedGraph<V>
|
||||
where
|
||||
V: Ord + Eq + Clone + Debug,
|
||||
{
|
||||
pub fn add_edge(&mut self, from: V, to: V) {
|
||||
self.directed.add_edge(from.clone(), to.clone());
|
||||
self.directed.add_edge(to.clone(), from.clone());
|
||||
}
|
||||
|
||||
pub fn remove_edge(&mut self, from: &V, to: &V) {
|
||||
self.directed.remove_edge(from, to);
|
||||
self.directed.remove_edge(to, from);
|
||||
}
|
||||
|
||||
pub fn connected_components(&self) -> Vec<Vec<V>> {
|
||||
let mut visited = BTreeSet::new();
|
||||
let mut result = Vec::new();
|
||||
|
||||
let pb = ProgressBar::new(self.directed.nodes.len() as u64);
|
||||
|
||||
for node in self.directed.nodes.iter() {
|
||||
if visited.contains(node) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut cc: BTreeSet<V> = BTreeSet::new();
|
||||
let mut stack: Vec<V> = vec![node.clone()];
|
||||
|
||||
while let Some(node) = stack.pop() {
|
||||
if cc.contains(&node) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pb.inc(1);
|
||||
cc.insert(node.clone());
|
||||
|
||||
for adj in self.neighbors(&node) {
|
||||
stack.push(adj);
|
||||
}
|
||||
}
|
||||
|
||||
visited.extend(cc.iter().map(|x| x.to_owned()));
|
||||
result.push(cc.iter().map(|x| x.to_owned()).collect());
|
||||
}
|
||||
|
||||
pb.finish();
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
// This runs a depth-first search on the graph searching for o--o--o paths and removes the middle node
|
||||
// recursively until no more o--o--o paths are found.
|
||||
pub fn compact_chains(&mut self) {
|
||||
let mut visited = BTreeSet::new();
|
||||
|
||||
let nodes = self.directed.nodes.clone();
|
||||
|
||||
let pb = ProgressBar::new(nodes.len() as u64);
|
||||
|
||||
let mut compacted_count = 0;
|
||||
|
||||
for node in nodes {
|
||||
if visited.contains(&node) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut stack = vec![node];
|
||||
|
||||
while let Some(node) = stack.pop() {
|
||||
if visited.contains(&node) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pb.inc(1);
|
||||
visited.insert(node.clone());
|
||||
|
||||
// while adj has only one neighbor
|
||||
let mut curr = node;
|
||||
let mut path = vec![curr.clone()];
|
||||
|
||||
loop {
|
||||
let adjacencies = self.neighbors(&curr);
|
||||
if adjacencies.is_empty() {
|
||||
break;
|
||||
}
|
||||
|
||||
let probes = adjacencies
|
||||
.iter()
|
||||
.filter(|&x| !path.contains(x))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if probes.len() != 1 {
|
||||
break;
|
||||
}
|
||||
|
||||
curr = probes[0].clone();
|
||||
|
||||
visited.insert(curr.clone());
|
||||
path.push(curr.clone());
|
||||
}
|
||||
|
||||
if path.len() < 3 {
|
||||
continue;
|
||||
}
|
||||
|
||||
path.windows(2).for_each(|x| {
|
||||
self.remove_edge(&x[0], &x[1]);
|
||||
});
|
||||
|
||||
self.add_edge(path[0].clone(), path[path.len() - 1].clone());
|
||||
|
||||
compacted_count += path.len() - 2;
|
||||
|
||||
for adj in self.neighbors(&curr) {
|
||||
stack.push(adj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("Compacted {} nodes", compacted_count);
|
||||
|
||||
self.directed.gc();
|
||||
|
||||
pb.finish();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user