capability_skeleton/
tree_weighted_branching_measurer.rs

1// ---------------- [ File: capability-skeleton/src/tree_weighted_branching_measurer.rs ]
2crate::ix!();
3
4impl TreeWeightedBranchingMeasurer for Skeleton {
5    #[instrument(level = "trace", skip(self))]
6    fn measure_tree_weighted_branching(&self) -> TreeWeightedBranchingStats {
7        let node_count = self.nodes().len();
8        if node_count == 0 {
9            return TreeWeightedBranchingStatsBuilder::default()
10                .build()
11                .unwrap_or_default();
12        }
13
14        let mut total_children = 0usize;
15        let mut min_child_count = u8::MAX;
16        let mut max_child_count = u8::MIN;
17
18        for node in self.nodes() {
19            let child_count = node.child_ids().len() as u8;
20            total_children += child_count as usize;
21            if child_count < min_child_count {
22                min_child_count = child_count;
23            }
24            if child_count > max_child_count {
25                max_child_count = child_count;
26            }
27        }
28
29        let average_children = total_children as f32 / node_count as f32;
30        TreeWeightedBranchingStatsBuilder::default()
31            .total_nodes_in_tree(node_count)
32            .total_child_count_in_tree(total_children)
33            .min_child_count_in_tree(min_child_count)
34            .max_child_count_in_tree(max_child_count)
35            .average_child_count_in_tree(average_children)
36            .build()
37            .unwrap_or_default()
38    }
39}
40
41#[cfg(test)]
42mod skeleton_weighted_branching_measurer_assessment {
43    use super::*;
44
45    #[traced_test]
46    fn check_weighted_branching_empty() {
47        let skel = SkeletonBuilder::default().build().unwrap();
48        let stats = skel.measure_tree_weighted_branching();
49        assert_eq!(*stats.total_nodes_in_tree(), 0);
50        assert_eq!(*stats.total_child_count_in_tree(), 0);
51    }
52
53    #[traced_test]
54    fn check_weighted_branching_mixed() {
55        // 5 nodes => child counts => [2,2,0,0,0]
56        let n0 = SkeletonNodeBuilder::default()
57            .id(0u16)
58            .child_ids(vec![1u16,2u16])
59            .name("root")
60            .original_key("root")
61            .build(NodeKind::Dispatch)
62            .unwrap();
63        let n1 = SkeletonNodeBuilder::default()
64            .id(1u16)
65            .child_ids(vec![3u16,4u16])
66            .name("childA")
67            .original_key("childA")
68            .build(NodeKind::Dispatch)
69            .unwrap();
70        let n2 = SkeletonNodeBuilder::default()
71            .id(2u16)
72            .name("childB")
73            .original_key("childB")
74            .build(NodeKind::LeafHolder)
75            .unwrap();
76        let n3 = SkeletonNodeBuilder::default()
77            .id(3u16)
78            .name("childC")
79            .original_key("childC")
80            .build(NodeKind::LeafHolder)
81            .unwrap();
82        let n4 = SkeletonNodeBuilder::default()
83            .id(4u16)
84            .name("childD")
85            .original_key("childD")
86            .build(NodeKind::LeafHolder)
87            .unwrap();
88
89        let skel = SkeletonBuilder::default()
90            .nodes(vec![n0, n1, n2, n3, n4])
91            .root_id(Some(0u16))
92            .build()
93            .unwrap();
94
95        let stats = skel.measure_tree_weighted_branching();
96        assert_eq!(*stats.total_nodes_in_tree(), 5);
97        assert_eq!(*stats.total_child_count_in_tree(), 4); // 2 + 2 + 0 + 0 + 0
98        assert_eq!(*stats.min_child_count_in_tree(), 0);
99        assert_eq!(*stats.max_child_count_in_tree(), 2);
100    }
101}