use super::{*, graph::strength_graph};
#[derive(Clone, Copy, PartialEq, Eq)]
pub(crate) enum Mark {
Unmarked,
C, F, }
#[derive(Clone)]
struct Node {
index: usize,
degree: usize,
}
pub(crate) fn coarsen<T>(a: &CsrMatrix<T>, theta: T) -> (Vec<Mark>, Vec<usize>)
where
T: RealField + Copy,
{
let n = a.nrows();
let graph = strength_graph(a, theta);
let mut nodes: Vec<Node> = graph.iter()
.enumerate()
.map(|(index, neighbors)| Node {
index,
degree: neighbors.len(),
})
.collect();
nodes.sort_unstable_by(|a, b| b.degree.cmp(&a.degree));
let mut marks = vec![Mark::Unmarked; n];
let mut coarse_of = vec![usize::MAX; n];
let mut next_coarse = 0usize;
for node in &nodes {
if marks[node.index] != Mark::Unmarked {
continue;
}
marks[node.index] = Mark::C;
coarse_of[node.index] = next_coarse;
next_coarse += 1;
for &neighbor in &graph[node.index] {
if matches!(marks[neighbor], Mark::Unmarked) {
marks[neighbor] = Mark::F;
}
}
}
(marks, coarse_of)
}