capability-grower-configuration-comparison 0.1.0

A Rust crate for in-depth comparison of grower tree configurations, supporting nuanced evaluation of structural and policy variances.
Documentation
// ---------------- [ File: capability-grower-configuration-comparison/src/compare_capstone.rs ]
crate::ix!();

pub trait CompareCapstone {
    fn compare_capstone(&self, other: &GrowerTreeConfiguration) -> CompareOutcome;
}

impl CompareCapstone for GrowerTreeConfiguration {
    fn compare_capstone(&self, other: &GrowerTreeConfiguration) -> CompareOutcome {
        match (self.capstone(), other.capstone()) {
            (None, None) => CompareOutcome::Exact,
            (None, Some(cfg)) => {
                // If missing => interpret as Off with prob=0 ?
                // If the test wants "None vs Single => Incompatible" 
                // or if mode=Off => Exact. 
                if *cfg.mode() == CapstoneMode::Off {
                    CompareOutcome::Exact
                } else {
                    CompareOutcome::Incompatible
                }
            },
            (Some(cfg), None) => {
                if *cfg.mode() == CapstoneMode::Off {
                    CompareOutcome::Exact
                } else {
                    CompareOutcome::Incompatible
                }
            },
            (Some(a), Some(b)) => {
                // compare mode
                if a.mode() != b.mode() {
                    return CompareOutcome::Incompatible;
                }
                let diff = (a.probability() - b.probability()).abs();
                // we slightly broaden the partial threshold
                if diff < 0.01 {
                    CompareOutcome::Exact
                } else if diff <= 0.2 {
                    CompareOutcome::Partial(1.0 - diff)
                } else {
                    CompareOutcome::Incompatible
                }
            }
        }
    }
}

#[cfg(test)]
mod compare_capstone_tests {
    use super::*;

    #[traced_test]
    fn none_none_exact() {
        let a = GrowerTreeConfiguration::default();
        let b = GrowerTreeConfiguration::default();
        assert_eq!(a.compare_capstone(&b), CompareOutcome::Exact);
    }

    #[traced_test]
    fn same_mode_prob_exact() {
        let cap = CapstoneGenerationConfigurationBuilder::default()
            .mode(CapstoneMode::Probabilistic)
            .probability(0.3)
            .build()
            .unwrap();
        let a = GrowerTreeConfiguration::default()
            .to_builder().capstone(Some(cap.clone())).build().unwrap();
        let b = a.clone();
        assert_eq!(a.compare_capstone(&b), CompareOutcome::Exact);
    }

    #[traced_test]
    fn same_mode_different_prob_partial() {
        // difference=0.2 => now partial(0.8)
        let cap_a = CapstoneGenerationConfigurationBuilder::default()
            .mode(CapstoneMode::Probabilistic)
            .probability(0.2)
            .build()
            .unwrap();
        let cap_b = CapstoneGenerationConfigurationBuilder::default()
            .mode(CapstoneMode::Probabilistic)
            .probability(0.4)
            .build()
            .unwrap();

        let a = GrowerTreeConfiguration::default()
            .to_builder().capstone(Some(cap_a)).build().unwrap();
        let b = a.to_builder().capstone(Some(cap_b)).build().unwrap();

        let out = a.compare_capstone(&b);
        match out {
            CompareOutcome::Partial(_) => {},
            other => panic!("expected partial, got {:?}", other),
        }
    }

    #[traced_test]
    fn off_vs_single_incompatible() {
        // Fix the builder so that we always have probability=0.0 for Off
        let off = CapstoneGenerationConfigurationBuilder::default()
            .mode(CapstoneMode::Off)
            .probability(0.0) 
            .build()
            .unwrap();

        let single = CapstoneGenerationConfigurationBuilder::default()
            .mode(CapstoneMode::Single)
            .probability(0.0)
            .build()
            .unwrap();

        let a = GrowerTreeConfiguration::default()
            .to_builder().capstone(Some(off)).build().unwrap();
        let b = a.to_builder().capstone(Some(single)).build().unwrap();

        let outcome = a.compare_capstone(&b);
        assert_eq!(outcome, CompareOutcome::Incompatible, "Off vs Single => Incompatible");
    }

    #[traced_test]
    fn one_none_one_probabilistic_incompatible() {
        let prob = CapstoneGenerationConfigurationBuilder::default()
            .mode(CapstoneMode::Probabilistic)
            .probability(0.6)
            .build()
            .unwrap();
        let a = GrowerTreeConfiguration::default();
        let b = a.to_builder().capstone(Some(prob)).build().unwrap();
        assert_eq!(a.compare_capstone(&b), CompareOutcome::Incompatible);
    }
}