Compare commits

..

3 commits

Author SHA1 Message Date
2c964737bc support degree calculation 2025-05-25 11:14:29 -06:00
77118c5d43 SimpleGraph: add new_vertex 2025-05-25 10:41:51 -06:00
940f244aaf change test_* to simple_* 2025-05-25 08:18:09 -06:00
3 changed files with 92 additions and 45 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,78 +25,124 @@ 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 {
let id = self.vertices.len();
let v = SimpleVertex {
id: id.clone(),
edges: HashSet::new(),
};
self.vertices.insert(id, v);
id
}
}
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 it_works() {} fn simple_connect() {
#[test]
fn test_connect() {
let v1 = SimpleVertex { id: 0 };
let v2 = SimpleVertex { id: 1 };
let mut g = SimpleGraph { let mut g = SimpleGraph {
vertices: vec![v1, v2], vertices: HashMap::new(),
edges: Vec::new(), edges: HashMap::new(),
}; };
let _e = g.connect(0, 1); 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.len(), 1);
assert_eq!(g.edges[0].id, 0);
assert_eq!(g.edges[0].v1, 0); let e = g.edges.get(&e).unwrap();
assert_eq!(g.edges[0].v2, 1); assert_eq!(e.id, 0);
assert_eq!(e.v1, h1);
assert_eq!(e.v2, h2);
} }
#[test] #[test]
fn test_disconnect() { fn simple_disconnect() {
let v1 = SimpleVertex { id: 0 };
let v2 = SimpleVertex { id: 1 };
let mut g = SimpleGraph { let mut g = SimpleGraph {
vertices: vec![v1, v2], vertices: HashMap::new(),
edges: Vec::new(), edges: HashMap::new(),
}; };
let e = g.connect(0, 1); let h1 = g.new_vertex();
assert_eq!(g.edges.len(), 1); let h2 = g.new_vertex();
assert_eq!(g.edges[0].id, 0); assert_eq!(g.vertices.len(), 2);
assert_eq!(g.edges[0].v1, 0);
assert_eq!(g.edges[0].v2, 1);
g.disconnect(e); let e = g.connect(h1, h2);
assert_eq!(g.edges.len(), 1);
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 test_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;
} }