From c131f520f4afe44301c489a2bf6e864e0c170a64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20M=C3=BCller?= Date: Tue, 14 Jul 2026 20:01:08 +0200 Subject: [PATCH] Add crate doc front-page, and update readme --- README.md | 59 ++++++++++++++++++++++- src/lib.rs | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/maps.rs | 1 - src/models.rs | 2 + 4 files changed, 188 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f8ce1bc..1aab12a 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,63 @@ # grapherity -Library for graph models and algorithms. +Graph models and algorithms. -This library is still experimental and its API may therefore change frequently. +This crate provides data structures to model graphs and to perform algorithms on these data structures. The functionality presented is designed to be easy to use, flexible, and performant. + +Currently supported are: + +* Undirected graph types `Graph` and `AppendGraph`, built on a flat, index-based adjacency list, +* Maps to freely associate custom data with vertices and edges, +* Connectivity and pathing algorithms: Dijkstra's algorithm, DFS, and BFS in different variants, +* Exposed traits to implement custom graph data structures or algorithms. + +For more information, see the [documentation](https://docs.rs/grapherity/latest/grapherity/). + +## Example + +``` +// Brings commonly used traits into scope. +use grapherity::prelude::*; +use grapherity::models::Graph; +use grapherity::algorithms; + +let mut graph = Graph::new(); +// Creates a map for edge weights with a default weight. +let mut weights = graph.edge_map(1); +// Adds three vertices and two edges. +let v1 = graph.add_vertex(); +let v2 = graph.add_vertex(); +let v3 = graph.add_vertex(); +graph.add_edge(v1, v2); +let e = graph.add_edge(v2, v3); +// Sets a non-default weight for the second edge. +weights[e] = 5; + +// Checks the number of vertices. +assert_eq!(graph.vertex_count(), 3); +// Checks the number of edges. +assert_eq!(graph.edge_count(), 2); +// Checks that v1 and v2 are adjacent. +assert!(graph.are_adjacent(v1, v2)); +// Checks that v1 and v3 are not adjacent. +assert!(!graph.are_adjacent(v1, v3)); +// Checks the sum of all vertex degrees. +let sum: usize = graph.vertices().map(|v| graph.degree(v)).sum(); +assert_eq!(sum, 1 + 2 + 1); + +// Calls Dijkstra's algorithm using the edge weights to find the shortest path from v1 to v3. +let result = algorithms::dijkstra(&graph, v1, |e| weights[e]); +assert_eq!(result.distances[v3], Some(1 + 5)); +assert_eq!(result.predecessors[v3], Some(v2)); + +// Deletes the middle vertex and its incident edges. +graph.delete_vertex(v2); + +// Calls Dijkstra's algorithm again on the now disconnected graph. +let result = algorithms::dijkstra(&graph, v1, |e| weights[e]); +assert_eq!(result.distances[v3], None); +assert_eq!(result.predecessors[v3], None); +``` ## License diff --git a/src/lib.rs b/src/lib.rs index 86d3680..892c8aa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,132 @@ +//! Graph models and algorithms. +//! +//! This crate provides data structures to model graphs and to perform algorithms on these data +//! structures. The functionality presented is designed to be easy to use, flexible, and performant. +//! +//! Currently supported are: +//! +//! * Undirected graph types [`Graph`] and [`AppendGraph`] built on a flat, index-based adjacency +//! list, +//! * [`VertexMap`] and [`EdgeMap`] to freely associate custom data with vertices and edges, +//! * Connectivity and pathing algorithms: [Dijkstra's algorithm], [DFS], and [BFS] in different +//! variants, +//! * Exposed traits to implement custom graph data structures or algorithms. +//! +//! # Usage example +//! +//! This example demonstrates some of this library's features. +//! +//! ``` +//! // Brings commonly used traits into scope. +//! use grapherity::prelude::*; +//! use grapherity::models::Graph; +//! use grapherity::algorithms; +//! +//! let mut graph = Graph::new(); +//! // Creates a map for edge weights with a default weight. +//! let mut weights = graph.edge_map(1); +//! // Adds three vertices and two edges. +//! let v1 = graph.add_vertex(); +//! let v2 = graph.add_vertex(); +//! let v3 = graph.add_vertex(); +//! graph.add_edge(v1, v2); +//! let e = graph.add_edge(v2, v3); +//! // Sets a non-default weight for the second edge. +//! weights[e] = 5; +//! +//! // Checks the number of vertices. +//! assert_eq!(graph.vertex_count(), 3); +//! // Checks the number of edges. +//! assert_eq!(graph.edge_count(), 2); +//! // Checks that v1 and v2 are adjacent. +//! assert!(graph.are_adjacent(v1, v2)); +//! // Checks that v1 and v3 are not adjacent. +//! assert!(!graph.are_adjacent(v1, v3)); +//! // Checks the sum of all vertex degrees. +//! let sum: usize = graph.vertices().map(|v| graph.degree(v)).sum(); +//! assert_eq!(sum, 1 + 2 + 1); +//! +//! // Calls Dijkstra's algorithm using the edge weights to find the shortest path from v1 to v3. +//! let result = algorithms::dijkstra(&graph, v1, |e| weights[e]); +//! assert_eq!(result.distances[v3], Some(1 + 5)); +//! assert_eq!(result.predecessors[v3], Some(v2)); +//! +//! // Deletes the middle vertex and its incident edges. +//! graph.delete_vertex(v2); +//! +//! // Calls Dijkstra's algorithm again on the now disconnected graph. +//! let result = algorithms::dijkstra(&graph, v1, |e| weights[e]); +//! assert_eq!(result.distances[v3], None); +//! assert_eq!(result.predecessors[v3], None); +//! ``` +//! +//! # Graph types +//! +//! [`Graph`] and [`AppendGraph`] both implement [`GraphTopology`] using a flat, index-based adjacency +//! list to store edges, which means that vertex and edge insertions happen in `O(1)`. Degree +//! lookups are also `O(1)`. +//! +//! [`Graph`] additionally implements [`GraphTopologyDeletion`], thereby supporting deletion of +//! vertices and edges. +//! +//! [`AppendGraph`] does not support deletion, vertices and edges can only be added, allowing it to +//! be smaller and more performant compared to [`Graph`] by not requiring the per-element generation +//! tracking needed for stable handles after deletion. +//! +//! # Vertices and edges +//! +//! Graphs in this library use stable indices [`GraphTopology::Vertex`] and [`GraphTopology::Edge`] +//! to denote vertices and edges. This means that vertices and edges returned by graph functions +//! never change, even if the underlying graph data structure is mutated. However, vertices and +//! edges can become invalid when the denoted element is deleted. Code using an invalid vertex or +//! edge in a graph method will panic. +//! +//! ```should_panic +//! # use grapherity::prelude::*; +//! # use grapherity::models::Graph; +//! let mut graph = Graph::new(); +//! let v = graph.add_vertex(); +//! graph.delete_vertex(v); +//! // This will panic because 'v' was deleted and is not valid anymore. +//! graph.degree(v); +//! ``` +//! +//! [`VertexMap`] and [`EdgeMap`] are not required to panic if provided with an invalid +//! vertex or edge. +//! +//! Vertices and edges are provided by the graph and not intended to be generated by users. +//! +//! # Loops and multi-edges +//! +//! Loops and multi edges are supported as well. In the following example, `v1` will have two loops +//! and two edges to `v2`. +//! +//! ``` +//! # use grapherity::prelude::*; +//! # use grapherity::models::Graph; +//! let mut graph = Graph::new(); +//! let v1 = graph.add_vertex(); +//! let v2 = graph.add_vertex(); +//! for _ in 0..2 { +//! graph.add_edge(v1, v1); +//! graph.add_edge(v1, v2); +//! } +//! assert_eq!(graph.edge_count(), 4); +//! assert_eq!(graph.degree(v1), 6); +//! ``` +//! +//! [BFS]: crate::algorithms::bfs +//! [Dijkstra's algorithm]: crate::algorithms::dijkstra +//! [DFS]: crate::algorithms::dfs +//! [`EdgeMap`]: crate::maps::EdgeMap +//! [`VertexMap`]: crate::maps::VertexMap +//! [`AppendGraph`]: crate::models::AppendGraph +//! [`Graph`]: crate::models::Graph +//! [`GraphTopology`]: crate::traits::GraphTopology +//! [`GraphTopology::Edge`]: crate::traits::GraphTopology::Edge +//! [`GraphTopology::Vertex`]: crate::traits::GraphTopology::Vertex +//! [`GraphTopologyDeletion`]: crate::traits::GraphTopologyDeletion + #![warn(missing_docs)] pub mod algorithms; diff --git a/src/maps.rs b/src/maps.rs index 1bda1a1..277ceb5 100644 --- a/src/maps.rs +++ b/src/maps.rs @@ -23,7 +23,6 @@ impl VertexMap { self.capacity() } - pub fn sync>(&mut self, graph: &G) { self.inner.resize(graph.vertex_capacity()); } diff --git a/src/models.rs b/src/models.rs index 5f556aa..d6b95a4 100644 --- a/src/models.rs +++ b/src/models.rs @@ -1,5 +1,7 @@ pub mod append_graph; pub mod graph; +// TODO: Compressed-sparse-row graph model. + pub use append_graph::{AppendGraph, AppendGraphEdgeMap, AppendGraphVertexMap}; pub use graph::{Graph, GraphEdgeMap, GraphVertexMap};