From 2c964737bca11698dffd17a8e4680bdce95a163e Mon Sep 17 00:00:00 2001 From: sigil-03 Date: Sun, 25 May 2025 11:14:29 -0600 Subject: [PATCH] support degree calculation --- src/graph.rs | 3 -- src/test.rs | 105 +++++++++++++++++++++++++++++++++++--------------- src/vertex.rs | 3 ++ 3 files changed, 77 insertions(+), 34 deletions(-) diff --git a/src/graph.rs b/src/graph.rs index c98238e..fe8f3a2 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -12,7 +12,4 @@ pub trait Graph { // disconnect two nodes, and return the old edge // fn disconnect(vertex_1: &V, vertex_2: &V) -> E; fn disconnect(&mut self, edge: E::HANDLE); - - // get the degree of a given vertex - possibly put this in a GraphUtil trait? - fn degree(vertex: V::HANDLE) -> usize; } diff --git a/src/test.rs b/src/test.rs index 2babfde..efa7120 100644 --- a/src/test.rs +++ b/src/test.rs @@ -1,4 +1,4 @@ -use std::marker::PhantomData; +use std::collections::{HashMap, HashSet}; use crate::{edge::Edge, graph::Graph, vertex::Vertex}; @@ -14,6 +14,7 @@ impl Edge for SimpleEdge { struct SimpleVertex { id: usize, + edges: HashSet<::HANDLE>, } impl SimpleVertex { @@ -24,18 +25,25 @@ impl SimpleVertex { impl Vertex for SimpleVertex { type HANDLE = usize; + + fn degree(&self) -> usize { + return self.edges.len(); + } } struct SimpleGraph { - vertices: Vec, - edges: Vec, + vertices: HashMap, + edges: HashMap, } impl SimpleGraph { pub fn new_vertex(&mut self) -> ::HANDLE { let id = self.vertices.len(); - let v = SimpleVertex { id: id.clone() }; - self.vertices.push(v); + let v = SimpleVertex { + id: id.clone(), + edges: HashSet::new(), + }; + self.vertices.insert(id, v); id } } @@ -43,63 +51,98 @@ impl SimpleGraph { impl<'a> Graph for SimpleGraph { fn connect(&mut self, vertex_1: usize, vertex_2: usize) -> usize { let id = self.edges.len(); - self.edges.push(SimpleEdge { - id: id.clone(), - v1: vertex_1, - v2: vertex_2, - }); + + // create the edge + self.edges.insert( + id, + SimpleEdge { + id: id.clone(), + v1: vertex_1, + v2: vertex_2, + }, + ); + + // add the edge handle to each vertex + if let Some(v) = self.vertices.get_mut(&vertex_1) { + v.edges.insert(id); + } + if let Some(v) = self.vertices.get_mut(&vertex_2) { + v.edges.insert(id); + } + id } // NOTE: this should probably be a failable function... and use a hashmap fn disconnect(&mut self, edge: usize) { - for i in (0..self.edges.len()) { - if self.edges[i].id == edge { - self.edges.remove(i); - return; + // TODO: handle unhappy path + if let Some(e) = self.edges.remove(&edge) { + // remove the edge handle from each vertex + if let Some(v) = self.vertices.get_mut(&e.v1) { + v.edges.remove(&e.id); + } + if let Some(v) = self.vertices.get_mut(&e.v2) { + v.edges.remove(&e.id); } } } - - fn degree(vertex: usize) -> usize { - todo!(); - } } #[test] fn simple_connect() { let mut g = SimpleGraph { - vertices: Vec::new(), - edges: Vec::new(), + vertices: HashMap::new(), + edges: HashMap::new(), }; let h1 = g.new_vertex(); let h2 = g.new_vertex(); - let _e = g.connect(h1, h2); + assert_eq!(g.vertices.len(), 2); + + let e = g.connect(h1, h2); assert_eq!(g.edges.len(), 1); - assert_eq!(g.edges[0].id, 0); - assert_eq!(g.edges[0].v1, h1); - assert_eq!(g.edges[0].v2, h2); + + let e = g.edges.get(&e).unwrap(); + assert_eq!(e.id, 0); + assert_eq!(e.v1, h1); + assert_eq!(e.v2, h2); } #[test] fn simple_disconnect() { let mut g = SimpleGraph { - vertices: Vec::new(), - edges: Vec::new(), + vertices: HashMap::new(), + edges: HashMap::new(), }; let h1 = g.new_vertex(); let h2 = g.new_vertex(); + assert_eq!(g.vertices.len(), 2); + let e = g.connect(h1, h2); assert_eq!(g.edges.len(), 1); - assert_eq!(g.edges[0].id, 0); - assert_eq!(g.edges[0].v1, h1); - assert_eq!(g.edges[0].v2, h2); - g.disconnect(e); + let e = g.edges.get(&e).unwrap(); + assert_eq!(e.id, 0); + assert_eq!(e.v1, h1); + assert_eq!(e.v2, h2); + + g.disconnect(e.id); assert_eq!(g.edges.len(), 0); } #[test] fn simple_degree() { - todo!() + let mut g = SimpleGraph { + vertices: HashMap::new(), + edges: HashMap::new(), + }; + let h1 = g.new_vertex(); + let h2 = g.new_vertex(); + let h3 = g.new_vertex(); + + let e1 = g.connect(h1, h2); + let e2 = g.connect(h1, h3); + + assert_eq!(g.vertices.get(&h1).unwrap().degree(), 2); + assert_eq!(g.vertices.get(&h2).unwrap().degree(), 1); + assert_eq!(g.vertices.get(&h3).unwrap().degree(), 1); } diff --git a/src/vertex.rs b/src/vertex.rs index 9ad334b..d68819f 100644 --- a/src/vertex.rs +++ b/src/vertex.rs @@ -1,3 +1,6 @@ pub trait Vertex { type HANDLE; + + // get the degree of a given vertex - possibly put this in a GraphUtil trait? + fn degree(&self) -> usize; }