hypergraph/core/hyperedges/
contract_hyperedge_vertices.rs1use itertools::Itertools;
2use rayon::prelude::*;
3
4use crate::{
5 HyperedgeIndex,
6 HyperedgeTrait,
7 Hypergraph,
8 VertexIndex,
9 VertexTrait,
10 core::utils::are_slices_equal,
11 errors::HypergraphError,
12};
13
14impl<V, HE> Hypergraph<V, HE>
15where
16 V: VertexTrait,
17 HE: HyperedgeTrait,
18{
19 pub fn contract_hyperedge_vertices(
23 &mut self,
24 hyperedge_index: HyperedgeIndex,
25 vertices: Vec<VertexIndex>,
26 target: VertexIndex,
27 ) -> Result<Vec<VertexIndex>, HypergraphError<V, HE>> {
28 let hyperedge_vertices = self.get_hyperedge_vertices(hyperedge_index)?;
30
31 let mut deduped_vertices = vertices;
36
37 deduped_vertices.par_sort_unstable();
38 deduped_vertices.dedup();
39
40 if !deduped_vertices
42 .par_iter()
43 .any(|¤t_index| current_index == target)
44 {
45 return Err(HypergraphError::HyperedgeInvalidContraction {
46 index: hyperedge_index,
47 target,
48 vertices: deduped_vertices,
49 });
50 }
51
52 let vertices_not_found = deduped_vertices
54 .par_iter()
55 .fold_with(vec![], |mut acc: Vec<VertexIndex>, &index| {
56 if !hyperedge_vertices
57 .par_iter()
58 .any(|¤t_index| current_index == index)
59 {
60 acc.push(index);
61 }
62
63 acc
64 })
65 .flatten()
66 .collect::<Vec<VertexIndex>>();
67
68 if !vertices_not_found.is_empty() {
71 return Err(HypergraphError::HyperedgeVerticesIndexesNotFound {
72 index: hyperedge_index,
73 vertices: vertices_not_found,
74 });
75 }
76
77 let mut all_hyperedges: Vec<HyperedgeIndex> = vec![];
79
80 for &vertex in &deduped_vertices {
82 let mut vertex_hyperedges = self.get_vertex_hyperedges(vertex)?;
84
85 all_hyperedges.append(&mut vertex_hyperedges);
87 }
88
89 for &hyperedge in all_hyperedges.iter().sorted().dedup() {
91 let hyperedge_vertices = self.get_hyperedge_vertices(hyperedge)?;
92
93 let contraction = hyperedge_vertices
95 .iter()
96 .map(|vertex| {
98 if deduped_vertices
99 .par_iter()
100 .any(|¤t_index| current_index == *vertex)
101 {
102 target
103 } else {
104 *vertex
105 }
106 })
107 .dedup()
109 .collect_vec();
110
111 if !are_slices_equal(
113 &self.get_internal_vertices(&contraction)?,
114 &self.get_internal_vertices(hyperedge_vertices)?,
115 ) {
116 self.update_hyperedge_vertices(hyperedge, contraction)?;
118 }
119 }
120
121 self.get_hyperedge_vertices(hyperedge_index)
123 }
124}