crate::ix!();
pub trait CompareDepthLimits {
fn compare_depth_limits(&self, other: &GrowerTreeConfiguration) -> CompareOutcome;
}
impl CompareDepthLimits for GrowerTreeConfiguration {
fn compare_depth_limits(&self, other: &GrowerTreeConfiguration) -> CompareOutcome {
let mut score = 1.0;
match (self.aggregator_depth_limit(), other.aggregator_depth_limit()) {
(None, None) => {},
(None, Some(_)) | (Some(_), None) => {
score *= 0.8;
},
(Some(a), Some(b)) => {
let diff = (*a as i32 - *b as i32).abs();
if diff > 10 {
return CompareOutcome::Incompatible;
} else if diff > 0 {
score *= 0.8;
}
}
}
match (self.dispatch_depth_limit(), other.dispatch_depth_limit()) {
(None, None) => {},
(None, Some(_)) | (Some(_), None) => {
score *= 0.8;
},
(Some(a), Some(b)) => {
let diff = (*a as i32 - *b as i32).abs();
if diff > 10 {
return CompareOutcome::Incompatible;
} else if diff > 0 {
score *= 0.8;
}
}
}
match (self.leaf_min_depth(), other.leaf_min_depth()) {
(None, None) => {},
(None, Some(_)) | (Some(_), None) => {
score *= 0.8;
},
(Some(a), Some(b)) => {
let diff = (*a as i32 - *b as i32).abs();
if diff > 10 {
return CompareOutcome::Incompatible;
} else if diff > 0 {
score *= 0.8;
}
}
}
if score < 0.2 {
CompareOutcome::Incompatible
} else if score < 1.0 {
CompareOutcome::Partial(score)
} else {
CompareOutcome::Exact
}
}
}
#[cfg(test)]
mod compare_depth_limits_tests {
use super::*;
#[traced_test]
fn all_none_exact() {
let a = GrowerTreeConfiguration::default();
let b = a.clone();
assert_eq!(a.compare_depth_limits(&b), CompareOutcome::Exact);
}
#[traced_test]
fn aggregator_diff_small_partial() {
let a = GrowerTreeConfiguration::default()
.to_builder().aggregator_depth_limit(Some(5)).build().unwrap();
let b = a.to_builder().aggregator_depth_limit(Some(6)).build().unwrap();
match a.compare_depth_limits(&b) {
CompareOutcome::Partial(sc) => assert!(sc < 1.0),
other => panic!("expected partial, got {:?}", other),
}
}
#[traced_test]
fn aggregator_diff_large_incompatible() {
let a = GrowerTreeConfiguration::default()
.to_builder().aggregator_depth_limit(Some(2)).build().unwrap();
let b = a.to_builder().aggregator_depth_limit(Some(13)).build().unwrap();
assert_eq!(a.compare_depth_limits(&b), CompareOutcome::Incompatible);
}
#[traced_test]
fn dispatch_leaf_none_agg_partial() {
let a = GrowerTreeConfiguration::default()
.to_builder()
.aggregator_depth_limit(Some(3))
.dispatch_depth_limit(None)
.leaf_min_depth(None)
.build().unwrap();
let b = a.to_builder()
.aggregator_depth_limit(None)
.build().unwrap();
match a.compare_depth_limits(&b) {
CompareOutcome::Partial(sc) => assert!(sc < 1.0),
other => panic!("expected partial, got {:?}", other),
}
}
#[traced_test]
fn all_same_exact() {
let a = GrowerTreeConfiguration::default()
.to_builder()
.aggregator_depth_limit(Some(3))
.dispatch_depth_limit(Some(5))
.leaf_min_depth(Some(2))
.build().unwrap();
let b = a.clone();
assert_eq!(a.compare_depth_limits(&b), CompareOutcome::Exact);
}
}