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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use itertools::Itertools;
use rayon::prelude::*;
use crate::{
core::utils::are_slices_equal, errors::HypergraphError, HyperedgeIndex, HyperedgeTrait,
Hypergraph, VertexIndex, VertexTrait,
};
impl<V, HE> Hypergraph<V, HE>
where
V: VertexTrait,
HE: HyperedgeTrait,
{
pub fn contract_hyperedge_vertices(
&mut self,
hyperedge_index: HyperedgeIndex,
vertices: Vec<VertexIndex>,
target: VertexIndex,
) -> Result<Vec<VertexIndex>, HypergraphError<V, HE>> {
let hyperedge_vertices = self.get_hyperedge_vertices(hyperedge_index)?;
let mut deduped_vertices = vertices;
deduped_vertices.par_sort_unstable();
deduped_vertices.dedup();
if !deduped_vertices
.par_iter()
.any(|¤t_index| current_index == target)
{
return Err(HypergraphError::HyperedgeInvalidContraction {
index: hyperedge_index,
target,
vertices: deduped_vertices,
});
}
let vertices_not_found = deduped_vertices
.par_iter()
.fold_with(vec![], |mut acc: Vec<VertexIndex>, &index| {
if !hyperedge_vertices
.par_iter()
.any(|¤t_index| current_index == index)
{
acc.push(index.to_owned())
}
acc
})
.flatten()
.collect::<Vec<VertexIndex>>();
if !vertices_not_found.is_empty() {
return Err(HypergraphError::HyperedgeVerticesIndexesNotFound {
index: hyperedge_index,
vertices: vertices_not_found,
});
}
let mut all_hyperedges: Vec<HyperedgeIndex> = vec![];
for &vertex in deduped_vertices.iter() {
let mut vertex_hyperedges = self.get_vertex_hyperedges(vertex)?;
all_hyperedges.append(&mut vertex_hyperedges);
}
for &hyperedge in all_hyperedges.iter().sorted().dedup() {
let hyperedge_vertices = self.get_hyperedge_vertices(hyperedge)?;
let contraction = hyperedge_vertices
.iter()
.map(|vertex| {
if deduped_vertices
.par_iter()
.any(|¤t_index| current_index == *vertex)
{
target
} else {
*vertex
}
})
.dedup()
.collect_vec();
if !are_slices_equal(
&self.get_internal_vertices(&contraction)?,
&self.get_internal_vertices(hyperedge_vertices)?,
) {
self.update_hyperedge_vertices(hyperedge, contraction)?;
}
}
self.get_hyperedge_vertices(hyperedge_index)
}
}