use crate::data::{DataSetAttributes, FieldData};
#[derive(Debug, Clone)]
pub struct Graph {
pub directed: bool,
edges: Vec<(usize, usize)>,
num_vertices: usize,
vertex_data: DataSetAttributes,
edge_data: DataSetAttributes,
field_data: FieldData,
}
impl Graph {
pub fn new_undirected() -> Self {
Self {
directed: false,
edges: Vec::new(),
num_vertices: 0,
vertex_data: DataSetAttributes::new(),
edge_data: DataSetAttributes::new(),
field_data: FieldData::new(),
}
}
pub fn new_directed() -> Self {
Self {
directed: true,
edges: Vec::new(),
num_vertices: 0,
vertex_data: DataSetAttributes::new(),
edge_data: DataSetAttributes::new(),
field_data: FieldData::new(),
}
}
pub fn add_vertex(&mut self) -> usize {
let id = self.num_vertices;
self.num_vertices += 1;
id
}
pub fn add_vertices(&mut self, count: usize) -> usize {
let first = self.num_vertices;
self.num_vertices += count;
first
}
pub fn add_edge(&mut self, source: usize, target: usize) -> usize {
let id = self.edges.len();
self.edges.push((source, target));
id
}
pub fn num_vertices(&self) -> usize {
self.num_vertices
}
pub fn num_edges(&self) -> usize {
self.edges.len()
}
pub fn edge(&self, idx: usize) -> (usize, usize) {
self.edges[idx]
}
pub fn edges(&self) -> &[(usize, usize)] {
&self.edges
}
pub fn degree(&self, vertex: usize) -> usize {
self.edges.iter().filter(|(s, t)| {
*s == vertex || (!self.directed && *t == vertex)
}).count()
}
pub fn neighbors(&self, vertex: usize) -> Vec<usize> {
let mut result = Vec::new();
for &(s, t) in &self.edges {
if s == vertex {
result.push(t);
} else if !self.directed && t == vertex {
result.push(s);
}
}
result
}
pub fn out_edges(&self, vertex: usize) -> Vec<usize> {
self.edges
.iter()
.enumerate()
.filter(|(_, (s, t))| *s == vertex || (!self.directed && *t == vertex))
.map(|(i, _)| i)
.collect()
}
pub fn adjacency_list(&self) -> Vec<Vec<usize>> {
let mut adj = vec![Vec::new(); self.num_vertices];
for &(s, t) in &self.edges {
if s < self.num_vertices {
adj[s].push(t);
}
if !self.directed && t < self.num_vertices {
adj[t].push(s);
}
}
adj
}
pub fn vertex_data(&self) -> &DataSetAttributes {
&self.vertex_data
}
pub fn vertex_data_mut(&mut self) -> &mut DataSetAttributes {
&mut self.vertex_data
}
pub fn edge_data(&self) -> &DataSetAttributes {
&self.edge_data
}
pub fn edge_data_mut(&mut self) -> &mut DataSetAttributes {
&mut self.edge_data
}
pub fn field_data(&self) -> &FieldData {
&self.field_data
}
pub fn field_data_mut(&mut self) -> &mut FieldData {
&mut self.field_data
}
}
#[derive(Debug, Clone)]
pub struct Tree {
parents: Vec<usize>,
children: Vec<Vec<usize>>,
vertex_data: DataSetAttributes,
edge_data: DataSetAttributes,
}
impl Tree {
pub fn new() -> Self {
Self {
parents: vec![usize::MAX],
children: vec![Vec::new()],
vertex_data: DataSetAttributes::new(),
edge_data: DataSetAttributes::new(),
}
}
pub fn add_child(&mut self, parent: usize) -> usize {
let id = self.parents.len();
self.parents.push(parent);
self.children.push(Vec::new());
self.children[parent].push(id);
id
}
pub fn num_nodes(&self) -> usize {
self.parents.len()
}
pub fn root(&self) -> usize {
0
}
pub fn parent(&self, node: usize) -> Option<usize> {
let p = self.parents[node];
if p == usize::MAX { None } else { Some(p) }
}
pub fn children(&self, node: usize) -> &[usize] {
&self.children[node]
}
pub fn is_leaf(&self, node: usize) -> bool {
self.children[node].is_empty()
}
pub fn depth(&self, node: usize) -> usize {
let mut d = 0;
let mut cur = node;
while self.parents[cur] != usize::MAX {
cur = self.parents[cur];
d += 1;
}
d
}
pub fn num_edges(&self) -> usize {
if self.parents.is_empty() { 0 } else { self.parents.len() - 1 }
}
pub fn leaves(&self) -> Vec<usize> {
(0..self.num_nodes()).filter(|&n| self.is_leaf(n)).collect()
}
pub fn vertex_data(&self) -> &DataSetAttributes {
&self.vertex_data
}
pub fn vertex_data_mut(&mut self) -> &mut DataSetAttributes {
&mut self.vertex_data
}
pub fn edge_data(&self) -> &DataSetAttributes {
&self.edge_data
}
pub fn edge_data_mut(&mut self) -> &mut DataSetAttributes {
&mut self.edge_data
}
}
impl Default for Tree {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn undirected_graph() {
let mut g = Graph::new_undirected();
let v0 = g.add_vertex();
let v1 = g.add_vertex();
let v2 = g.add_vertex();
g.add_edge(v0, v1);
g.add_edge(v1, v2);
assert_eq!(g.num_vertices(), 3);
assert_eq!(g.num_edges(), 2);
assert_eq!(g.degree(v1), 2);
assert_eq!(g.neighbors(v0), vec![v1]);
assert!(!g.directed);
}
#[test]
fn directed_graph() {
let mut g = Graph::new_directed();
g.add_vertices(3);
g.add_edge(0, 1);
g.add_edge(0, 2);
assert!(g.directed);
assert_eq!(g.degree(0), 2);
assert_eq!(g.degree(1), 0); assert_eq!(g.neighbors(0), vec![1, 2]);
}
#[test]
fn adjacency_list() {
let mut g = Graph::new_undirected();
g.add_vertices(4);
g.add_edge(0, 1);
g.add_edge(0, 2);
g.add_edge(2, 3);
let adj = g.adjacency_list();
assert_eq!(adj[0].len(), 2);
assert_eq!(adj[3], vec![2]);
}
#[test]
fn tree_basic() {
let mut t = Tree::new();
let c1 = t.add_child(0);
let c2 = t.add_child(0);
let c1_1 = t.add_child(c1);
assert_eq!(t.num_nodes(), 4);
assert_eq!(t.num_edges(), 3);
assert_eq!(t.root(), 0);
assert_eq!(t.parent(c1), Some(0));
assert_eq!(t.parent(0), None);
assert_eq!(t.children(0), &[c1, c2]);
assert!(t.is_leaf(c2));
assert!(!t.is_leaf(c1));
assert_eq!(t.depth(c1_1), 2);
assert_eq!(t.leaves(), vec![c2, c1_1]);
}
}