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 120 121 122 123 124 125 126 127 128 129 130 131 132 133
use crate::{
errors::HypergraphError, HyperedgeIndex, HyperedgeKey, HyperedgeTrait, Hypergraph, VertexTrait,
};
impl<V, HE> Hypergraph<V, HE>
where
V: VertexTrait,
HE: HyperedgeTrait,
{
/// Removes a hyperedge by index.
pub fn remove_hyperedge(
&mut self,
hyperedge_index: HyperedgeIndex,
) -> Result<(), HypergraphError<V, HE>> {
let internal_index = self.get_internal_hyperedge(hyperedge_index)?;
let HyperedgeKey { vertices, .. } = self
.hyperedges
.get_index(internal_index)
.map(|hyperedge_key| hyperedge_key.to_owned())
.ok_or(HypergraphError::InternalHyperedgeIndexNotFound(
internal_index,
))?;
// Find the last index.
let last_index = self.hyperedges.len() - 1;
// Swap and remove by index.
self.hyperedges.swap_remove_index(internal_index);
// Update the mapping for the removed hyperedge.
self.hyperedges_mapping.left.remove(&internal_index);
self.hyperedges_mapping.right.remove(&hyperedge_index);
// Remove the hyperedge from the vertices.
for vertex in vertices.into_iter() {
match self.vertices.get_index_mut(vertex) {
Some((_, index_set)) => {
index_set.remove(&internal_index);
}
None => return Err(HypergraphError::InternalVertexIndexNotFound(vertex)),
}
}
// Given the following bi-mapping with three hyperedges, i.e. an
// initial set of hyperedges [0, 1, 2]. Let's assume in this example
// that the first hyperedge will be removed:
//
// left | Right
// ---------------------------------------------------------
// 0usize -> HyperedgeIndex(0) | HyperedgeIndex(0) -> 0usize
// 1usize -> HyperedgeIndex(1) | HyperedgeIndex(1) -> 1usize
// 2usize -> HyperedgeIndex(2) | HyperedgeIndex(2) -> 2usize
//
// In the previous steps, the current hyperedge has been already nuked.
// So we now have:
//
// left | Right
// ---------------------------------------------------------
// xxxxxxxxxxxxxxxxxxxxxxxxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxxx
// 1usize -> HyperedgeIndex(1) | HyperedgeIndex(1) -> 1usize
// 2usize -> HyperedgeIndex(2) | HyperedgeIndex(2) -> 2usize
//
// The next step will be to insert the swapped index on the right:
//
// left | Right
// ---------------------------------------------------------
// xxxxxxxxxxxxxxxxxxxxxxxxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxxx
// 1usize -> HyperedgeIndex(1) | HyperedgeIndex(1) -> 1usize
// 2usize -> HyperedgeIndex(2) | HyperedgeIndex(2) -> 0usize
//
// Now remove the index which no longer exists on the left:
//
// left | Right
// ---------------------------------------------------------
// xxxxxxxxxxxxxxxxxxxxxxxxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxxx
// 1usize -> HyperedgeIndex(1) | HyperedgeIndex(1) -> 1usize
// xxxxxxxxxxxxxxxxxxxxxxxxxxx | HyperedgeIndex(2) -> 0usize
//
// Insert the swapped index on the left:
//
// left | Right
// ---------------------------------------------------------
// 0usize -> HyperedgeIndex(2) | xxxxxxxxxxxxxxxxxxxxxxxxxxx
// 1usize -> HyperedgeIndex(1) | HyperedgeIndex(1) -> 1usize
// xxxxxxxxxxxxxxxxxxxxxxxxxxx | HyperedgeIndex(2) -> 0usize
//
// If the index to remove wasn't the last one, the last hyperedge has
// been swapped in place of the removed one. Thus we need to update
// the mapping accordingly.
if internal_index != last_index {
// Get the index of the swapped hyperedge.
let swapped_hyperedge_index = self.get_hyperedge(last_index)?;
// Proceed with the aforementioned operations.
self.hyperedges_mapping
.right
.insert(swapped_hyperedge_index, internal_index);
self.hyperedges_mapping.left.remove(&last_index);
self.hyperedges_mapping
.left
.insert(internal_index, swapped_hyperedge_index);
// Get the vertices of the swapped hyperedge.
let HyperedgeKey {
vertices: swapped_vertices,
..
} = self
.hyperedges
.get_index(internal_index)
.map(|hyperedge_key| hyperedge_key.to_owned())
.ok_or(HypergraphError::InternalHyperedgeIndexNotFound(
internal_index,
))?;
// Update the impacted vertices accordingly.
for vertex in swapped_vertices.into_iter() {
match self.vertices.get_index_mut(vertex) {
Some((_, index_set)) => {
// Update the by performing an insertion of the current
// hyperedge and a removal of the swapped one.
index_set.insert(internal_index);
index_set.remove(&last_index);
}
None => return Err(HypergraphError::InternalVertexIndexNotFound(vertex)),
}
}
}
// Return a unit.
Ok(())
}
}