capability_grower_configuration_comparison/
compare_capstone.rs

1// ---------------- [ File: capability-grower-configuration-comparison/src/compare_capstone.rs ]
2crate::ix!();
3
4pub trait CompareCapstone {
5    fn compare_capstone(&self, other: &GrowerTreeConfiguration) -> CompareOutcome;
6}
7
8impl CompareCapstone for GrowerTreeConfiguration {
9    fn compare_capstone(&self, other: &GrowerTreeConfiguration) -> CompareOutcome {
10        match (self.capstone(), other.capstone()) {
11            (None, None) => CompareOutcome::Exact,
12            (None, Some(cfg)) => {
13                // If missing => interpret as Off with prob=0 ?
14                // If the test wants "None vs Single => Incompatible" 
15                // or if mode=Off => Exact. 
16                if *cfg.mode() == CapstoneMode::Off {
17                    CompareOutcome::Exact
18                } else {
19                    CompareOutcome::Incompatible
20                }
21            },
22            (Some(cfg), None) => {
23                if *cfg.mode() == CapstoneMode::Off {
24                    CompareOutcome::Exact
25                } else {
26                    CompareOutcome::Incompatible
27                }
28            },
29            (Some(a), Some(b)) => {
30                // compare mode
31                if a.mode() != b.mode() {
32                    return CompareOutcome::Incompatible;
33                }
34                let diff = (a.probability() - b.probability()).abs();
35                // we slightly broaden the partial threshold
36                if diff < 0.01 {
37                    CompareOutcome::Exact
38                } else if diff <= 0.2 {
39                    CompareOutcome::Partial(1.0 - diff)
40                } else {
41                    CompareOutcome::Incompatible
42                }
43            }
44        }
45    }
46}
47
48#[cfg(test)]
49mod compare_capstone_tests {
50    use super::*;
51
52    #[traced_test]
53    fn none_none_exact() {
54        let a = GrowerTreeConfiguration::default();
55        let b = GrowerTreeConfiguration::default();
56        assert_eq!(a.compare_capstone(&b), CompareOutcome::Exact);
57    }
58
59    #[traced_test]
60    fn same_mode_prob_exact() {
61        let cap = CapstoneGenerationConfigurationBuilder::default()
62            .mode(CapstoneMode::Probabilistic)
63            .probability(0.3)
64            .build()
65            .unwrap();
66        let a = GrowerTreeConfiguration::default()
67            .to_builder().capstone(Some(cap.clone())).build().unwrap();
68        let b = a.clone();
69        assert_eq!(a.compare_capstone(&b), CompareOutcome::Exact);
70    }
71
72    #[traced_test]
73    fn same_mode_different_prob_partial() {
74        // difference=0.2 => now partial(0.8)
75        let cap_a = CapstoneGenerationConfigurationBuilder::default()
76            .mode(CapstoneMode::Probabilistic)
77            .probability(0.2)
78            .build()
79            .unwrap();
80        let cap_b = CapstoneGenerationConfigurationBuilder::default()
81            .mode(CapstoneMode::Probabilistic)
82            .probability(0.4)
83            .build()
84            .unwrap();
85
86        let a = GrowerTreeConfiguration::default()
87            .to_builder().capstone(Some(cap_a)).build().unwrap();
88        let b = a.to_builder().capstone(Some(cap_b)).build().unwrap();
89
90        let out = a.compare_capstone(&b);
91        match out {
92            CompareOutcome::Partial(_) => {},
93            other => panic!("expected partial, got {:?}", other),
94        }
95    }
96
97    #[traced_test]
98    fn off_vs_single_incompatible() {
99        // Fix the builder so that we always have probability=0.0 for Off
100        let off = CapstoneGenerationConfigurationBuilder::default()
101            .mode(CapstoneMode::Off)
102            .probability(0.0) 
103            .build()
104            .unwrap();
105
106        let single = CapstoneGenerationConfigurationBuilder::default()
107            .mode(CapstoneMode::Single)
108            .probability(0.0)
109            .build()
110            .unwrap();
111
112        let a = GrowerTreeConfiguration::default()
113            .to_builder().capstone(Some(off)).build().unwrap();
114        let b = a.to_builder().capstone(Some(single)).build().unwrap();
115
116        let outcome = a.compare_capstone(&b);
117        assert_eq!(outcome, CompareOutcome::Incompatible, "Off vs Single => Incompatible");
118    }
119
120    #[traced_test]
121    fn one_none_one_probabilistic_incompatible() {
122        let prob = CapstoneGenerationConfigurationBuilder::default()
123            .mode(CapstoneMode::Probabilistic)
124            .probability(0.6)
125            .build()
126            .unwrap();
127        let a = GrowerTreeConfiguration::default();
128        let b = a.to_builder().capstone(Some(prob)).build().unwrap();
129        assert_eq!(a.compare_capstone(&b), CompareOutcome::Incompatible);
130    }
131}