support degree calculation

This commit is contained in:
sigil-03 2025-05-25 11:14:29 -06:00
parent 77118c5d43
commit 2c964737bc
3 changed files with 77 additions and 34 deletions

View file

@ -12,7 +12,4 @@ pub trait Graph<V: Vertex, E: Edge> {
// disconnect two nodes, and return the old edge // disconnect two nodes, and return the old edge
// fn disconnect(vertex_1: &V, vertex_2: &V) -> E; // fn disconnect(vertex_1: &V, vertex_2: &V) -> E;
fn disconnect(&mut self, edge: E::HANDLE); 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;
} }

View file

@ -1,4 +1,4 @@
use std::marker::PhantomData; use std::collections::{HashMap, HashSet};
use crate::{edge::Edge, graph::Graph, vertex::Vertex}; use crate::{edge::Edge, graph::Graph, vertex::Vertex};
@ -14,6 +14,7 @@ impl Edge for SimpleEdge {
struct SimpleVertex { struct SimpleVertex {
id: usize, id: usize,
edges: HashSet<<SimpleEdge as Edge>::HANDLE>,
} }
impl SimpleVertex { impl SimpleVertex {
@ -24,18 +25,25 @@ impl SimpleVertex {
impl Vertex for SimpleVertex { impl Vertex for SimpleVertex {
type HANDLE = usize; type HANDLE = usize;
fn degree(&self) -> usize {
return self.edges.len();
}
} }
struct SimpleGraph { struct SimpleGraph {
vertices: Vec<SimpleVertex>, vertices: HashMap<usize, SimpleVertex>,
edges: Vec<SimpleEdge>, edges: HashMap<usize, SimpleEdge>,
} }
impl SimpleGraph { impl SimpleGraph {
pub fn new_vertex(&mut self) -> <SimpleVertex as Vertex>::HANDLE { pub fn new_vertex(&mut self) -> <SimpleVertex as Vertex>::HANDLE {
let id = self.vertices.len(); let id = self.vertices.len();
let v = SimpleVertex { id: id.clone() }; let v = SimpleVertex {
self.vertices.push(v); id: id.clone(),
edges: HashSet::new(),
};
self.vertices.insert(id, v);
id id
} }
} }
@ -43,63 +51,98 @@ impl SimpleGraph {
impl<'a> Graph<SimpleVertex, SimpleEdge> for SimpleGraph { impl<'a> Graph<SimpleVertex, SimpleEdge> for SimpleGraph {
fn connect(&mut self, vertex_1: usize, vertex_2: usize) -> usize { fn connect(&mut self, vertex_1: usize, vertex_2: usize) -> usize {
let id = self.edges.len(); let id = self.edges.len();
self.edges.push(SimpleEdge {
id: id.clone(), // create the edge
v1: vertex_1, self.edges.insert(
v2: vertex_2, 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 id
} }
// NOTE: this should probably be a failable function... and use a hashmap // NOTE: this should probably be a failable function... and use a hashmap
fn disconnect(&mut self, edge: usize) { fn disconnect(&mut self, edge: usize) {
for i in (0..self.edges.len()) { // TODO: handle unhappy path
if self.edges[i].id == edge { if let Some(e) = self.edges.remove(&edge) {
self.edges.remove(i); // remove the edge handle from each vertex
return; 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] #[test]
fn simple_connect() { fn simple_connect() {
let mut g = SimpleGraph { let mut g = SimpleGraph {
vertices: Vec::new(), vertices: HashMap::new(),
edges: Vec::new(), edges: HashMap::new(),
}; };
let h1 = g.new_vertex(); let h1 = g.new_vertex();
let h2 = 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.len(), 1);
assert_eq!(g.edges[0].id, 0);
assert_eq!(g.edges[0].v1, h1); let e = g.edges.get(&e).unwrap();
assert_eq!(g.edges[0].v2, h2); assert_eq!(e.id, 0);
assert_eq!(e.v1, h1);
assert_eq!(e.v2, h2);
} }
#[test] #[test]
fn simple_disconnect() { fn simple_disconnect() {
let mut g = SimpleGraph { let mut g = SimpleGraph {
vertices: Vec::new(), vertices: HashMap::new(),
edges: Vec::new(), edges: HashMap::new(),
}; };
let h1 = g.new_vertex(); let h1 = g.new_vertex();
let h2 = g.new_vertex(); let h2 = g.new_vertex();
assert_eq!(g.vertices.len(), 2);
let e = g.connect(h1, h2); let e = g.connect(h1, h2);
assert_eq!(g.edges.len(), 1); 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); assert_eq!(g.edges.len(), 0);
} }
#[test] #[test]
fn simple_degree() { 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);
} }

View file

@ -1,3 +1,6 @@
pub trait Vertex { pub trait Vertex {
type HANDLE; type HANDLE;
// get the degree of a given vertex - possibly put this in a GraphUtil trait?
fn degree(&self) -> usize;
} }