in src/dachshund/algorithms/cnm_communities.rs [160:265]
fn iterate_cnm_communities(
&self,
state: CNMCommunityIntermediaryState,
) -> CNMCommunityIntermediaryState {
let mut communities = state.communities;
let mut degree_map = state.degree_map;
let mut delta_q_bmap = state.delta_q_bmap;
let mut delta_q_maxheap = state.delta_q_maxheap;
let mut maxh = state.maxh;
let num_edges = state.num_edges;
// find largest delta_q_ij
let (_largest_delta_q_ij, i, j) = maxh.pop().unwrap().tuple();
// we will create community j from communities i and j
let com_i: Community = communities.remove(&i).unwrap();
let com_j: &mut Community = communities.get_mut(&j).unwrap();
com_j.extend(com_i);
// get communities to which com_i, com_j are connected
let neighbors_i: HashMap<usize, f64> = delta_q_bmap.remove(&i).unwrap();
let neighbors_j: HashMap<usize, f64> = delta_q_bmap.remove(&j).unwrap();
let mut all_neighbors: HashSet<usize> = neighbors_i.keys().copied().collect();
all_neighbors.extend(neighbors_j.keys().copied());
all_neighbors.remove(&i);
all_neighbors.remove(&j);
let mut new_delta_qjk_map: HashMap<usize, f64> = HashMap::new();
let mut new_community_maxheap: CNMCommunityMergeInstructionHeap = BinaryHeap::new();
for k in all_neighbors {
let delta_qik: Option<&f64> = neighbors_i.get(&k);
let delta_qjk: Option<&f64> = neighbors_j.get(&k);
/* Get new delta_qjk */
let new_delta_qjk = match delta_qik {
Some(x) => match delta_qjk {
Some(y) => x + y,
None => {
x - (degree_map[&j] as f64 / num_edges as f64)
* (degree_map[&k] as f64 / (2 * num_edges) as f64)
}
},
None => {
delta_qjk.unwrap()
- (degree_map[&i] as f64 / num_edges as f64)
* (degree_map[&k] as f64 / (2 * num_edges) as f64)
}
};
new_delta_qjk_map.insert(k, new_delta_qjk);
/* Update the binary maps for k */
let neighbors_k: &mut HashMap<usize, f64> = delta_q_bmap.get_mut(&k).unwrap();
if delta_qik.is_some() {
neighbors_k.remove(&i);
}
neighbors_k.insert(j, new_delta_qjk);
/* Update the binary heap for k */
let old_maxheap: CNMCommunityMergeInstructionHeap = delta_q_maxheap.remove(&k).unwrap();
let mut new_maxheap: CNMCommunityMergeInstructionHeap =
BinaryHeap::with_capacity(old_maxheap.len());
for el in old_maxheap.into_iter_sorted() {
let ll = el.j;
if ll != i {
if ll == j {
new_maxheap.push(CNMCommunityMergeInstruction::new(
OrderedFloat(new_delta_qjk),
k,
ll,
));
} else {
new_maxheap.push(el);
}
}
}
delta_q_maxheap.insert(k, new_maxheap);
new_community_maxheap.push(CNMCommunityMergeInstruction::new(
OrderedFloat(new_delta_qjk),
j,
k,
));
}
// adding the new_delta_qjk map for the newly created community
delta_q_bmap.insert(j, new_delta_qjk_map);
delta_q_bmap.remove(&i);
// updating the delta_q_maxheap
delta_q_maxheap.insert(j, new_community_maxheap);
delta_q_maxheap.remove(&i);
// updating the degree map
let new_degree = degree_map[&i] + degree_map[&j];
degree_map.insert(j, new_degree);
degree_map.remove(&i);
maxh = self.get_max_maxheap(&delta_q_maxheap);
CNMCommunityIntermediaryState {
communities,
degree_map,
delta_q_bmap,
delta_q_maxheap,
maxh,
num_edges,
}
}