1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
use crate::{
errors::HypergraphError, HyperedgeIndex, HyperedgeKey, HyperedgeTrait, Hypergraph, VertexIndex,
VertexTrait,
};
use itertools::Itertools;
impl<V, HE> Hypergraph<V, HE>
where
V: VertexTrait,
HE: HyperedgeTrait,
{
/// Gets the intersections of a set of hyperedges as a vector of vertices.
pub fn get_hyperedges_intersections(
&self,
hyperedges: Vec<HyperedgeIndex>,
) -> Result<Vec<VertexIndex>, HypergraphError<V, HE>> {
// Keep track of the number of hyperedges.
let number_of_hyperedges = hyperedges.len();
// Early exit if less than two hyperedges are provided.
if number_of_hyperedges < 2 {
return Err(HypergraphError::HyperedgesIntersections);
}
// Get the internal vertices of the hyperedges and keep the eventual error.
let vertices = hyperedges
.into_iter()
.map(
|hyperedge_index| match self.get_internal_hyperedge(hyperedge_index) {
Ok(internal_index) => match self.hyperedges.get_index(internal_index).ok_or(
HypergraphError::InternalHyperedgeIndexNotFound(internal_index),
) {
Ok(HyperedgeKey { vertices, .. }) => {
// Keep the unique vertices.
Ok(vertices.iter().unique().cloned().collect_vec())
}
Err(error) => Err(error),
},
Err(error) => Err(error),
},
)
.collect::<Result<Vec<Vec<usize>>, HypergraphError<V, HE>>>();
match vertices {
Ok(vertices) => {
self.get_vertices(
vertices
.into_iter()
// Flatten and sort the vertices.
.flatten()
.sorted()
// Map the result to tuples where the second term is an arbitrary value.
// The goal is to group them by indexes.
.map(|index| (index, 0))
.into_group_map()
.into_iter()
// Filter the groups having the same size as the hyperedge.
.filter_map(|(index, occurences)| {
if occurences.len() == number_of_hyperedges {
Some(index)
} else {
None
}
})
.sorted()
.collect_vec(),
)
}
Err(error) => Err(error),
}
}
}