use crate::decomposition_advice::{
MethodProfileBuilder, build_feature_vector,
community::{
LabelPropagationReport as RuntimeLabelPropagationReport,
propagate_labels_report as runtime_propagate_labels_report,
},
};
use super::adjacency::{AdjacencyError, EdgeInput, validate_edges};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct LabelPropagationReport {
runtime: RuntimeLabelPropagationReport,
has_active_nodes: bool,
}
impl LabelPropagationReport {
#[must_use]
pub fn labels(&self) -> &[usize] {
&self.runtime.labels
}
#[must_use]
pub fn label_of(&self, node: usize) -> Option<usize> {
self.labels().get(node).copied()
}
#[must_use]
pub fn iteration_count(&self) -> usize {
self.runtime.iteration_count
}
#[must_use]
pub fn has_active_nodes(&self) -> bool {
self.has_active_nodes
}
#[must_use]
pub fn all_labels_in_bounds(&self) -> bool {
self.runtime
.labels
.iter()
.all(|&label| label < self.runtime.labels.len())
}
}
pub fn label_propagation_report(
method_names: &[&str],
edges: &[EdgeInput],
max_iterations: usize,
) -> Result<LabelPropagationReport, AdjacencyError> {
let similarity_edges = validate_edges(method_names.len(), edges)?;
let adjacency = crate::decomposition_advice::community::build_adjacency(
method_names.len(),
&similarity_edges,
);
let vectors = method_names
.iter()
.map(|method_name| build_feature_vector(&MethodProfileBuilder::new(*method_name).build()))
.collect::<Vec<_>>();
let has_active_nodes = adjacency.iter().any(|neighbours| !neighbours.is_empty());
let runtime = runtime_propagate_labels_report(&vectors, &adjacency, max_iterations);
Ok(LabelPropagationReport {
runtime,
has_active_nodes,
})
}