statrs/statistics/
traits.rs

1use ::nalgebra::{
2    base::allocator::Allocator, base::dimension::DimName, DefaultAllocator, Dim, DimMin, U1,
3};
4use ::num_traits::float::Float;
5
6const STEPS: usize = 1_000;
7
8/// The `Min` trait specifies than an object has a minimum value
9pub trait Min<T> {
10    /// Returns the minimum value in the domain of a given distribution
11    /// if it exists, otherwise `None`.
12    ///
13    /// # Examples
14    ///
15    /// ```
16    /// use statrs::statistics::Min;
17    /// use statrs::distribution::Uniform;
18    ///
19    /// let n = Uniform::new(0.0, 1.0).unwrap();
20    /// assert_eq!(0.0, n.min());
21    /// ```
22    fn min(&self) -> T;
23}
24
25/// The `Max` trait specifies that an object has a maximum value
26pub trait Max<T> {
27    /// Returns the maximum value in the domain of a given distribution
28    /// if it exists, otherwise `None`.
29    ///
30    /// # Examples
31    ///
32    /// ```
33    /// use statrs::statistics::Max;
34    /// use statrs::distribution::Uniform;
35    ///
36    /// let n = Uniform::new(0.0, 1.0).unwrap();
37    /// assert_eq!(1.0, n.max());
38    /// ```
39    fn max(&self) -> T;
40}
41pub trait DiscreteDistribution<T: Float>: ::rand::distributions::Distribution<u64> {
42    /// Returns the mean, if it exists.
43    fn mean(&self) -> Option<T> {
44        None
45    }
46    /// Returns the variance, if it exists.
47    fn variance(&self) -> Option<T> {
48        None
49    }
50    /// Returns the standard deviation, if it exists.
51    fn std_dev(&self) -> Option<T> {
52        self.variance().map(|var| var.sqrt())
53    }
54    /// Returns the entropy, if it exists.
55    fn entropy(&self) -> Option<T> {
56        None
57    }
58    /// Returns the skewness, if it exists.
59    fn skewness(&self) -> Option<T> {
60        None
61    }
62}
63
64pub trait Distribution<T: Float>: ::rand::distributions::Distribution<T> {
65    /// Returns the mean, if it exists.
66    /// The default implementation returns an estimation
67    /// based on random samples. This is a crude estimate
68    /// for when no further information is known about the
69    /// distribution. More accurate statements about the
70    /// mean can and should be given by overriding the
71    /// default implementation.
72    ///
73    /// # Examples
74    ///
75    /// ```
76    /// use statrs::statistics::Distribution;
77    /// use statrs::distribution::Uniform;
78    ///
79    /// let n = Uniform::new(0.0, 1.0).unwrap();
80    /// assert_eq!(0.5, n.mean().unwrap());
81    /// ```
82    fn mean(&self) -> Option<T> {
83        // TODO: Does not need cryptographic rng
84        let mut rng = ::rand::rngs::OsRng;
85        let mut mean = T::zero();
86        let mut steps = T::zero();
87        for _ in 0..STEPS {
88            steps = steps + T::one();
89            mean = mean + Self::sample(self, &mut rng);
90        }
91        Some(mean / steps)
92    }
93    /// Returns the variance, if it exists.
94    /// The default implementation returns an estimation
95    /// based on random samples. This is a crude estimate
96    /// for when no further information is known about the
97    /// distribution. More accurate statements about the
98    /// variance can and should be given by overriding the
99    /// default implementation.
100    ///
101    /// # Examples
102    ///
103    /// ```
104    /// use statrs::statistics::Distribution;
105    /// use statrs::distribution::Uniform;
106    ///
107    /// let n = Uniform::new(0.0, 1.0).unwrap();
108    /// assert_eq!(1.0 / 12.0, n.variance().unwrap());
109    /// ```
110    fn variance(&self) -> Option<T> {
111        // TODO: Does not need cryptographic rng
112        let mut rng = ::rand::rngs::OsRng;
113        let mut mean = T::zero();
114        let mut variance = T::zero();
115        let mut steps = T::zero();
116        for _ in 0..STEPS {
117            steps = steps + T::one();
118            let sample = Self::sample(self, &mut rng);
119            variance = variance + (steps - T::one()) * (sample - mean) * (sample - mean) / steps;
120            mean = mean + (sample - mean) / steps;
121        }
122        steps = steps - T::one();
123        Some(variance / steps)
124    }
125    /// Returns the standard deviation, if it exists.
126    ///
127    /// # Examples
128    ///
129    /// ```
130    /// use statrs::statistics::Distribution;
131    /// use statrs::distribution::Uniform;
132    ///
133    /// let n = Uniform::new(0.0, 1.0).unwrap();
134    /// assert_eq!((1f64 / 12f64).sqrt(), n.std_dev().unwrap());
135    /// ```
136    fn std_dev(&self) -> Option<T> {
137        self.variance().map(|var| var.sqrt())
138    }
139    /// Returns the entropy, if it exists.
140    ///
141    /// # Examples
142    ///
143    /// ```
144    /// use statrs::statistics::Distribution;
145    /// use statrs::distribution::Uniform;
146    ///
147    /// let n = Uniform::new(0.0, 1.0).unwrap();
148    /// assert_eq!(0.0, n.entropy().unwrap());
149    /// ```
150    fn entropy(&self) -> Option<T> {
151        None
152    }
153    /// Returns the skewness, if it exists.
154    ///
155    /// # Examples
156    ///
157    /// ```
158    /// use statrs::statistics::Distribution;
159    /// use statrs::distribution::Uniform;
160    ///
161    /// let n = Uniform::new(0.0, 1.0).unwrap();
162    /// assert_eq!(0.0, n.skewness().unwrap());
163    /// ```
164    fn skewness(&self) -> Option<T> {
165        None
166    }
167}
168
169/// The `Mean` trait implements the calculation of a mean.
170// TODO: Clarify the traits of multidimensional distributions
171pub trait MeanN<T> {
172    fn mean(&self) -> Option<T>;
173}
174
175// TODO: Clarify the traits of multidimensional distributions
176pub trait VarianceN<T> {
177    fn variance(&self) -> Option<T>;
178}
179
180/// The `Median` trait returns the median of the distribution.
181pub trait Median<T> {
182    /// Returns the median.
183    ///
184    /// # Examples
185    ///
186    /// ```
187    /// use statrs::statistics::Median;
188    /// use statrs::distribution::Uniform;
189    ///
190    /// let n = Uniform::new(0.0, 1.0).unwrap();
191    /// assert_eq!(0.5, n.median());
192    /// ```
193    fn median(&self) -> T;
194}
195
196/// The `Mode` trait specifies that an object has a closed form solution
197/// for its mode(s)
198pub trait Mode<T> {
199    /// Returns the mode, if one exists.
200    ///
201    /// # Examples
202    ///
203    /// ```
204    /// use statrs::statistics::Mode;
205    /// use statrs::distribution::Uniform;
206    ///
207    /// let n = Uniform::new(0.0, 1.0).unwrap();
208    /// assert_eq!(Some(0.5), n.mode());
209    /// ```
210    fn mode(&self) -> T;
211}