hipparchus_metrics/
sampling.rs1use hipparchus_mean::Fp;
2use crate::metrics::Metrics;
3
4#[repr(i32)]
6#[derive(Clone,PartialEq,Debug)]
7pub enum SamplingMetrics
8{
9 Jaccard = 1,
11
12 SorensenDice = 2,
14
15 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}