Skip to main content

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::*;