1use crate::colony::Colony;
7use phago_core::topology::TopologyGraph;
8use serde::Serialize;
9
10#[derive(Debug, Clone, Serialize)]
12pub struct WeightedTriple {
13 pub subject: String,
14 pub predicate: String,
15 pub object: String,
16 pub weight: f64,
17 pub co_activations: u64,
18}
19
20pub fn export_triples(colony: &Colony) -> Vec<WeightedTriple> {
22 let graph = colony.substrate().graph();
23 let mut triples = Vec::new();
24
25 for (from_id, to_id, edge) in graph.all_edges() {
26 let from_label = graph.get_node(&from_id)
27 .map(|n| n.label.clone())
28 .unwrap_or_else(|| "?".to_string());
29 let to_label = graph.get_node(&to_id)
30 .map(|n| n.label.clone())
31 .unwrap_or_else(|| "?".to_string());
32
33 triples.push(WeightedTriple {
34 subject: from_label,
35 predicate: "related_to".to_string(),
36 object: to_label,
37 weight: edge.weight,
38 co_activations: edge.co_activations,
39 });
40 }
41
42 triples.sort_by(|a, b| b.weight.partial_cmp(&a.weight).unwrap_or(std::cmp::Ordering::Equal));
44 triples
45}
46
47pub fn triple_stats(triples: &[WeightedTriple]) -> TripleStats {
49 if triples.is_empty() {
50 return TripleStats {
51 total: 0,
52 mean_weight: 0.0,
53 median_weight: 0.0,
54 max_weight: 0.0,
55 min_weight: 0.0,
56 mean_co_activations: 0.0,
57 };
58 }
59
60 let weights: Vec<f64> = triples.iter().map(|t| t.weight).collect();
61 let total = triples.len();
62 let mean_weight = weights.iter().sum::<f64>() / total as f64;
63 let max_weight = weights.iter().cloned().fold(0.0f64, f64::max);
64 let min_weight = weights.iter().cloned().fold(f64::MAX, f64::min);
65
66 let mut sorted = weights.clone();
67 sorted.sort_by(|a, b| a.partial_cmp(b).unwrap());
68 let median_weight = sorted[sorted.len() / 2];
69
70 let mean_co_activations = triples.iter()
71 .map(|t| t.co_activations as f64)
72 .sum::<f64>() / total as f64;
73
74 TripleStats {
75 total,
76 mean_weight,
77 median_weight,
78 max_weight,
79 min_weight,
80 mean_co_activations,
81 }
82}
83
84#[derive(Debug, Clone, Serialize)]
86pub struct TripleStats {
87 pub total: usize,
88 pub mean_weight: f64,
89 pub median_weight: f64,
90 pub max_weight: f64,
91 pub min_weight: f64,
92 pub mean_co_activations: f64,
93}