//! 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; pub mod maps; pub mod models; pub mod traits; pub mod prelude { pub use crate::traits::{GraphTopology, GraphTopologyDeletion}; } mod testing;