abd_clam/core/cluster/
criteria.rs1use distances::Number;
4
5use crate::{Cluster, UniBall};
6
7pub trait PartitionCriterion<U: Number>: Send + Sync {
9 fn check(&self, c: &UniBall<U>) -> bool;
11}
12
13#[derive(Debug, Clone)]
15pub struct MaxDepth(usize);
16
17impl<U: Number> PartitionCriterion<U> for MaxDepth {
18 fn check(&self, c: &UniBall<U>) -> bool {
19 c.depth() < self.0
20 }
21}
22
23#[derive(Debug, Clone)]
25pub struct MinCardinality(usize);
26
27impl<U: Number> PartitionCriterion<U> for MinCardinality {
28 fn check(&self, c: &UniBall<U>) -> bool {
29 c.cardinality() > self.0
30 }
31}
32
33#[allow(clippy::module_name_repetitions)]
35pub struct PartitionCriteria<U: Number> {
36 criteria: Vec<Box<dyn PartitionCriterion<U>>>,
38 check_all: bool,
41}
42
43impl<U: Number> PartitionCriterion<U> for PartitionCriteria<U> {
44 fn check(&self, cluster: &UniBall<U>) -> bool {
45 !cluster.is_singleton()
46 && if self.check_all {
47 self.criteria.iter().all(|c| c.check(cluster))
48 } else {
49 self.criteria.iter().any(|c| c.check(cluster))
50 }
51 }
52}
53
54impl<U: Number> Default for PartitionCriteria<U> {
55 fn default() -> Self {
56 Self::new(true).with_min_cardinality(1)
57 }
58}
59
60impl<U: Number> PartitionCriteria<U> {
61 #[must_use]
68 pub fn new(check_all: bool) -> Self {
69 Self {
70 criteria: Vec::new(),
71 check_all,
72 }
73 }
74
75 #[must_use]
81 pub fn with_max_depth(mut self, threshold: usize) -> Self {
82 self.criteria.push(Box::new(MaxDepth(threshold)));
83 self
84 }
85
86 #[must_use]
92 pub fn with_min_cardinality(mut self, threshold: usize) -> Self {
93 self.criteria.push(Box::new(MinCardinality(threshold)));
94 self
95 }
96
97 #[allow(dead_code)]
103 pub(crate) fn with_custom(mut self, c: Box<dyn PartitionCriterion<U>>) -> Self {
104 self.criteria.push(c);
105 self
106 }
107}