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
// 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;
}

View file

@ -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<<SimpleEdge as Edge>::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<SimpleVertex>,
edges: Vec<SimpleEdge>,
vertices: HashMap<usize, SimpleVertex>,
edges: HashMap<usize, SimpleEdge>,
}
impl SimpleGraph {
pub fn new_vertex(&mut self) -> <SimpleVertex as Vertex>::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<SimpleVertex, SimpleEdge> 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);
}

View file

@ -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;
}