rust_fuzzylogic/membership/
gaussian.rs

1use super::{Float, FuzzyError, MembershipFn};
2
3///validation function to check if sd is greater than 0.0 for Gaussian function.
4fn validate_positive(val: Float) -> Result<(), FuzzyError> {
5    if val <= 0.0 {
6        return Err(FuzzyError::OutOfBounds);
7    }
8    Ok(())
9}
10
11///Struct for gaussian membership function.
12///Initialize by calling the new() function.
13#[derive(Clone, Copy, PartialEq, Debug)]
14pub struct Gaussian {
15    ///sd is also commonly called sigma or standard deviation.
16    sd: Float,
17    mean: Float,
18    neg_two_sigma_sq: Float,
19}
20
21impl MembershipFn for Gaussian {
22    ///Evaluates the membership value for the input x against the membership struct.
23    fn eval(&self, x: Float) -> Float {
24        return ((x - self.mean).powi(2) / self.neg_two_sigma_sq).exp();
25    }
26}
27
28impl Gaussian {
29    ///Initializes the struct. Note that it requires sd > 0.0
30    pub fn new(sd: Float, mean: Float) -> crate::error::Result<Self> {
31        validate_positive(sd)?;
32        //precalculate and save constant "neg_two_sigma_sq" for performance at eval().
33        return Ok(Gaussian {
34            sd: sd,
35            mean: mean,
36            neg_two_sigma_sq: (-2.0 * sd.powi(2)),
37        });
38    }
39}
40
41#[cfg(test)]
42mod tests {
43    use crate::membership::gaussian::*;
44
45    #[test]
46    fn test_gaussian() {
47        let eps = crate::Float::EPSILON;
48        assert_eq!(Gaussian::new(0.0, 0.0), Err(FuzzyError::OutOfBounds));
49        let membership = Gaussian::new(1.0, 0.0);
50
51        assert!(membership.clone().unwrap().eval(100.0).abs() < eps);
52        assert!((membership.clone().unwrap().eval(0.0) - 1.0).abs() < eps);
53        assert_eq!(
54            membership.clone().unwrap().eval(-1.0),
55            membership.clone().unwrap().eval(1.0)
56        );
57    }
58}