algae_rs/
algaeset.rs

1/// A representation of a ZF set.
2///
3/// All elements must belong to a "supertype" `E`. Subsets of the supertype are
4/// determined by a given set of conditions (similar to the conditions used in
5/// the set construction paradigm of traditional ZF set theory).
6///
7/// Element existence (ie. whether or not a certain element is a member of a
8/// given set) is given through the [`has`](fn@AlgaeSet::has) function. Set
9/// unions are given by the [`or`](fn@AlgaeSet::or) function, and set
10/// intersections are given by the [`and`](fn@AlgaeSet::and) function.
11///
12/// # Examples
13///
14/// ```
15/// use algae_rs::algaeset::AlgaeSet;
16///
17/// let mut pos_floats = AlgaeSet::new(vec![
18///     Box::new(|e: f32| e > 0_f32)
19/// ]);
20///
21/// assert!(pos_floats.has(12_f32));
22///
23/// let neg_floats = AlgaeSet::new(vec![
24///     Box::new(|e: f32| e < 0_f32)
25/// ]);
26///
27/// pos_floats.or(neg_floats);
28/// let all_floats = pos_floats;
29/// assert!(all_floats.has(12_f32));
30/// assert!(all_floats.has(-12_f32));
31/// ```
32pub struct AlgaeSet<E> {
33    pos_conditions: Vec<Box<dyn Fn(E) -> bool>>,
34    neg_conditions: Vec<Box<dyn Fn(E) -> bool>>,
35}
36
37impl<E> AlgaeSet<E> {
38    /// Returns an AlgaeSet defined by a `Vec` of conditions
39    pub fn new(pos_conditions: Vec<Box<dyn Fn(E) -> bool>>) -> Self {
40        Self {
41            pos_conditions,
42            neg_conditions: vec![],
43        }
44    }
45
46    /// Returns an AlgaeSet defined by a single condition
47    pub fn mono(condition: Box<dyn Fn(E) -> bool>) -> Self {
48        Self::new(vec![condition])
49    }
50
51    /// Returns an AlgaeSet containing all members of the type `E`
52    pub fn all() -> Self {
53        Self {
54            pos_conditions: vec![Box::new(|_x: E| true)],
55            neg_conditions: vec![],
56        }
57    }
58}
59
60impl<E: Copy + Clone> AlgaeSet<E> {
61    /// Returns whether or not `element` is in the given set
62    pub fn has(&self, element: E) -> bool {
63        if self.neg_conditions.iter().any(|c| (c)(element)) {
64            return false;
65        }
66        return self.pos_conditions.iter().any(|c| (c)(element));
67    }
68}
69
70impl<E: PartialEq + Copy + Clone + 'static> AlgaeSet<E> {
71    /// Adds `element` to the given set
72    pub fn add(&mut self, element: E) {
73        self.neg_conditions.retain(|c| !(c)(element));
74        self.pos_conditions.push(Box::new(move |x: E| x == element))
75    }
76
77    /// Removes `element` from the given set
78    pub fn remove(&mut self, element: E) {
79        self.pos_conditions.retain(|c| (c)(element));
80        self.neg_conditions.push(Box::new(move |x: E| x == element))
81    }
82
83    /// Adds all elements from `other` to `self`
84    pub fn or(&mut self, other: Self) {
85        self.pos_conditions.push(Box::new(move |x: E| other.has(x)));
86    }
87
88    /// Removes all elements from `self` that aren't in `other`
89    pub fn and(&mut self, other: Self) {
90        self.neg_conditions
91            .push(Box::new(move |x: E| !other.has(x)));
92    }
93}
94
95#[cfg(test)]
96#[allow(non_snake_case)]
97mod tests {
98
99    use super::*;
100
101    mod infinite_set {
102
103        use super::*;
104
105        #[derive(PartialEq, Clone, Copy)]
106        enum Real {
107            UInt(u32),
108            SInt(i32),
109            Float(f32),
110        }
111
112        #[test]
113        fn has_element() {
114            let REALS = AlgaeSet::<Real>::all();
115            assert!(REALS.has(Real::UInt(12)));
116            assert!(REALS.has(Real::SInt(-42)));
117            assert!(REALS.has(Real::Float(-34.2)));
118        }
119
120        #[test]
121        fn remove_element() {
122            let mut REALS = AlgaeSet::<Real>::all();
123            REALS.remove(Real::Float(23.1));
124            assert!(REALS.has(Real::Float(23.2)));
125            assert!(!REALS.has(Real::Float(23.1)));
126        }
127
128        #[test]
129        fn add_after_remove() {
130            let mut REALS = AlgaeSet::<Real>::all();
131            REALS.remove(Real::Float(32.1));
132            assert!(!REALS.has(Real::Float(32.1)));
133            REALS.add(Real::Float(32.1));
134            assert!(REALS.has(Real::Float(32.1)));
135        }
136
137        #[test]
138        fn remove_after_add_after_remove() {
139            let mut REALS = AlgaeSet::<Real>::all();
140            assert!(REALS.has(Real::Float(32.1)));
141            REALS.remove(Real::Float(32.1));
142            assert!(!REALS.has(Real::Float(32.1)));
143            REALS.add(Real::Float(32.1));
144            assert!(REALS.has(Real::Float(32.1)));
145            REALS.remove(Real::Float(32.1));
146            assert!(!REALS.has(Real::Float(32.1)));
147        }
148
149        #[test]
150        fn overlapping_union() {
151            let REALS = AlgaeSet::<Real>::all();
152            let mut FLOATS = AlgaeSet::<Real>::mono(Box::new(|x: Real| match x {
153                Real::UInt(_) => false,
154                Real::SInt(_) => false,
155                Real::Float(_) => true,
156            }));
157            assert!(!FLOATS.has(Real::UInt(12)));
158            FLOATS.or(REALS);
159            assert!(FLOATS.has(Real::UInt(12)));
160        }
161
162        #[test]
163        fn encompassing_union() {
164            let mut REALS = AlgaeSet::<Real>::all();
165            let FLOATS = AlgaeSet::<Real>::mono(Box::new(|x: Real| match x {
166                Real::UInt(_) => false,
167                Real::SInt(_) => false,
168                Real::Float(_) => true,
169            }));
170            REALS.or(FLOATS);
171            assert!(REALS.has(Real::Float(12.0)));
172            assert!(REALS.has(Real::UInt(12)));
173            assert!(REALS.has(Real::SInt(-12)));
174        }
175
176        #[test]
177        fn disjoint_union() {
178            let UINTS = AlgaeSet::<Real>::mono(Box::new(|x: Real| match x {
179                Real::UInt(_) => true,
180                Real::SInt(_) => false,
181                Real::Float(_) => false,
182            }));
183            let mut FLOATS = AlgaeSet::<Real>::mono(Box::new(|x: Real| match x {
184                Real::UInt(_) => false,
185                Real::SInt(_) => false,
186                Real::Float(_) => true,
187            }));
188            assert!(FLOATS.has(Real::Float(12.0)));
189            assert!(!FLOATS.has(Real::UInt(12)));
190            FLOATS.or(UINTS);
191            assert!(FLOATS.has(Real::Float(12.0)));
192            assert!(FLOATS.has(Real::UInt(12)));
193        }
194
195        #[test]
196        fn overlapping_intersection() {
197            let REALS = AlgaeSet::<Real>::all();
198            let mut FLOATS = AlgaeSet::<Real>::mono(Box::new(|x: Real| match x {
199                Real::UInt(_) => false,
200                Real::SInt(_) => false,
201                Real::Float(_) => true,
202            }));
203            assert!(!FLOATS.has(Real::UInt(12)));
204            FLOATS.and(REALS);
205            assert!(!FLOATS.has(Real::UInt(12)));
206        }
207
208        #[test]
209        fn encompassing_intersection() {
210            let mut REALS = AlgaeSet::<Real>::all();
211            let FLOATS = AlgaeSet::<Real>::mono(Box::new(|x: Real| match x {
212                Real::UInt(_) => false,
213                Real::SInt(_) => false,
214                Real::Float(_) => true,
215            }));
216            assert!(REALS.has(Real::UInt(12)));
217            assert!(REALS.has(Real::SInt(-12)));
218            assert!(REALS.has(Real::Float(12.0)));
219            REALS.and(FLOATS);
220            assert!(REALS.has(Real::Float(12.0)));
221            assert!(!REALS.has(Real::UInt(12)));
222            assert!(!REALS.has(Real::SInt(-12)));
223        }
224
225        #[test]
226        fn disjoint_intersection() {
227            let UINTS = AlgaeSet::<Real>::mono(Box::new(|x: Real| match x {
228                Real::UInt(_) => true,
229                Real::SInt(_) => false,
230                Real::Float(_) => false,
231            }));
232            let mut FLOATS = AlgaeSet::<Real>::mono(Box::new(|x: Real| match x {
233                Real::UInt(_) => false,
234                Real::SInt(_) => false,
235                Real::Float(_) => true,
236            }));
237            assert!(FLOATS.has(Real::Float(12.0)));
238            assert!(!FLOATS.has(Real::UInt(12)));
239            FLOATS.and(UINTS);
240            assert!(!FLOATS.has(Real::Float(12.0)));
241            assert!(!FLOATS.has(Real::UInt(12)));
242        }
243    }
244
245    mod finite_set {
246
247        use super::*;
248
249        #[test]
250        fn has_element() {
251            let Z2 = AlgaeSet::<i32>::mono(Box::new(|x: i32| x % 2 == x));
252            assert!(Z2.has(1));
253            assert!(Z2.has(0));
254            assert!(!Z2.has(2));
255            assert!(!Z2.has(-2));
256        }
257
258        #[test]
259        fn add_element() {
260            let mut Z2 = AlgaeSet::<i32>::mono(Box::new(|x: i32| x % 2 == x));
261            assert!(!Z2.has(2));
262            Z2.add(2);
263            assert!(Z2.has(2));
264        }
265
266        #[test]
267        fn remove_element() {
268            let mut Z2 = AlgaeSet::<i32>::mono(Box::new(|x: i32| x % 2 == x));
269            assert!(Z2.has(1));
270            Z2.remove(1);
271            assert!(!Z2.has(1));
272        }
273
274        #[test]
275        fn overlapping_union() {
276            let mut Z2 = AlgaeSet::<i32>::mono(Box::new(|x: i32| x % 2 == x));
277            let Z3 = AlgaeSet::<i32>::mono(Box::new(|x: i32| x % 3 == x));
278            Z2.or(Z3);
279            assert!(Z2.has(0));
280            assert!(Z2.has(1));
281            assert!(Z2.has(2));
282        }
283
284        #[test]
285        fn encompassing_union() {
286            let Z2 = AlgaeSet::<i32>::mono(Box::new(|x: i32| x % 2 == x));
287            let mut Z3 = AlgaeSet::<i32>::mono(Box::new(|x: i32| x % 3 == x));
288            Z3.or(Z2);
289            assert!(Z3.has(0));
290            assert!(Z3.has(1));
291            assert!(Z3.has(2));
292        }
293
294        #[test]
295        fn disjoint_union() {
296            let mut one = AlgaeSet::<i32>::mono(Box::new(|x: i32| x == 1));
297            let two = AlgaeSet::<i32>::mono(Box::new(|x: i32| x == 2));
298            one.or(two);
299            assert!(one.has(1));
300            assert!(one.has(2));
301        }
302
303        #[test]
304        fn overlapping_intersection() {
305            let mut Z2 = AlgaeSet::<i32>::mono(Box::new(|x: i32| x % 2 == x));
306            let one = AlgaeSet::<i32>::mono(Box::new(|x: i32| x == 1));
307            Z2.and(one);
308            assert!(Z2.has(1));
309            assert!(!Z2.has(0));
310        }
311
312        #[test]
313        fn encompassing_intersection() {
314            let Z2 = AlgaeSet::<i32>::mono(Box::new(|x: i32| x % 2 == x));
315            let mut one = AlgaeSet::<i32>::mono(Box::new(|x: i32| x == 1));
316            one.and(Z2);
317            assert!(one.has(1));
318            assert!(!one.has(0));
319        }
320
321        #[test]
322        fn disjoint_intersection() {
323            let mut one = AlgaeSet::<i32>::mono(Box::new(|x: i32| x == 1));
324            let two = AlgaeSet::<i32>::mono(Box::new(|x: i32| x == 2));
325            one.and(two);
326            assert!(!one.has(1));
327            assert!(!one.has(2));
328        }
329    }
330}