hypergraph/lib.rs
1//! Hypergraph is data structure library to generate directed [hypergraphs](https://en.wikipedia.org/wiki/Hypergraph).
2//!
3//! > A hypergraph is a generalization of a graph in which a hyperedge can join any number of vertices.
4//!
5//! ## Features
6//!
7//! This library enables you to:
8//!
9//! - represent **non-simple** hypergraphs with two or more hyperedges containing the exact same set of vertices
10//! - represent **self-loops** — i.e., hyperedges containing vertices directed to themselves one or more times
11//! - represent **unaries** — i.e., hyperedges containing a unique vertex
12//!
13//! Additional features:
14//!
15//! - Safe Rust implementation
16//! - Proper error handling
17//! - Stable indexes for each hyperedge and each vertex — identity is the index, not the weight; duplicate weights are permitted on both sides
18//! - Graph traversal: BFS, DFS, topological sort, reachability check, all simple paths
19//! - Shortest paths: Dijkstra point-to-point and single-source
20//! - Structural analysis: strongly connected components, weakly connected components, subgraph extraction, cycle detection
21//! - Filtered views: `retain_vertices`, `retain_hyperedges`
22//! - Optional **`serde`** feature for serialization/deserialization support
23//! (enable with `features = ["serde"]` in `Cargo.toml`)
24//!
25//! ## Example
26//!
27//! Please notice that the hyperedges and the vertices must implement the
28//! [`HyperedgeTrait`] and the [`VertexTrait`] respectively.
29//!
30//! ```
31//! use hypergraph::{HyperedgeIndex, Hypergraph, VertexIndex};
32//! use std::fmt::{Display, Formatter, Result};
33//!
34//! // Create a new struct to represent a person.
35//! #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
36//! pub struct Person<'a> {
37//! name: &'a str,
38//! }
39//!
40//! impl<'a> Person<'a> {
41//! pub fn new(name: &'a str) -> Self {
42//! Self { name }
43//! }
44//! }
45//!
46//! impl<'a> Display for Person<'a> {
47//! fn fmt(&self, f: &mut Formatter<'_>) -> Result {
48//! write!(f, "{}", self.name)
49//! }
50//! }
51//!
52//! // Create a new struct to represent a relation.
53//! #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
54//! pub struct Relation<'a> {
55//! cost: usize,
56//! name: &'a str,
57//! }
58//!
59//! impl<'a> Relation<'a> {
60//! pub fn new(name: &'a str, cost: usize) -> Self {
61//! Self { cost, name }
62//! }
63//! }
64//!
65//! impl<'a> Display for Relation<'a> {
66//! fn fmt(&self, f: &mut Formatter<'_>) -> Result {
67//! write!(f, "{}", self.name)
68//! }
69//! }
70//!
71//! impl<'a> From<Relation<'a>> for usize {
72//! fn from(relation: Relation<'a>) -> usize {
73//! relation.cost
74//! }
75//! }
76//!
77//! fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
78//! let mut graph = Hypergraph::<Person, Relation>::new();
79//!
80//! // Create some folks.
81//! let ava_person = Person::new("Ava");
82//! let bianca_person = Person::new("Bianca");
83//! let charles_person = Person::new("Charles");
84//! let daena_person = Person::new("Daena");
85//! let ewan_person = Person::new("Ewan");
86//! let faarooq_person = Person::new("Faarooq");
87//! let ghanda_person = Person::new("Ghanda");
88//!
89//! // Add those to the graph as vertices.
90//! let ava = graph.add_vertex(ava_person)?;
91//! let bianca = graph.add_vertex(bianca_person)?;
92//! let charles = graph.add_vertex(charles_person)?;
93//! let daena = graph.add_vertex(daena_person)?;
94//! let ewan = graph.add_vertex(ewan_person)?;
95//! let faarooq = graph.add_vertex(faarooq_person)?;
96//! let ghanda = graph.add_vertex(ghanda_person)?;
97//!
98//! // Each vertex gets a unique index by insertion order.
99//! assert_eq!(ava, VertexIndex(0));
100//! assert_eq!(ghanda, VertexIndex(6));
101//!
102//! // Get the weight of a vertex.
103//! assert_eq!(graph.get_vertex_weight(VertexIndex(0)), Ok(&ava_person));
104//!
105//! // The hypergraph has seven vertices.
106//! assert_eq!(graph.count_vertices(), 7);
107//!
108//! // Create some relations.
109//! let cat_video = Relation::new("share a viral video with a cat", 1);
110//! let dog_video = Relation::new("share a viral video with a dog", 1);
111//! let beaver_video = Relation::new("share a viral video with a beaver", 1);
112//! let playing_online = Relation::new("play online", 1);
113//! let passing_ball = Relation::new("pass the ball", 1);
114//!
115//! // Add those to the graph as hyperedges.
116//! let first_relation = graph.add_hyperedge(vec![faarooq, ava, ghanda], cat_video)?;
117//! let second_relation = graph.add_hyperedge(vec![faarooq, ava, ghanda], dog_video)?;
118//! let third_relation = graph.add_hyperedge(vec![ewan, ava, bianca], beaver_video)?;
119//! let fourth_relation = graph.add_hyperedge(vec![daena], playing_online)?;
120//! let fifth_relation = graph.add_hyperedge(vec![ewan, charles, bianca, bianca, ewan], passing_ball)?;
121//!
122//! // Each hyperedge gets a unique index by insertion order.
123//! assert_eq!(first_relation, HyperedgeIndex(0));
124//! assert_eq!(fifth_relation, HyperedgeIndex(4));
125//!
126//! // Get the weight of a hyperedge.
127//! assert_eq!(graph.get_hyperedge_weight(HyperedgeIndex(0)), Ok(&cat_video));
128//!
129//! // Get the vertices of a hyperedge.
130//! assert_eq!(graph.get_hyperedge_vertices(HyperedgeIndex(0)), Ok(vec![faarooq, ava, ghanda]));
131//!
132//! // The hypergraph has 5 hyperedges.
133//! assert_eq!(graph.count_hyperedges(), 5);
134//!
135//! // Get the hyperedges of a vertex.
136//! assert_eq!(graph.get_vertex_hyperedges(VertexIndex(0)), Ok(vec![first_relation, second_relation, third_relation]));
137//! assert_eq!(graph.get_full_vertex_hyperedges(VertexIndex(0)), Ok(vec![vec![faarooq, ava, ghanda], vec![faarooq, ava, ghanda], vec![ewan, ava, bianca]]));
138//!
139//! // Get the intersection of some hyperedges.
140//! assert_eq!(graph.get_hyperedges_intersections(vec![second_relation, third_relation]), Ok(vec![ava]));
141//!
142//! // Find a hyperedge containing a connection between two vertices.
143//! assert_eq!(graph.get_hyperedges_connecting(bianca, bianca), Ok(vec![fifth_relation]));
144//!
145//! // Get the adjacent vertices from a vertex.
146//! assert_eq!(graph.get_adjacent_vertices_from(VertexIndex(0)), Ok(vec![bianca, ghanda]));
147//!
148//! // Get the adjacent vertices to a vertex.
149//! assert_eq!(graph.get_adjacent_vertices_to(VertexIndex(0)), Ok(vec![ewan, faarooq]));
150//!
151//! // Find the shortest paths between some vertices.
152//! assert_eq!(graph.get_dijkstra_connections(faarooq, bianca), Ok(vec![(faarooq, None), (ava, Some(first_relation)), (bianca, Some(third_relation))]));
153//!
154//! // Update the weight of a vertex.
155//! graph.update_vertex_weight(ava, Person::new("Avā"))?;
156//!
157//! // Update the weight of a hyperedge.
158//! graph.update_hyperedge_weight(third_relation, Relation::new("share a viral video with a capybara", 1))?;
159//!
160//! // Update the vertices of a hyperedge.
161//! graph.update_hyperedge_vertices(third_relation, vec![ewan, ava, daena])?;
162//!
163//! // Remove a hyperedge.
164//! graph.remove_hyperedge(first_relation)?;
165//!
166//! // Remove a vertex.
167//! graph.remove_vertex(ewan)?;
168//!
169//! // Reverse a hyperedge.
170//! graph.reverse_hyperedge(fifth_relation)?;
171//!
172//! // Get the in-degree of a vertex.
173//! assert_eq!(graph.get_vertex_degree_in(ava), Ok(1));
174//!
175//! // Get the out-degree of a vertex.
176//! assert_eq!(graph.get_vertex_degree_out(ghanda), Ok(0));
177//!
178//! // Contract a hyperedge's vertices.
179//! graph.contract_hyperedge_vertices(fifth_relation, vec![bianca, charles], bianca)?;
180//!
181//! // Join some hyperedges.
182//! graph.join_hyperedges(&[fifth_relation, third_relation]);
183//!
184//! // Clear the hyperedges.
185//! graph.clear_hyperedges()?;
186//!
187//! // Clear the whole hypergraph.
188//! graph.clear();
189//!
190//! Ok(())
191//! }
192//! ```
193
194#[doc(hidden)]
195pub mod core;
196
197// Reexport of the public API.
198#[doc(inline)]
199pub use crate::core::*;