hipparchus_metrics/
sampling.rs

1use hipparchus_mean::Fp;
2use crate::metrics::Metrics;
3
4/// Metrics for sampling
5#[repr(i32)]
6#[derive(Clone,PartialEq,Debug)]
7pub enum SamplingMetrics
8{
9    /// Jaccard index
10    Jaccard = 1,
11
12    /// Sorensen-Dice index
13    SorensenDice = 2,
14
15    /// Bray-Curtis dissimilarity
16    BrayCurtis = 3,
17}
18
19impl<T:Fp> Metrics<&[T], T> for SamplingMetrics
20{
21    fn measure(self, x:&[T], y:&[T]) -> T
22    {
23        let it = x.iter().zip(y.iter());
24        match self
25        {
26            SamplingMetrics::Jaccard => 
27            {
28                let (intersect, union) = it.fold((T::zero(), T::zero()), | (i, u), (&p, &q)|
29                {(
30                    i + p.min(q),
31                    u + p.max(q),
32                )});
33                intersect / union
34            },
35            SamplingMetrics::SorensenDice => 
36            {
37                let (intersect, agg) = it.fold((T::zero(), T::zero()), | (i, agg), (&p, &q)|
38                {(
39                    i + p.min(q),
40                    agg + p + q,
41                )});
42                T::from(2).unwrap() * intersect / agg
43            },
44            SamplingMetrics::BrayCurtis =>
45            {
46                let (intersect, agg) = it.fold((T::zero(), T::zero()), | (i, agg), (&p, &q)|
47                {(
48                    i + p.min(q),
49                    agg + p + q,
50                )});
51                T::one() - T::from(2).unwrap() * intersect / agg
52            },
53        }
54    }
55}
56
57#[cfg(test)]
58mod tests 
59{
60    use super::*;
61    use rstest::*;
62    use float_cmp::assert_approx_eq;
63
64    #[rstest]
65    #[case(vec![1.0, 0.0, 1.0], vec![0.0, 1.0, 3.0], SamplingMetrics::Jaccard, 0.2)]
66    #[case(vec![1.0, 0.0, 1.0], vec![0.0, 1.0, 3.0], SamplingMetrics::SorensenDice, 0.33333334)]
67    #[case(vec![1.0, 0.0, 1.0], vec![0.0, 1.0, 3.0], SamplingMetrics::BrayCurtis, 0.6666666)]
68    fn test_sampling(#[case] d1: Vec<f32>, #[case] d2: Vec<f32>, #[case] m: SamplingMetrics, #[case] expected :f32)
69    {
70        let actual = m.measure(&d1, &d2);
71        assert_approx_eq!(f32, expected, actual);
72    }
73
74    #[rstest]
75    #[case(vec![5.0, 5.0], SamplingMetrics::Jaccard, 1.0)]
76    #[case(vec![5.0, 5.0], SamplingMetrics::SorensenDice, 1.0)]
77    #[case(vec![5.0, 5.0], SamplingMetrics::BrayCurtis, 0.0)]
78    fn test_sampling_eq(#[case] d: Vec<f32>, #[case] m: SamplingMetrics, #[case] expected :f32)
79    {
80        let actual = m.measure(&d, &d);
81        assert_approx_eq!(f32, expected, actual);
82    }
83}