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}