fast_distances/distances/
matching.rs

1extern crate ndarray;
2
3use ndarray::ArrayView1;
4
5/// Computes the Matching similarity between two binary vectors.
6///
7/// The Matching similarity is the proportion of positions where the two binary vectors
8/// differ in their values. The vectors are treated as binary, where non-zero values are
9/// considered `True` and zero values are considered `False`.
10///
11/// The formula is:
12///
13/// ..math::
14///    M(x, y) = \frac{|\{x_i \neq y_i\}|}{n}
15///
16/// where n is the number of elements in the vectors.
17///
18/// # Arguments
19/// * `x` - A 1D array (view) of values representing the first binary vector.
20/// * `y` - A 1D array (view) of values representing the second binary vector.
21///
22/// # Returns
23/// A f64 value representing the Matching similarity.
24pub fn matching(x: &ArrayView1<f64>, y: &ArrayView1<f64>) -> f64 {
25    let mut num_not_equal = 0.0;
26
27    for i in 0..x.len() {
28        let x_true = x[i] != 0.0;
29        let y_true = y[i] != 0.0;
30        num_not_equal += if x_true != y_true { 1.0 } else { 0.0 };
31    }
32
33    num_not_equal / x.len() as f64
34}
35
36#[cfg(test)]
37mod tests {
38    use super::*;
39    use ndarray::arr1;
40
41    #[test]
42    fn test_matching_basic() {
43        let x = arr1(&[1.0, 0.0, 1.0]);
44        let y = arr1(&[1.0, 1.0, 0.0]);
45
46        let similarity = matching(&x.view(), &y.view());
47        let expected_similarity = 2.0 / 3.0; // Two positions are not equal: (x[1] != y[1]) and (x[2] != y[2])
48        assert_eq!(similarity, expected_similarity);
49    }
50
51    #[test]
52    fn test_matching_identical_vectors() {
53        let x = arr1(&[1.0, 1.0, 1.0]);
54        let y = arr1(&[1.0, 1.0, 1.0]);
55
56        let similarity = matching(&x.view(), &y.view());
57        assert_eq!(similarity, 0.0); // All elements are equal, so no mismatches
58    }
59
60    #[test]
61    fn test_matching_no_overlap() {
62        let x = arr1(&[1.0, 0.0, 0.0]);
63        let y = arr1(&[0.0, 0.0, 1.0]);
64
65        let similarity = matching(&x.view(), &y.view());
66        assert_eq!(similarity, 0.6666666666666666); // All elements are mismatched
67    }
68
69    #[test]
70    fn test_matching_empty_vectors() {
71        let x = arr1::<f64>(&[]);
72        let y = arr1::<f64>(&[]);
73
74        let similarity = matching(&x.view(), &y.view());
75        assert!(similarity.is_nan()); // Empty vectors, no mismatches
76    }
77
78    #[test]
79    fn test_matching_zero_vector() {
80        let x = arr1(&[0.0, 0.0, 0.0]);
81        let y = arr1(&[1.0, 1.0, 1.0]);
82
83        let similarity = matching(&x.view(), &y.view());
84        assert_eq!(similarity, 1.0); // x is zero vector, y is all ones, all elements mismatch
85    }
86}