diff --git a/src/graph.rs b/src/graph.rs index cba9b27..1f25452 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -500,41 +500,20 @@ fn label_propagation( labels } -/// Schema fit: for a node, measure how well-connected its neighbors are -/// to each other. High density + high CC among neighbors = good schema fit. +/// Schema fit for a node: how well-integrated into its local neighborhood. +/// +/// Algebraically identical to clustering_coefficient — both measure the +/// fraction of neighbor pairs that are connected. Kept as an alias for +/// semantic clarity: CC is a graph metric, schema fit is a cognitive one +/// (how well does this node fit the surrounding schema?). pub fn schema_fit(graph: &Graph, key: &str) -> f32 { - let neighbors = graph.neighbor_keys(key); - let n = neighbors.len(); - if n < 2 { - return 0.0; // isolated or leaf — no schema context - } - - // Count edges among neighbors - let neighbor_vec: Vec<&str> = neighbors.iter().copied().collect(); - let mut inter_edges = 0u32; - for i in 0..neighbor_vec.len() { - for j in (i + 1)..neighbor_vec.len() { - let ni_neighbors = graph.neighbor_keys(neighbor_vec[i]); - if ni_neighbors.contains(neighbor_vec[j]) { - inter_edges += 1; - } - } - } - - let max_edges = (n * (n - 1)) / 2; - let density = if max_edges == 0 { 0.0 } else { - inter_edges as f32 / max_edges as f32 - }; - - // Combine neighborhood density with own CC - let cc = graph.clustering_coefficient(key); - (density + cc) / 2.0 + graph.clustering_coefficient(key) } /// Compute schema fit for all nodes pub fn schema_fit_all(graph: &Graph) -> HashMap { graph.nodes().iter() - .map(|key| (key.clone(), schema_fit(graph, key))) + .map(|key| (key.clone(), graph.clustering_coefficient(key))) .collect() }