#[derive(PartialEq, Debug, Clone)]
pub struct DiNode<T> {
pub id: usize,
pub label: T,
}
pub struct Digraph<T> {
pub nodes: Vec<DiNode<T>>,
pub edges: Vec<(u32, u32)>,
}
impl<T: Clone> Digraph<T> {
pub fn new(nodes: Vec<DiNode<T>>, edges: Vec<(u32, u32)>) -> Self {
Digraph { nodes, edges }
}
pub fn successors(&self, node_id: u32) -> impl Iterator<Item = u32> + '_ {
self.edges
.iter()
.filter(move |&&(u, _)| u == node_id)
.map(|&(_, v)| v)
}
pub fn predecessors(&self, node_id: u32) -> impl Iterator<Item = u32> + '_ {
self.edges
.iter()
.filter(move |&&(_, v)| v == node_id)
.map(|&(u, _)| u)
}
pub fn node_count(&self) -> usize {
self.nodes.len()
}
pub fn edge_count(&self) -> usize {
self.edges.len()
}
}
#[cfg(test)]
mod tests {
use super::*;
fn make_node(id: usize) -> DiNode<usize> {
DiNode { id, label: id }
}
#[test]
fn test_empty_graph() {
let g: Digraph<usize> = Digraph::new(vec![], vec![]);
assert_eq!(g.node_count(), 0);
assert_eq!(g.edge_count(), 0);
assert_eq!(g.successors(0).count(), 0);
assert_eq!(g.predecessors(0).count(), 0);
}
#[test]
fn test_chain_graph() {
let g = Digraph::new(
vec![make_node(0), make_node(1), make_node(2)],
vec![(0, 1), (1, 2)],
);
let succ_a: Vec<u32> = g.successors(0).collect();
let succ_b: Vec<u32> = g.successors(1).collect();
let succ_c: Vec<u32> = g.successors(2).collect();
assert_eq!(succ_a, vec![1]);
assert_eq!(succ_b, vec![2]);
assert_eq!(succ_c, vec![]);
let pred_a: Vec<u32> = g.predecessors(0).collect();
let pred_b: Vec<u32> = g.predecessors(1).collect();
assert_eq!(pred_a, vec![]);
assert_eq!(pred_b, vec![0]);
}
#[test]
fn test_diamond_graph() {
let g = Digraph::new(
vec![make_node(0), make_node(1), make_node(2), make_node(3)],
vec![(0, 1), (0, 2), (1, 3), (2, 3)],
);
let mut succ_a: Vec<u32> = g.successors(0).collect();
succ_a.sort();
assert_eq!(succ_a, vec![1, 2]);
let mut pred_d: Vec<u32> = g.predecessors(3).collect();
pred_d.sort();
assert_eq!(pred_d, vec![1, 2]);
assert_eq!(g.predecessors(0).count(), 0);
assert_eq!(g.successors(3).count(), 0);
}
}