pub mod centrality;
pub mod clustering;
pub mod patterns;
pub use centrality::{compute_betweenness_centrality, compute_depth_from_entry_points};
pub use clustering::compute_clustering_coefficient;
pub use patterns::{CallGraphPattern, PatternDetector, ResponsibilityClassification};
use crate::priority::call_graph::{CallGraph, FunctionId};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GraphMetrics {
pub outdegree: usize,
pub indegree: usize,
pub depth: usize,
pub betweenness: f64,
pub clustering: f64,
}
impl GraphMetrics {
pub fn empty() -> Self {
Self {
outdegree: 0,
indegree: 0,
depth: usize::MAX,
betweenness: 0.0,
clustering: 0.0,
}
}
pub fn compute(call_graph: &CallGraph, function_id: &FunctionId) -> Self {
let outdegree = call_graph.get_callees(function_id).len();
let indegree = call_graph.get_callers(function_id).len();
let depth = compute_depth_from_entry_points(call_graph, function_id);
let betweenness = compute_betweenness_centrality(call_graph, function_id);
let clustering = compute_clustering_coefficient(call_graph, function_id);
Self {
outdegree,
indegree,
depth,
betweenness,
clustering,
}
}
pub fn is_orchestrator(&self) -> bool {
self.outdegree >= 5 && self.indegree <= 3
}
pub fn is_leaf(&self) -> bool {
self.outdegree == 0
}
pub fn is_hub(&self) -> bool {
self.indegree >= 10
}
pub fn is_bridge(&self) -> bool {
self.betweenness > 0.5
}
pub fn is_utility_cluster(&self) -> bool {
self.clustering > 0.6 && self.indegree >= 3
}
}