Add GraphTopologyAddition trait from GraphTopology
Move capacity and add methods from GraphTopology trait to new GraphTopologyAddition trait
This commit is contained in:
+2
-2
@@ -1,4 +1,4 @@
|
||||
use crate::traits::GraphTopology;
|
||||
use crate::traits::{GraphTopology, GraphTopologyAddition};
|
||||
|
||||
pub fn petersen<G>(
|
||||
graph: &mut G,
|
||||
@@ -7,7 +7,7 @@ pub fn petersen<G>(
|
||||
[<G as GraphTopology>::Edge; 15],
|
||||
)
|
||||
where
|
||||
G: GraphTopology,
|
||||
G: GraphTopologyAddition,
|
||||
{
|
||||
const N: usize = 5;
|
||||
const K: usize = 2;
|
||||
|
||||
+3
-1
@@ -136,7 +136,9 @@ pub mod traits;
|
||||
|
||||
/// Convenience re-exports of graph topology traits for common use.
|
||||
pub mod prelude {
|
||||
pub use crate::traits::{GraphTopology, GraphTopologyDeletion, Incidence, IncidenceCursor};
|
||||
pub use crate::traits::{
|
||||
GraphTopology, GraphTopologyAddition, GraphTopologyDeletion, Incidence, IncidenceCursor,
|
||||
};
|
||||
}
|
||||
|
||||
mod testing;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! [`AppendGraph`], an undirected graph topology supporting addition only.
|
||||
|
||||
use crate::maps::EntityMap;
|
||||
use crate::traits::{GraphTopology, Incidence, IncidenceCursor};
|
||||
use crate::traits::{GraphTopology, GraphTopologyAddition, Incidence, IncidenceCursor};
|
||||
|
||||
/// An opaque handle identifying a vertex in an [`AppendGraph`].
|
||||
///
|
||||
@@ -147,10 +147,6 @@ impl GraphTopology for AppendGraph {
|
||||
self.vertices.len()
|
||||
}
|
||||
|
||||
fn vertex_capacity(&self) -> usize {
|
||||
self.vertices.capacity()
|
||||
}
|
||||
|
||||
fn vertex_map<T: Clone>(&self, default: T) -> EntityMap<Self::Vertex, T> {
|
||||
EntityMap::new(default, |v| v.0, self.vertex_capacity())
|
||||
}
|
||||
@@ -159,10 +155,6 @@ impl GraphTopology for AppendGraph {
|
||||
self.incidences.len() / 2
|
||||
}
|
||||
|
||||
fn edge_capacity(&self) -> usize {
|
||||
self.incidences.capacity() / 2
|
||||
}
|
||||
|
||||
fn edge_map<T: Clone>(&self, default: T) -> EntityMap<Self::Edge, T> {
|
||||
EntityMap::new(default, |e| e.0 / 2, self.edge_capacity())
|
||||
}
|
||||
@@ -209,6 +201,16 @@ impl GraphTopology for AppendGraph {
|
||||
incidence: self.vertices[v.0].first_incidence,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GraphTopologyAddition for AppendGraph {
|
||||
fn vertex_capacity(&self) -> usize {
|
||||
self.vertices.capacity()
|
||||
}
|
||||
|
||||
fn edge_capacity(&self) -> usize {
|
||||
self.incidences.capacity() / 2
|
||||
}
|
||||
|
||||
fn add_vertex(&mut self) -> Self::Vertex {
|
||||
self.vertices.push(VertexIncidenceHeader {
|
||||
|
||||
+13
-9
@@ -3,7 +3,9 @@
|
||||
use typed_generational_arena::{Arena, Index};
|
||||
|
||||
use crate::maps::EntityMap;
|
||||
use crate::traits::{GraphTopology, GraphTopologyDeletion, Incidence, IncidenceCursor};
|
||||
use crate::traits::{
|
||||
GraphTopology, GraphTopologyAddition, GraphTopologyDeletion, Incidence, IncidenceCursor,
|
||||
};
|
||||
|
||||
/// An opaque handle identifying a vertex in a [`Graph`].
|
||||
///
|
||||
@@ -239,10 +241,6 @@ impl GraphTopology for Graph {
|
||||
self.vertices.len()
|
||||
}
|
||||
|
||||
fn vertex_capacity(&self) -> usize {
|
||||
self.vertices.capacity()
|
||||
}
|
||||
|
||||
fn vertex_map<T: Clone>(&self, default: T) -> EntityMap<Self::Vertex, T> {
|
||||
EntityMap::new(default, |v| v.arr_idx(), self.vertex_capacity())
|
||||
}
|
||||
@@ -251,10 +249,6 @@ impl GraphTopology for Graph {
|
||||
self.incidences.len() / 2
|
||||
}
|
||||
|
||||
fn edge_capacity(&self) -> usize {
|
||||
self.incidences.capacity() / 2
|
||||
}
|
||||
|
||||
fn edge_map<T: Clone>(&self, default: T) -> EntityMap<Self::Edge, T> {
|
||||
EntityMap::new(default, |e| e.arr_idx() / 2, self.edge_capacity())
|
||||
}
|
||||
@@ -312,6 +306,16 @@ impl GraphTopology for Graph {
|
||||
incidence: self.vertices[v].first_incidence,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GraphTopologyAddition for Graph {
|
||||
fn vertex_capacity(&self) -> usize {
|
||||
self.vertices.capacity()
|
||||
}
|
||||
|
||||
fn edge_capacity(&self) -> usize {
|
||||
self.incidences.capacity() / 2
|
||||
}
|
||||
|
||||
fn add_vertex(&mut self) -> Self::Vertex {
|
||||
self.vertices.insert(VertexIncidenceHeader {
|
||||
|
||||
@@ -4,7 +4,7 @@ macro_rules! bfs_tests {
|
||||
($T:ty) => {
|
||||
#[test]
|
||||
fn bfs_single_vertex() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::GraphTopologyAddition;
|
||||
let mut graph = <$T>::new();
|
||||
let v = graph.add_vertex();
|
||||
let result = $crate::algorithms::bfs(&graph, v);
|
||||
@@ -54,7 +54,7 @@ macro_rules! bfs_tests {
|
||||
|
||||
#[test]
|
||||
fn bfs_distances_single_vertex() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::GraphTopologyAddition;
|
||||
let mut graph = <$T>::new();
|
||||
let v = graph.add_vertex();
|
||||
let distances = $crate::algorithms::bfs_distances(&graph, v);
|
||||
@@ -91,7 +91,7 @@ macro_rules! bfs_tests {
|
||||
|
||||
#[test]
|
||||
fn bfs_find_source() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::GraphTopologyAddition;
|
||||
let mut graph = <$T>::new();
|
||||
let v = graph.add_vertex();
|
||||
assert_eq!(
|
||||
@@ -139,7 +139,7 @@ macro_rules! bfs_tests {
|
||||
|
||||
#[test]
|
||||
fn bfs_find_where_source_matches() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::GraphTopologyAddition;
|
||||
let mut graph = <$T>::new();
|
||||
let v = graph.add_vertex();
|
||||
assert_eq!(
|
||||
|
||||
@@ -4,7 +4,7 @@ macro_rules! dfs_tests {
|
||||
($T:ty) => {
|
||||
#[test]
|
||||
fn dfs_single_vertex() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::GraphTopologyAddition;
|
||||
let mut graph = <$T>::new();
|
||||
let v = graph.add_vertex();
|
||||
let result = $crate::algorithms::dfs(&graph, v);
|
||||
@@ -49,7 +49,7 @@ macro_rules! dfs_tests {
|
||||
|
||||
#[test]
|
||||
fn dfs_visited_single_vertex() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::GraphTopologyAddition;
|
||||
let mut graph = <$T>::new();
|
||||
let v = graph.add_vertex();
|
||||
let visited = $crate::algorithms::dfs_visited(&graph, v);
|
||||
@@ -78,7 +78,7 @@ macro_rules! dfs_tests {
|
||||
|
||||
#[test]
|
||||
fn dfs_find_source() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::GraphTopologyAddition;
|
||||
let mut graph = <$T>::new();
|
||||
let v = graph.add_vertex();
|
||||
assert!(
|
||||
@@ -111,7 +111,7 @@ macro_rules! dfs_tests {
|
||||
|
||||
#[test]
|
||||
fn dfs_find_where_source_matches() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::GraphTopologyAddition;
|
||||
let mut graph = <$T>::new();
|
||||
let v = graph.add_vertex();
|
||||
assert_eq!(
|
||||
@@ -205,7 +205,7 @@ macro_rules! dfs_tests {
|
||||
|
||||
#[test]
|
||||
fn dfs_find_path_source_equals_target() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::GraphTopologyAddition;
|
||||
let mut graph = <$T>::new();
|
||||
let v = graph.add_vertex();
|
||||
assert_eq!(
|
||||
@@ -227,7 +227,7 @@ macro_rules! dfs_tests {
|
||||
|
||||
#[test]
|
||||
fn dfs_find_path_adjacent() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::GraphTopologyAddition;
|
||||
let mut graph = <$T>::new();
|
||||
let v1 = graph.add_vertex();
|
||||
let v2 = graph.add_vertex();
|
||||
@@ -255,7 +255,7 @@ macro_rules! dfs_tests {
|
||||
|
||||
#[test]
|
||||
fn dfs_find_path_where_source_matches() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::GraphTopologyAddition;
|
||||
let mut graph = <$T>::new();
|
||||
let v = graph.add_vertex();
|
||||
assert_eq!(
|
||||
|
||||
@@ -4,7 +4,7 @@ macro_rules! dijkstra_tests {
|
||||
($T:ty) => {
|
||||
#[test]
|
||||
fn dijkstra_single_vertex() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::GraphTopologyAddition;
|
||||
let mut graph = <$T>::new();
|
||||
let v = graph.add_vertex();
|
||||
let result = $crate::algorithms::dijkstra(&graph, v, |_| {
|
||||
@@ -25,7 +25,7 @@ macro_rules! dijkstra_tests {
|
||||
|
||||
#[test]
|
||||
fn dijkstra_zero_weight_loop() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::{GraphTopology, GraphTopologyAddition};
|
||||
let mut graph = <$T>::new();
|
||||
let vertices: [<$T as $crate::traits::GraphTopology>::Vertex; 3] =
|
||||
core::array::from_fn(|_| graph.add_vertex());
|
||||
@@ -71,7 +71,7 @@ macro_rules! dijkstra_tests {
|
||||
|
||||
#[test]
|
||||
fn dijkstra_unweighted_single_vertex() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::GraphTopologyAddition;
|
||||
let mut graph = <$T>::new();
|
||||
let v = graph.add_vertex();
|
||||
let result = $crate::algorithms::dijkstra_unweighted(&graph, v);
|
||||
@@ -95,7 +95,7 @@ macro_rules! dijkstra_tests {
|
||||
|
||||
#[test]
|
||||
fn dijkstra_distances_unweighted_single_vertex() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::GraphTopologyAddition;
|
||||
let mut graph = <$T>::new();
|
||||
let v = graph.add_vertex();
|
||||
let distances = $crate::algorithms::dijkstra_distances_unweighted(&graph, v);
|
||||
|
||||
@@ -15,7 +15,7 @@ macro_rules! graph_topology_test_fixtures {
|
||||
<$T as $crate::traits::GraphTopology>::Edge,
|
||||
>>; 10],
|
||||
) {
|
||||
use $crate::traits::{GraphTopology, Incidence};
|
||||
use $crate::traits::{GraphTopology, GraphTopologyAddition, Incidence};
|
||||
let mut graph = <$T>::new();
|
||||
let vertices: [<$T as $crate::traits::GraphTopology>::Vertex; 10] =
|
||||
core::array::from_fn(|_| graph.add_vertex());
|
||||
@@ -96,7 +96,7 @@ macro_rules! graph_topology_test_fixtures {
|
||||
#[allow(dead_code)]
|
||||
fn make_test_graph_disconnected()
|
||||
-> ($T, [<$T as $crate::traits::GraphTopology>::Vertex; 3]) {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::GraphTopologyAddition;
|
||||
let mut graph = <$T>::new();
|
||||
let vertices: [<$T as $crate::traits::GraphTopology>::Vertex; 3] =
|
||||
core::array::from_fn(|_| graph.add_vertex());
|
||||
@@ -112,7 +112,7 @@ macro_rules! graph_topology_tests {
|
||||
($T:ty) => {
|
||||
#[test]
|
||||
fn add_vertex() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::GraphTopologyAddition;
|
||||
let mut graph = <$T>::new();
|
||||
let v = graph.add_vertex();
|
||||
assert_ne!(graph.add_vertex(), v, "unexpected duplicate vertex");
|
||||
@@ -147,7 +147,7 @@ macro_rules! graph_topology_tests {
|
||||
|
||||
#[test]
|
||||
fn add_edge() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::GraphTopologyAddition;
|
||||
let mut graph = <$T>::new();
|
||||
let v1 = graph.add_vertex();
|
||||
let v2 = graph.add_vertex();
|
||||
@@ -974,7 +974,7 @@ macro_rules! graph_topology_deletion_tests {
|
||||
|
||||
#[test]
|
||||
fn delete_vertex_invalid_index() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::GraphTopologyAddition;
|
||||
use $crate::traits::GraphTopologyDeletion;
|
||||
let mut graph = Graph::new();
|
||||
let v = graph.add_vertex();
|
||||
@@ -1169,7 +1169,7 @@ macro_rules! graph_topology_deletion_tests {
|
||||
|
||||
#[test]
|
||||
fn delete_edge_invalid_index() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::GraphTopologyAddition;
|
||||
use $crate::traits::GraphTopologyDeletion;
|
||||
let mut graph = Graph::new();
|
||||
let v1 = graph.add_vertex();
|
||||
|
||||
@@ -4,7 +4,7 @@ macro_rules! entity_map_tests {
|
||||
($T:ty) => {
|
||||
#[test]
|
||||
fn initial_values_are_default() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::{GraphTopology, GraphTopologyAddition};
|
||||
let mut graph = <$T>::new();
|
||||
let v1 = graph.add_vertex();
|
||||
let v2 = graph.add_vertex();
|
||||
@@ -15,7 +15,7 @@ macro_rules! entity_map_tests {
|
||||
|
||||
#[test]
|
||||
fn write_and_read() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::{GraphTopology, GraphTopologyAddition};
|
||||
let mut graph = <$T>::new();
|
||||
let v1 = graph.add_vertex();
|
||||
let v2 = graph.add_vertex();
|
||||
@@ -27,7 +27,7 @@ macro_rules! entity_map_tests {
|
||||
|
||||
#[test]
|
||||
fn lazy_growth_on_read() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::{GraphTopology, GraphTopologyAddition};
|
||||
let mut graph = <$T>::new();
|
||||
graph.add_vertex();
|
||||
let map = graph.vertex_map(99);
|
||||
@@ -37,7 +37,7 @@ macro_rules! entity_map_tests {
|
||||
|
||||
#[test]
|
||||
fn lazy_growth_on_write() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::{GraphTopology, GraphTopologyAddition};
|
||||
let mut graph = <$T>::new();
|
||||
let v1 = graph.add_vertex();
|
||||
let mut map = graph.vertex_map(0);
|
||||
@@ -49,7 +49,7 @@ macro_rules! entity_map_tests {
|
||||
|
||||
#[test]
|
||||
fn expand_to_new_vertices() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::{GraphTopology, GraphTopologyAddition};
|
||||
let mut graph = <$T>::new();
|
||||
graph.add_vertex();
|
||||
let mut map = graph.vertex_map(42);
|
||||
@@ -67,7 +67,7 @@ macro_rules! entity_map_tests {
|
||||
|
||||
#[test]
|
||||
fn expand_does_not_overwrite_existing_values() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::{GraphTopology, GraphTopologyAddition};
|
||||
let mut graph = <$T>::new();
|
||||
let v = graph.add_vertex();
|
||||
let mut map = graph.vertex_map(0);
|
||||
@@ -85,8 +85,7 @@ macro_rules! entity_map_deletion_tests {
|
||||
($T:ty) => {
|
||||
#[test]
|
||||
fn surviving_vertex_readable_after_delete() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::GraphTopologyDeletion;
|
||||
use $crate::traits::{GraphTopology, GraphTopologyAddition, GraphTopologyDeletion};
|
||||
let mut graph = <$T>::new();
|
||||
let v1 = graph.add_vertex();
|
||||
let v2 = graph.add_vertex();
|
||||
@@ -99,8 +98,7 @@ macro_rules! entity_map_deletion_tests {
|
||||
|
||||
#[test]
|
||||
fn reused_slot_returns_old_value() {
|
||||
use $crate::traits::GraphTopology;
|
||||
use $crate::traits::GraphTopologyDeletion;
|
||||
use $crate::traits::{GraphTopology, GraphTopologyAddition, GraphTopologyDeletion};
|
||||
let mut graph = <$T>::new();
|
||||
graph.add_vertex();
|
||||
let v1 = graph.add_vertex();
|
||||
|
||||
+17
-11
@@ -2,13 +2,11 @@
|
||||
|
||||
use crate::maps::EntityMap;
|
||||
|
||||
// TODO: Add functions to reserve memory for vertices and edges.
|
||||
// TODO: Split out GraphTopologyAddition trait.
|
||||
/// A trait representing an undirected graph topology.
|
||||
///
|
||||
/// An undirected graph is a set of vertices and undirected edges, where each edge connects either
|
||||
/// exactly two vertices or one vertex with itself (loop edge). This trait provides methods for
|
||||
/// querying a graph topology, iterating over vertices and edges, and adding new vertices and edges.
|
||||
/// querying a graph topology, and iterating over vertices and edges.
|
||||
///
|
||||
/// # Vertices and edges
|
||||
///
|
||||
@@ -20,9 +18,10 @@ use crate::maps::EntityMap;
|
||||
/// Methods accepting vertices or edges as parameters panic if the handle was invalidated by a
|
||||
/// deletion, and return incorrect results if the handle was not produced by this graph instance.
|
||||
///
|
||||
/// # Deletion
|
||||
/// # Addition and deletion
|
||||
///
|
||||
/// This trait covers graph construction and querying only. To delete vertices and edges, see
|
||||
/// This trait covers graph querying only. To construct a graph incrementally by adding vertices and
|
||||
/// edges, see [`GraphTopologyAddition`]. To delete vertices and edges, see
|
||||
/// [`GraphTopologyDeletion`].
|
||||
///
|
||||
/// [`Edge`]: GraphTopology::Edge
|
||||
@@ -45,9 +44,6 @@ pub trait GraphTopology {
|
||||
/// Returns the number of vertices in the graph.
|
||||
fn vertex_count(&self) -> usize;
|
||||
|
||||
/// Returns the total number of vertices the graph can hold without reallocating.
|
||||
fn vertex_capacity(&self) -> usize;
|
||||
|
||||
/// Creates and returns an [`EntityMap`] for the vertices with every slot initialised to
|
||||
/// `default`.
|
||||
///
|
||||
@@ -74,9 +70,6 @@ pub trait GraphTopology {
|
||||
/// Returns the number of edges in the graph.
|
||||
fn edge_count(&self) -> usize;
|
||||
|
||||
/// Returns the total number of edges the graph can hold without reallocating.
|
||||
fn edge_capacity(&self) -> usize;
|
||||
|
||||
/// Creates and returns an [`EntityMap`] for the edges with every slot initialised to `default`.
|
||||
///
|
||||
/// # Examples
|
||||
@@ -179,6 +172,19 @@ pub trait GraphTopology {
|
||||
///
|
||||
/// Panics if `v` is not a valid vertex of this graph.
|
||||
fn incidence_cursor(&self, v: Self::Vertex) -> Self::IncidenceCursor;
|
||||
}
|
||||
|
||||
// TODO: Add functions to reserve memory for vertices and edges.
|
||||
/// A trait that adds construction operations to an undirected graph topology.
|
||||
///
|
||||
/// This trait provides methods for addition of vertices and edges, and capacity management in an
|
||||
/// undirected graph.
|
||||
pub trait GraphTopologyAddition: GraphTopology {
|
||||
/// Returns the total number of vertices the graph can hold without reallocating.
|
||||
fn vertex_capacity(&self) -> usize;
|
||||
|
||||
/// Returns the total number of edges the graph can hold without reallocating.
|
||||
fn edge_capacity(&self) -> usize;
|
||||
|
||||
/// Adds a new isolated vertex and returns its handle.
|
||||
fn add_vertex(&mut self) -> Self::Vertex;
|
||||
|
||||
Reference in New Issue
Block a user