pmrs/algo/transformation/ocel/features/
operator.rs

1use std::fmt;
2use std::iter::Iterator;
3use itertools::Itertools;
4use num_traits::Num;
5use num_traits::{FromPrimitive, ToPrimitive};
6use stats;
7use strum::{EnumString, EnumIter};
8
9#[derive(Debug, EnumString, EnumIter)]
10pub enum Operator {
11    Mean,
12    Median,
13    Mode,
14    StdDev,
15    Variance,
16    Min,
17    Max,
18    Count
19}
20
21impl fmt::Display for Operator {
22    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23        write!(f, "{:?}", self)
24    }
25}
26
27
28impl Operator {
29    pub fn execute<T, I>(&self, input_iter: I) -> Option<T> 
30        where I: Iterator<Item = T>, T: Num + ToPrimitive + PartialOrd + Clone + FromPrimitive {
31        
32        match self {
33            Operator::Mean => {
34                T::from_f64(stats::mean(input_iter))
35            }, 
36            Operator::Median => {
37                let ordered_iterator = input_iter.sorted_by(|a,b| a.partial_cmp(b).expect("A NaN value got into the iterator!"));
38                T::from_f64(stats::median(ordered_iterator).unwrap())
39            },
40            // any order
41            Operator::Mode => {
42                stats::mode(input_iter)
43            },
44            Operator::StdDev => {
45                T::from_f64(stats::stddev(input_iter))
46            },
47            Operator::Variance => {
48                T::from_f64(stats::variance(input_iter))
49            },
50            Operator::Min => {
51                input_iter.min_by(|a, b| a.partial_cmp(b).expect("A NaN value got into the iterator!"))
52            },
53            Operator::Max => {
54                input_iter.max_by(|a, b| a.partial_cmp(b).expect("A NaN value got into the iterator!"))
55            },
56            Operator::Count => {
57                T::from_usize(input_iter.count())
58            }
59        }
60    }
61    
62}
63
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68    const ERROR: f64 = 0.00001;
69
70    fn get_int_ord_vec() -> Vec<i32>{
71        vec![1,3,5,7,9]
72    }
73
74    fn get_int_parord_vec() -> Vec<i32>{
75        vec![1,3,5,5,9]
76    }
77
78    fn get_float_ord_vec() -> Vec<f64> {
79        vec![1.5, 2.4, 3.3, 4.2, 5.1]
80    }
81
82    fn get_float_parord_vec() -> Vec<f64> {
83        vec![1.5, 2.4, 3.3, 3.3, 5.1]
84    }
85
86
87    #[test]
88    fn test_mean_operator() {
89        let op = Operator::Mean;
90
91        let iov = get_int_ord_vec();
92        let ipv = get_int_parord_vec();
93        let fov = get_float_ord_vec();
94        let fpv = get_float_parord_vec();
95        
96        assert!((op.execute(iov.iter().map(|i| *i as f64)).unwrap().to_owned() - 5.0).abs() < ERROR);
97        assert!((op.execute(ipv.iter().map(|i| *i as f64)).unwrap().to_owned() - 4.6).abs() < ERROR);
98        assert!((op.execute(fov.iter().map(|i| *i)).unwrap().to_owned() - 3.3).abs() < ERROR);
99        assert!((op.execute(fpv.iter().map(|i| *i)).unwrap().to_owned() - 3.12).abs() < ERROR);
100
101        // mess with ordering
102        let riov: Vec<&i32> = iov.iter().rev().collect();
103        let ripv: Vec<&i32> = ipv.iter().rev().collect();
104        let rfov: Vec<&f64> = fov.iter().rev().collect();
105        let rfpv: Vec<&f64> = fpv.iter().rev().collect();
106        
107        assert!((op.execute(riov.iter().map(|i| **i as f64)).unwrap().to_owned() - 5.0).abs() < ERROR);
108        assert!((op.execute(ripv.iter().map(|i| **i as f64)).unwrap().to_owned() - 4.6).abs() < ERROR);
109        assert!((op.execute(rfov.iter().map(|i| **i)).unwrap().to_owned() - 3.3).abs() < ERROR);
110        assert!((op.execute(rfpv.iter().map(|i| **i)).unwrap().to_owned() - 3.12).abs() < ERROR);
111    }
112
113    #[test]
114    fn test_median_operator() {
115        let op = Operator::Median;
116
117        let iov = get_int_ord_vec();
118        let ipv = get_int_parord_vec();
119        let fov = get_float_ord_vec();
120        let fpv = get_float_parord_vec();
121        
122        assert!((op.execute(iov.iter().map(|i| *i as f64)).unwrap().to_owned() - 5.0).abs() < ERROR);
123        assert!((op.execute(ipv.iter().map(|i| *i as f64)).unwrap().to_owned() - 5.0).abs() < ERROR);
124        assert!((op.execute(fov.iter().map(|i| *i)).unwrap().to_owned() - 3.3).abs() < ERROR);
125        assert!((op.execute(fpv.iter().map(|i| *i)).unwrap().to_owned() - 3.3).abs() < ERROR);
126
127        // mess with ordering
128        let riov: Vec<&i32> = iov.iter().rev().collect();
129        let ripv: Vec<&i32> = ipv.iter().rev().collect();
130        let rfov: Vec<&f64> = fov.iter().rev().collect();
131        let rfpv: Vec<&f64> = fpv.iter().rev().collect();
132        
133        assert!((op.execute(riov.iter().map(|i| **i as f64)).unwrap().to_owned() - 5.0).abs() < ERROR);
134        assert!((op.execute(ripv.iter().map(|i| **i as f64)).unwrap().to_owned() - 5.0).abs() < ERROR);
135        assert!((op.execute(rfov.iter().map(|i| **i)).unwrap().to_owned() - 3.3).abs() < ERROR);
136        assert!((op.execute(rfpv.iter().map(|i| **i)).unwrap().to_owned() - 3.3).abs() < ERROR);
137    }
138
139    #[test]
140    fn test_mode_operator() {
141        let op = Operator::Mode;
142
143        let iov = get_int_ord_vec();
144        let ipv = get_int_parord_vec();
145        let fov = get_float_ord_vec();
146        let fpv = get_float_parord_vec();
147        
148        assert_eq!(op.execute(iov.iter().map(|i| *i as f64)), None);
149        assert!((op.execute(ipv.iter().map(|i| *i as f64)).unwrap().to_owned() - 5.0).abs() < ERROR);
150        assert_eq!(op.execute(fov.iter().map(|i| *i as f64)), None);
151        assert!((op.execute(fpv.iter().map(|i| *i)).unwrap().to_owned() - 3.3).abs() < ERROR);
152
153        // mess with ordering
154        let riov: Vec<&i32> = iov.iter().rev().collect();
155        let ripv: Vec<&i32> = ipv.iter().rev().collect();
156        let rfov: Vec<&f64> = fov.iter().rev().collect();
157        let rfpv: Vec<&f64> = fpv.iter().rev().collect();
158        
159        assert_eq!(op.execute(riov.iter().map(|i| **i as f64)), None);
160        assert!((op.execute(ripv.iter().map(|i| **i as f64)).unwrap().to_owned() - 5.0).abs() < ERROR);
161        assert_eq!(op.execute(rfov.iter().map(|i| **i as f64)), None);
162        assert!((op.execute(rfpv.iter().map(|i| **i)).unwrap().to_owned() - 3.3).abs() < ERROR);
163    }
164
165    #[test]
166    fn test_stddev_operator() {
167        let op = Operator::StdDev;
168
169        let iov = get_int_ord_vec();
170        let ipv = get_int_parord_vec();
171        let fov = get_float_ord_vec();
172        let fpv = get_float_parord_vec();
173
174        assert!((op.execute(iov.iter().map(|i| *i as f64)).unwrap().to_owned() - 2.82842712).abs() < ERROR);
175        assert!((op.execute(ipv.iter().map(|i| *i as f64)).unwrap().to_owned() - 2.65329983).abs() < ERROR);
176        assert!((op.execute(fov.iter().map(|i| *i)).unwrap().to_owned() - 1.2727922061).abs() < ERROR);
177        assert!((op.execute(fpv.iter().map(|i| *i)).unwrap().to_owned() - 1.1939849245).abs() < ERROR);
178
179        // mess with ordering
180        let riov: Vec<&i32> = iov.iter().rev().collect();
181        let ripv: Vec<&i32> = ipv.iter().rev().collect();
182        let rfov: Vec<&f64> = fov.iter().rev().collect();
183        let rfpv: Vec<&f64> = fpv.iter().rev().collect();
184        
185        assert!((op.execute(riov.iter().map(|i| **i as f64)).unwrap().to_owned() - 2.82842712).abs() < ERROR);
186        assert!((op.execute(ripv.iter().map(|i| **i as f64)).unwrap().to_owned() - 2.65329983).abs() < ERROR);
187        assert!((op.execute(rfov.iter().map(|i| **i)).unwrap().to_owned() - 1.2727922061).abs() < ERROR);
188        assert!((op.execute(rfpv.iter().map(|i| **i)).unwrap().to_owned() - 1.1939849245).abs() < ERROR);
189    }
190
191    #[test]
192    fn test_variance_operator() {
193        let op = Operator::Variance;
194
195        let iov = get_int_ord_vec();
196        let ipv = get_int_parord_vec();
197        let fov = get_float_ord_vec();
198        let fpv = get_float_parord_vec();
199
200        assert!((op.execute(iov.iter().map(|i| *i as f64)).unwrap().to_owned() - 8.0).abs() < ERROR);
201        assert!((op.execute(ipv.iter().map(|i| *i as f64)).unwrap().to_owned() - 7.04).abs() < ERROR);
202        assert!((op.execute(fov.iter().map(|i| *i)).unwrap().to_owned() - 1.62).abs() < ERROR);
203        assert!((op.execute(fpv.iter().map(|i| *i)).unwrap().to_owned() - 1.4256).abs() < ERROR);
204
205        // mess with ordering
206        let riov: Vec<&i32> = iov.iter().rev().collect();
207        let ripv: Vec<&i32> = ipv.iter().rev().collect();
208        let rfov: Vec<&f64> = fov.iter().rev().collect();
209        let rfpv: Vec<&f64> = fpv.iter().rev().collect();
210        
211        assert!((op.execute(riov.iter().map(|i| **i as f64)).unwrap().to_owned() - 8.0).abs() < ERROR);
212        assert!((op.execute(ripv.iter().map(|i| **i as f64)).unwrap().to_owned() - 7.04).abs() < ERROR);
213        assert!((op.execute(rfov.iter().map(|i| **i)).unwrap().to_owned() - 1.62).abs() < ERROR);
214        assert!((op.execute(rfpv.iter().map(|i| **i)).unwrap().to_owned() - 1.4256).abs() < ERROR);
215    }
216
217    #[test]
218    fn test_min_operator() {
219        let op = Operator::Min;
220
221        let iov = get_int_ord_vec();
222        let ipv = get_int_parord_vec();
223        let fov = get_float_ord_vec();
224        let fpv = get_float_parord_vec();
225        
226        assert_eq!(op.execute(iov.iter().map(|i| *i as f64)).unwrap() as i32, 1);
227        assert_eq!(op.execute(ipv.iter().map(|i| *i as f64)).unwrap() as i32, 1);
228        assert_eq!(op.execute(fov.iter().map(|i| *i as f64)).unwrap(), 1.5);
229        assert_eq!(op.execute(fpv.iter().map(|i| *i as f64)).unwrap(), 1.5);
230
231        // mess with ordering
232        let riov: Vec<&i32> = iov.iter().rev().collect();
233        let ripv: Vec<&i32> = ipv.iter().rev().collect();
234        let rfov: Vec<&f64> = fov.iter().rev().collect();
235        let rfpv: Vec<&f64> = fpv.iter().rev().collect();
236
237        assert_eq!(op.execute(riov.iter().map(|i| **i as f64)).unwrap() as i32, 1);
238        assert_eq!(op.execute(ripv.iter().map(|i| **i as f64)).unwrap() as i32, 1);
239        assert_eq!(op.execute(rfov.iter().map(|i| **i as f64)).unwrap(), 1.5);
240        assert_eq!(op.execute(rfpv.iter().map(|i| **i as f64)).unwrap(), 1.5);
241    }
242
243    #[test]
244    fn test_max_operator() {
245        let op = Operator::Max;
246
247        let iov = get_int_ord_vec();
248        let ipv = get_int_parord_vec();
249        let fov = get_float_ord_vec();
250        let fpv = get_float_parord_vec();
251        
252        assert_eq!(op.execute(iov.iter().map(|i| *i as f64)).unwrap() as i32, 9);
253        assert_eq!(op.execute(ipv.iter().map(|i| *i as f64)).unwrap() as i32, 9);
254        assert_eq!(op.execute(fov.iter().map(|i| *i as f64)).unwrap(), 5.1);
255        assert_eq!(op.execute(fpv.iter().map(|i| *i as f64)).unwrap(), 5.1);
256
257        // mess with ordering
258        let riov: Vec<&i32> = iov.iter().rev().collect();
259        let ripv: Vec<&i32> = ipv.iter().rev().collect();
260        let rfov: Vec<&f64> = fov.iter().rev().collect();
261        let rfpv: Vec<&f64> = fpv.iter().rev().collect();
262
263        assert_eq!(op.execute(riov.iter().map(|i| **i as f64)).unwrap() as i32, 9);
264        assert_eq!(op.execute(ripv.iter().map(|i| **i as f64)).unwrap() as i32, 9);
265        assert_eq!(op.execute(rfov.iter().map(|i| **i as f64)).unwrap(), 5.1);
266        assert_eq!(op.execute(rfpv.iter().map(|i| **i as f64)).unwrap(), 5.1);
267    }
268
269    #[test]
270    fn test_count_operator() {
271        let op = Operator::Count;
272
273        let iov = get_int_ord_vec();
274        let ipv = get_int_parord_vec();
275        let fov = get_float_ord_vec();
276        let fpv = get_float_parord_vec();
277        
278        assert_eq!(op.execute(iov.iter().map(|i| *i as usize)).unwrap(), 5);
279        assert_eq!(op.execute(ipv.iter().map(|i| *i as usize)).unwrap(), 5);
280        assert_eq!(op.execute(fov.iter().map(|i| *i as usize)).unwrap(), 5);
281        assert_eq!(op.execute(fpv.iter().map(|i| *i as usize)).unwrap(), 5);
282
283        // mess with ordering
284        let riov: Vec<&i32> = iov.iter().rev().collect();
285        let ripv: Vec<&i32> = ipv.iter().rev().collect();
286        let rfov: Vec<&f64> = fov.iter().rev().collect();
287        let rfpv: Vec<&f64> = fpv.iter().rev().collect();
288
289        assert_eq!(op.execute(riov.iter().map(|i| **i as usize)).unwrap(), 5);
290        assert_eq!(op.execute(ripv.iter().map(|i| **i as usize)).unwrap(), 5);
291        assert_eq!(op.execute(rfov.iter().map(|i| **i as usize)).unwrap(), 5);
292        assert_eq!(op.execute(rfpv.iter().map(|i| **i as usize)).unwrap(), 5);
293    }
294}