Skip to main content

oxilean_std/hashset/
functions.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use std::hash::Hash;
6
7use super::oxihashset_type::OxiHashSet;
8use super::types::{Bijection, MultiSet, UnionFind};
9
10/// A set of `String` values optimized for name lookups.
11///
12/// Used internally for tracking declared names, reserved identifiers, etc.
13pub type NameSet = OxiHashSet<String>;
14impl NameSet {
15    /// Insert a `&str` directly.
16    pub fn insert_str(&mut self, s: &str) -> bool {
17        self.insert(s.to_string())
18    }
19    /// Check whether the set contains the given `&str`.
20    pub fn contains_str(&self, s: &str) -> bool {
21        self.contains(&s.to_string())
22    }
23    /// Remove by `&str`.
24    pub fn remove_str(&mut self, s: &str) -> bool {
25        self.remove(&s.to_string())
26    }
27}
28/// A set of `u64` values, useful for tracking metavariable IDs.
29pub type U64Set = OxiHashSet<u64>;
30impl U64Set {
31    /// Return the minimum element if non-empty.
32    pub fn min_elem(&self) -> Option<u64> {
33        self.inner.iter().copied().min()
34    }
35    /// Return the maximum element if non-empty.
36    pub fn max_elem(&self) -> Option<u64> {
37        self.inner.iter().copied().max()
38    }
39    /// Return the sum of all elements.
40    pub fn sum(&self) -> u64 {
41        self.inner.iter().copied().sum()
42    }
43    /// Check whether the range `lo..=hi` is completely covered.
44    pub fn covers_range(&self, lo: u64, hi: u64) -> bool {
45        (lo..=hi).all(|i| self.inner.contains(&i))
46    }
47}
48/// A set of `usize` values.
49pub type UsizeSet = OxiHashSet<usize>;
50impl UsizeSet {
51    /// Check whether the indices `0..n` are all present.
52    pub fn covers_indices(&self, n: usize) -> bool {
53        (0..n).all(|i| self.contains(&i))
54    }
55    /// Return elements as a sorted vector.
56    pub fn sorted(&self) -> Vec<usize> {
57        let mut v = self.to_vec();
58        v.sort_unstable();
59        v
60    }
61}
62/// Compute the union of a collection of sets.
63pub fn big_union<T: Eq + Hash + Clone, I: IntoIterator<Item = OxiHashSet<T>>>(
64    sets: I,
65) -> OxiHashSet<T> {
66    sets.into_iter()
67        .fold(OxiHashSet::new(), |acc, s| acc.union(&s))
68}
69/// Compute the intersection of a collection of sets (empty input → empty set).
70pub fn big_intersection<T: Eq + Hash + Clone, I: IntoIterator<Item = OxiHashSet<T>>>(
71    sets: I,
72) -> OxiHashSet<T> {
73    let mut iter = sets.into_iter();
74    match iter.next() {
75        None => OxiHashSet::new(),
76        Some(first) => iter.fold(first, |acc, s| acc.intersection(&s)),
77    }
78}
79/// Return `true` if all sets in the collection are pairwise disjoint.
80pub fn pairwise_disjoint<T: Eq + Hash + Clone>(sets: &[OxiHashSet<T>]) -> bool {
81    for i in 0..sets.len() {
82        for j in (i + 1)..sets.len() {
83            if !sets[i].is_disjoint(&sets[j]) {
84                return false;
85            }
86        }
87    }
88    true
89}
90/// Compute the cartesian product of two sets as a set of pairs.
91pub fn cartesian_product<A, B>(a: &OxiHashSet<A>, b: &OxiHashSet<B>) -> OxiHashSet<(A, B)>
92where
93    A: Eq + Hash + Clone,
94    B: Eq + Hash + Clone,
95{
96    let mut result = OxiHashSet::new();
97    for x in a.iter() {
98        for y in b.iter() {
99            result.insert((x.clone(), y.clone()));
100        }
101    }
102    result
103}
104/// Build a set from a range `lo..hi`.
105pub fn range_set(lo: u64, hi: u64) -> U64Set {
106    U64Set::from_iter(lo..hi)
107}
108/// Check whether two sets have exactly the same elements (alias for `==`).
109pub fn set_equal<T: Eq + Hash + Clone>(a: &OxiHashSet<T>, b: &OxiHashSet<T>) -> bool {
110    a == b
111}
112/// Return the number of elements present in exactly one of the two sets.
113pub fn symmetric_diff_size<T: Eq + Hash + Clone>(a: &OxiHashSet<T>, b: &OxiHashSet<T>) -> usize {
114    a.symmetric_difference(b).len()
115}
116/// Convert a `Vec<T>` to a `OxiHashSet<T>`, discarding duplicates.
117pub fn deduplicate<T: Eq + Hash + Clone>(v: Vec<T>) -> OxiHashSet<T> {
118    OxiHashSet::from_iter(v)
119}
120/// Return elements that appear in `a` but not in any set in `others`.
121pub fn difference_all<'a, T: Eq + Hash + Clone + 'a>(
122    a: &OxiHashSet<T>,
123    others: impl Iterator<Item = &'a OxiHashSet<T>>,
124) -> OxiHashSet<T> {
125    others.fold(a.clone(), |acc, s| acc.difference(s))
126}
127#[cfg(test)]
128mod tests {
129    use super::*;
130    fn mk_set(v: Vec<i32>) -> OxiHashSet<i32> {
131        OxiHashSet::from_iter(v)
132    }
133    #[test]
134    fn test_insert_contains_len() {
135        let mut s = OxiHashSet::new();
136        assert!(s.insert(1));
137        assert!(!s.insert(1));
138        assert!(s.contains(&1));
139        assert_eq!(s.len(), 1);
140    }
141    #[test]
142    fn test_remove() {
143        let mut s = mk_set(vec![1, 2, 3]);
144        assert!(s.remove(&2));
145        assert!(!s.contains(&2));
146        assert_eq!(s.len(), 2);
147    }
148    #[test]
149    fn test_union() {
150        let a = mk_set(vec![1, 2]);
151        let b = mk_set(vec![2, 3]);
152        let u = a.union(&b);
153        assert_eq!(u.len(), 3);
154        assert!(u.contains(&1) && u.contains(&2) && u.contains(&3));
155    }
156    #[test]
157    fn test_intersection() {
158        let a = mk_set(vec![1, 2, 3]);
159        let b = mk_set(vec![2, 3, 4]);
160        let i = a.intersection(&b);
161        assert_eq!(i.len(), 2);
162        assert!(i.contains(&2) && i.contains(&3));
163    }
164    #[test]
165    fn test_difference() {
166        let a = mk_set(vec![1, 2, 3]);
167        let b = mk_set(vec![2]);
168        let d = a.difference(&b);
169        assert!(d.contains(&1) && d.contains(&3));
170        assert!(!d.contains(&2));
171    }
172    #[test]
173    fn test_is_subset_superset() {
174        let a = mk_set(vec![1, 2]);
175        let b = mk_set(vec![1, 2, 3]);
176        assert!(a.is_subset(&b));
177        assert!(b.is_superset(&a));
178        assert!(!b.is_subset(&a));
179    }
180    #[test]
181    fn test_is_disjoint() {
182        let a = mk_set(vec![1, 2]);
183        let b = mk_set(vec![3, 4]);
184        assert!(a.is_disjoint(&b));
185        let c = mk_set(vec![2, 5]);
186        assert!(!a.is_disjoint(&c));
187    }
188    #[test]
189    fn test_map() {
190        let a = mk_set(vec![1, 2, 3]);
191        let doubled: OxiHashSet<i32> = a.map(|x| x * 2);
192        assert!(doubled.contains(&2) && doubled.contains(&4) && doubled.contains(&6));
193    }
194    #[test]
195    fn test_retain_clone() {
196        let a = mk_set(vec![1, 2, 3, 4]);
197        let evens = a.retain_clone(|x| x % 2 == 0);
198        assert_eq!(evens.len(), 2);
199        assert!(evens.contains(&2) && evens.contains(&4));
200    }
201    #[test]
202    fn test_fold() {
203        let a = mk_set(vec![1, 2, 3, 4]);
204        let sum = a.fold(0, |acc, x| acc + x);
205        assert_eq!(sum, 10);
206    }
207    #[test]
208    fn test_any_all() {
209        let a = mk_set(vec![2, 4, 6]);
210        assert!(a.all(|x| x % 2 == 0));
211        assert!(a.any(|x| *x == 4));
212        assert!(!a.any(|x| *x == 3));
213    }
214    #[test]
215    fn test_partition() {
216        let a = mk_set(vec![1, 2, 3, 4, 5]);
217        let (evens, odds) = a.partition(|x| x % 2 == 0);
218        assert_eq!(evens.len(), 2);
219        assert_eq!(odds.len(), 3);
220    }
221    #[test]
222    fn test_singleton() {
223        let s = OxiHashSet::singleton(42i32);
224        assert_eq!(s.len(), 1);
225        assert!(s.contains(&42));
226    }
227    #[test]
228    fn test_name_set() {
229        let mut ns = NameSet::new();
230        ns.insert_str("foo");
231        ns.insert_str("bar");
232        assert!(ns.contains_str("foo"));
233        ns.remove_str("foo");
234        assert!(!ns.contains_str("foo"));
235    }
236    #[test]
237    fn test_u64_set_min_max() {
238        let s = U64Set::from_iter(vec![10u64, 3, 7]);
239        assert_eq!(s.min_elem(), Some(3));
240        assert_eq!(s.max_elem(), Some(10));
241        assert_eq!(s.sum(), 20);
242    }
243    #[test]
244    fn test_big_union() {
245        let sets = vec![mk_set(vec![1, 2]), mk_set(vec![3]), mk_set(vec![2, 4])];
246        let u = big_union(sets);
247        assert_eq!(u.len(), 4);
248    }
249    #[test]
250    fn test_big_intersection() {
251        let sets = vec![
252            mk_set(vec![1, 2, 3]),
253            mk_set(vec![2, 3, 4]),
254            mk_set(vec![3, 5]),
255        ];
256        let i = big_intersection(sets);
257        assert_eq!(i.len(), 1);
258        assert!(i.contains(&3));
259    }
260    #[test]
261    fn test_pairwise_disjoint() {
262        let sets = vec![mk_set(vec![1]), mk_set(vec![2]), mk_set(vec![3])];
263        assert!(pairwise_disjoint(&sets));
264        let overlapping = vec![mk_set(vec![1, 2]), mk_set(vec![2, 3])];
265        assert!(!pairwise_disjoint(&overlapping));
266    }
267    #[test]
268    fn test_cartesian_product() {
269        let a = mk_set(vec![1, 2]);
270        let b = mk_set(vec![10, 20]);
271        let prod = cartesian_product(&a, &b);
272        assert_eq!(prod.len(), 4);
273    }
274    #[test]
275    fn test_range_set() {
276        let r = range_set(0, 5);
277        assert_eq!(r.len(), 5);
278        assert!(r.covers_range(0, 4));
279    }
280    #[test]
281    fn test_jaccard() {
282        let a = mk_set(vec![1, 2, 3]);
283        let b = mk_set(vec![2, 3, 4]);
284        let j = a.jaccard(&b);
285        assert!((j - 0.5).abs() < 1e-10);
286    }
287    #[test]
288    fn test_symmetric_difference() {
289        let a = mk_set(vec![1, 2, 3]);
290        let b = mk_set(vec![3, 4, 5]);
291        let sd = a.symmetric_difference(&b);
292        assert_eq!(sd.len(), 4);
293        assert!(sd.contains(&1) && sd.contains(&2) && sd.contains(&4) && sd.contains(&5));
294        assert!(!sd.contains(&3));
295    }
296    #[test]
297    fn test_flat_map() {
298        let a = mk_set(vec![1, 2]);
299        let result: OxiHashSet<i32> = a.flat_map(|x| OxiHashSet::from_iter(vec![*x, x * 10]));
300        assert!(result.contains(&1) && result.contains(&10));
301        assert!(result.contains(&2) && result.contains(&20));
302    }
303    #[test]
304    fn test_power_set() {
305        let s = mk_set(vec![1, 2]);
306        let ps = s.power_set();
307        assert_eq!(ps.len(), 4);
308    }
309    #[test]
310    fn test_usize_set_sorted() {
311        let s = UsizeSet::from_iter(vec![3, 1, 4, 1, 5, 9, 2, 6]);
312        let sorted = s.sorted();
313        let expected: Vec<usize> = (1..=9)
314            .filter(|&x| [1, 2, 3, 4, 5, 6, 9].contains(&x))
315            .collect();
316        assert_eq!(sorted, expected);
317    }
318    #[test]
319    fn test_extend() {
320        let mut s = mk_set(vec![1]);
321        s.extend(vec![2, 3, 4]);
322        assert_eq!(s.len(), 4);
323    }
324    #[test]
325    fn test_clear() {
326        let mut s = mk_set(vec![1, 2, 3]);
327        s.clear();
328        assert!(s.is_empty());
329    }
330}
331#[cfg(test)]
332mod extra_tests {
333    use super::*;
334    #[test]
335    fn test_multiset_insert_count() {
336        let mut ms = MultiSet::new();
337        ms.insert(1i32);
338        ms.insert(1i32);
339        ms.insert(2i32);
340        assert_eq!(ms.count(&1), 2);
341        assert_eq!(ms.count(&2), 1);
342        assert_eq!(ms.total(), 3);
343        assert_eq!(ms.distinct_count(), 2);
344    }
345    #[test]
346    fn test_multiset_remove_one() {
347        let mut ms = MultiSet::from(vec![1i32, 1, 2]);
348        ms.remove_one(&1);
349        assert_eq!(ms.count(&1), 1);
350        ms.remove_one(&1);
351        assert_eq!(ms.count(&1), 0);
352        assert!(!ms.contains(&1));
353    }
354    #[test]
355    fn test_multiset_to_set() {
356        let ms = MultiSet::from(vec![1i32, 1, 2, 3]);
357        let s = ms.to_set();
358        assert_eq!(s.len(), 3);
359    }
360    #[test]
361    fn test_bijection_insert_forward_backward() {
362        let mut bij: Bijection<i32, &str> = Bijection::new();
363        assert!(bij.insert(1, "one"));
364        assert!(bij.insert(2, "two"));
365        assert_eq!(bij.forward(&1), Some(&"one"));
366        assert_eq!(bij.backward(&"one"), Some(&1));
367        assert_eq!(bij.len(), 2);
368    }
369    #[test]
370    fn test_bijection_no_duplicate() {
371        let mut bij: Bijection<i32, i32> = Bijection::new();
372        bij.insert(1, 10);
373        assert!(!bij.insert(1, 20));
374        assert!(!bij.insert(2, 10));
375    }
376    #[test]
377    fn test_union_find_basic() {
378        let mut uf = UnionFind::new(5);
379        assert!(!uf.same(0, 1));
380        uf.union(0, 1);
381        assert!(uf.same(0, 1));
382        uf.union(1, 2);
383        assert!(uf.same(0, 2));
384        assert!(!uf.same(0, 3));
385    }
386    #[test]
387    fn test_union_find_component_count() {
388        let mut uf = UnionFind::new(6);
389        assert_eq!(uf.component_count(), 6);
390        uf.union(0, 1);
391        uf.union(2, 3);
392        assert_eq!(uf.component_count(), 4);
393    }
394    #[test]
395    fn test_union_find_component_of() {
396        let mut uf = UnionFind::new(4);
397        uf.union(0, 1);
398        uf.union(1, 2);
399        let comp = uf.component_of(0);
400        assert_eq!(comp.len(), 3);
401        assert!(comp.contains(&0) && comp.contains(&1) && comp.contains(&2));
402    }
403    #[test]
404    fn test_sorted_vec() {
405        let s = OxiHashSet::from_iter(vec![3i32, 1, 4, 1, 5, 9, 2, 6]);
406        let sorted = s.sorted_vec();
407        let expected = vec![1, 2, 3, 4, 5, 6, 9];
408        assert_eq!(sorted, expected);
409    }
410    #[test]
411    fn test_min_max_ord() {
412        let s = OxiHashSet::from_iter(vec![3i32, 1, 4, 2]);
413        assert_eq!(s.min(), Some(&1));
414        assert_eq!(s.max(), Some(&4));
415    }
416    #[test]
417    fn test_difference_all() {
418        let a = OxiHashSet::from_iter(vec![1i32, 2, 3, 4, 5]);
419        let others: Vec<OxiHashSet<i32>> = vec![
420            OxiHashSet::from_iter(vec![1]),
421            OxiHashSet::from_iter(vec![3]),
422        ];
423        let result = difference_all(&a, others.iter());
424        assert_eq!(result.len(), 3);
425        assert!(result.contains(&2) && result.contains(&4) && result.contains(&5));
426    }
427}
428/// Build the standard HashSet environment declarations.
429///
430/// Registers the `HashSet` type constructor and its core operations as axioms
431/// in the OxiLean kernel environment.
432pub fn build_hashset_env(env: &mut oxilean_kernel::Environment) -> Result<(), String> {
433    use oxilean_kernel::{BinderInfo as Bi, Declaration, Expr, Level, Name};
434    let mut add = |name: &str, ty: Expr| -> Result<(), String> {
435        match env.add(Declaration::Axiom {
436            name: Name::str(name),
437            univ_params: vec![],
438            ty,
439        }) {
440            Ok(()) | Err(_) => Ok(()),
441        }
442    };
443    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
444    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
445    let arr = |a: Expr, b: Expr| -> Expr {
446        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
447    };
448    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
449    let nat_ty = || -> Expr { cst("Nat") };
450    let bool_ty = || -> Expr { cst("Bool") };
451    let list_of = |ty: Expr| -> Expr { app(cst("List"), ty) };
452    let hashset_of = |ty: Expr| -> Expr { app(cst("HashSet"), ty) };
453    let option_of = |ty: Expr| -> Expr { app(cst("Option"), ty) };
454    add("HashSet", arr(type1(), type1()))?;
455    let empty_ty = Expr::Pi(
456        Bi::Implicit,
457        Name::str("α"),
458        Box::new(type1()),
459        Box::new(hashset_of(Expr::BVar(0))),
460    );
461    add("HashSet.empty", empty_ty)?;
462    let insert_ty = Expr::Pi(
463        Bi::Implicit,
464        Name::str("α"),
465        Box::new(type1()),
466        Box::new(arr(
467            Expr::BVar(0),
468            arr(hashset_of(Expr::BVar(1)), hashset_of(Expr::BVar(2))),
469        )),
470    );
471    add("HashSet.insert", insert_ty)?;
472    let contains_ty = Expr::Pi(
473        Bi::Implicit,
474        Name::str("α"),
475        Box::new(type1()),
476        Box::new(arr(
477            hashset_of(Expr::BVar(0)),
478            arr(Expr::BVar(1), bool_ty()),
479        )),
480    );
481    add("HashSet.contains", contains_ty)?;
482    let erase_ty = Expr::Pi(
483        Bi::Implicit,
484        Name::str("α"),
485        Box::new(type1()),
486        Box::new(arr(
487            hashset_of(Expr::BVar(0)),
488            arr(Expr::BVar(1), hashset_of(Expr::BVar(2))),
489        )),
490    );
491    add("HashSet.erase", erase_ty)?;
492    let size_ty = Expr::Pi(
493        Bi::Implicit,
494        Name::str("α"),
495        Box::new(type1()),
496        Box::new(arr(hashset_of(Expr::BVar(0)), nat_ty())),
497    );
498    add("HashSet.size", size_ty)?;
499    let is_empty_ty = Expr::Pi(
500        Bi::Implicit,
501        Name::str("α"),
502        Box::new(type1()),
503        Box::new(arr(hashset_of(Expr::BVar(0)), bool_ty())),
504    );
505    add("HashSet.isEmpty", is_empty_ty)?;
506    let to_list_ty = Expr::Pi(
507        Bi::Implicit,
508        Name::str("α"),
509        Box::new(type1()),
510        Box::new(arr(hashset_of(Expr::BVar(0)), list_of(Expr::BVar(1)))),
511    );
512    add("HashSet.toList", to_list_ty)?;
513    let of_list_ty = Expr::Pi(
514        Bi::Implicit,
515        Name::str("α"),
516        Box::new(type1()),
517        Box::new(arr(list_of(Expr::BVar(0)), hashset_of(Expr::BVar(1)))),
518    );
519    add("HashSet.ofList", of_list_ty)?;
520    let union_ty = Expr::Pi(
521        Bi::Implicit,
522        Name::str("α"),
523        Box::new(type1()),
524        Box::new(arr(
525            hashset_of(Expr::BVar(0)),
526            arr(hashset_of(Expr::BVar(1)), hashset_of(Expr::BVar(2))),
527        )),
528    );
529    add("HashSet.union", union_ty)?;
530    let inter_ty = Expr::Pi(
531        Bi::Implicit,
532        Name::str("α"),
533        Box::new(type1()),
534        Box::new(arr(
535            hashset_of(Expr::BVar(0)),
536            arr(hashset_of(Expr::BVar(1)), hashset_of(Expr::BVar(2))),
537        )),
538    );
539    add("HashSet.inter", inter_ty)?;
540    let sdiff_ty = Expr::Pi(
541        Bi::Implicit,
542        Name::str("α"),
543        Box::new(type1()),
544        Box::new(arr(
545            hashset_of(Expr::BVar(0)),
546            arr(hashset_of(Expr::BVar(1)), hashset_of(Expr::BVar(2))),
547        )),
548    );
549    add("HashSet.sdiff", sdiff_ty)?;
550    let subset_ty = Expr::Pi(
551        Bi::Implicit,
552        Name::str("α"),
553        Box::new(type1()),
554        Box::new(arr(
555            hashset_of(Expr::BVar(0)),
556            arr(hashset_of(Expr::BVar(1)), bool_ty()),
557        )),
558    );
559    add("HashSet.subset", subset_ty)?;
560    let filter_ty = Expr::Pi(
561        Bi::Implicit,
562        Name::str("α"),
563        Box::new(type1()),
564        Box::new(arr(
565            arr(Expr::BVar(0), bool_ty()),
566            arr(hashset_of(Expr::BVar(1)), hashset_of(Expr::BVar(2))),
567        )),
568    );
569    add("HashSet.filter", filter_ty)?;
570    let fold_ty = Expr::Pi(
571        Bi::Implicit,
572        Name::str("α"),
573        Box::new(type1()),
574        Box::new(Expr::Pi(
575            Bi::Implicit,
576            Name::str("β"),
577            Box::new(type1()),
578            Box::new(arr(
579                arr(Expr::BVar(0), arr(Expr::BVar(1), Expr::BVar(2))),
580                arr(Expr::BVar(3), arr(hashset_of(Expr::BVar(4)), Expr::BVar(5))),
581            )),
582        )),
583    );
584    add("HashSet.fold", fold_ty)?;
585    let any_ty = Expr::Pi(
586        Bi::Implicit,
587        Name::str("α"),
588        Box::new(type1()),
589        Box::new(arr(
590            arr(Expr::BVar(0), bool_ty()),
591            arr(hashset_of(Expr::BVar(1)), bool_ty()),
592        )),
593    );
594    add("HashSet.any", any_ty)?;
595    let all_ty = Expr::Pi(
596        Bi::Implicit,
597        Name::str("α"),
598        Box::new(type1()),
599        Box::new(arr(
600            arr(Expr::BVar(0), bool_ty()),
601            arr(hashset_of(Expr::BVar(1)), bool_ty()),
602        )),
603    );
604    add("HashSet.all", all_ty)?;
605    let find_first_ty = Expr::Pi(
606        Bi::Implicit,
607        Name::str("α"),
608        Box::new(type1()),
609        Box::new(arr(
610            arr(Expr::BVar(0), bool_ty()),
611            arr(hashset_of(Expr::BVar(1)), option_of(Expr::BVar(2))),
612        )),
613    );
614    add("HashSet.findFirst?", find_first_ty)?;
615    Ok(())
616}
617/// Compute the symmetric difference of two sets.
618pub fn symmetric_difference<T: Eq + Hash + Clone>(
619    a: &OxiHashSet<T>,
620    b: &OxiHashSet<T>,
621) -> OxiHashSet<T> {
622    let mut result = OxiHashSet::new();
623    for x in a.iter() {
624        if !b.contains(x) {
625            result.insert(x.clone());
626        }
627    }
628    for x in b.iter() {
629        if !a.contains(x) {
630            result.insert(x.clone());
631        }
632    }
633    result
634}
635/// Check if two sets are disjoint (no elements in common).
636pub fn are_disjoint<T: Eq + Hash + Clone>(a: &OxiHashSet<T>, b: &OxiHashSet<T>) -> bool {
637    a.iter().all(|x| !b.contains(x))
638}
639/// Partition a set into elements satisfying and not satisfying a predicate.
640pub fn partition<T, P>(set: &OxiHashSet<T>, pred: P) -> (OxiHashSet<T>, OxiHashSet<T>)
641where
642    T: Eq + Hash + Clone,
643    P: Fn(&T) -> bool,
644{
645    let mut yes = OxiHashSet::new();
646    let mut no = OxiHashSet::new();
647    for x in set.iter() {
648        if pred(x) {
649            yes.insert(x.clone());
650        } else {
651            no.insert(x.clone());
652        }
653    }
654    (yes, no)
655}
656/// Build a set from an exclusive range `[start, end)`.
657pub fn range_set_i64(start: i64, end: i64) -> OxiHashSet<i64> {
658    OxiHashSet::from_iter(start..end)
659}
660/// Check whether the set forms a contiguous range `[min, max]`.
661pub fn is_contiguous_range(set: &OxiHashSet<i64>) -> bool {
662    if set.is_empty() {
663        return true;
664    }
665    let mut v: Vec<i64> = set.iter().cloned().collect();
666    v.sort();
667    v.windows(2).all(|w| w[1] == w[0] + 1)
668}
669#[cfg(test)]
670mod hashset_extra_tests {
671    use super::*;
672    #[test]
673    fn test_symmetric_difference() {
674        let a = OxiHashSet::from_iter(vec![1i32, 2, 3]);
675        let b = OxiHashSet::from_iter(vec![2i32, 3, 4]);
676        let sym = symmetric_difference(&a, &b);
677        assert_eq!(sym.len(), 2);
678        assert!(sym.contains(&1));
679        assert!(sym.contains(&4));
680        assert!(!sym.contains(&2));
681    }
682    #[test]
683    fn test_are_disjoint_true() {
684        let a = OxiHashSet::from_iter(vec![1i32, 2]);
685        let b = OxiHashSet::from_iter(vec![3i32, 4]);
686        assert!(are_disjoint(&a, &b));
687    }
688    #[test]
689    fn test_are_disjoint_false() {
690        let a = OxiHashSet::from_iter(vec![1i32, 2, 3]);
691        let b = OxiHashSet::from_iter(vec![3i32, 4, 5]);
692        assert!(!are_disjoint(&a, &b));
693    }
694    #[test]
695    fn test_partition() {
696        let s = OxiHashSet::from_iter(vec![1i32, 2, 3, 4, 5]);
697        let (evens, odds) = partition(&s, |x| x % 2 == 0);
698        assert_eq!(evens.len(), 2);
699        assert_eq!(odds.len(), 3);
700        assert!(evens.contains(&2) && evens.contains(&4));
701        assert!(odds.contains(&1) && odds.contains(&3) && odds.contains(&5));
702    }
703    #[test]
704    fn test_range_set_i64() {
705        let s = range_set_i64(1, 6);
706        assert_eq!(s.len(), 5);
707        for i in 1..6 {
708            assert!(s.contains(&i));
709        }
710    }
711    #[test]
712    fn test_is_contiguous_range_true() {
713        let s = range_set_i64(3, 8);
714        assert!(is_contiguous_range(&s));
715    }
716    #[test]
717    fn test_is_contiguous_range_false() {
718        let s = OxiHashSet::from_iter(vec![1i64, 2, 4, 5]);
719        assert!(!is_contiguous_range(&s));
720    }
721    #[test]
722    fn test_is_contiguous_range_empty() {
723        let s: OxiHashSet<i64> = OxiHashSet::new();
724        assert!(is_contiguous_range(&s));
725    }
726    #[test]
727    fn test_to_sorted_vec() {
728        let s = OxiHashSet::from_iter(vec![5i32, 3, 1, 4, 2]);
729        let v = s.to_sorted_vec();
730        assert_eq!(v, vec![1, 2, 3, 4, 5]);
731    }
732}
733pub fn hs_ext_finite_set_type(
734    add: &mut impl FnMut(&str, oxilean_kernel::Expr) -> Result<(), String>,
735) -> Result<(), String> {
736    use oxilean_kernel::{BinderInfo as Bi, Expr, Level, Name};
737    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
738    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
739    let arr = |a: Expr, b: Expr| -> Expr {
740        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
741    };
742    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
743    let hashset_of = |ty: Expr| -> Expr { app(cst("HashSet"), ty) };
744    let is_finite_ty = Expr::Pi(
745        Bi::Implicit,
746        Name::str("α"),
747        Box::new(type1()),
748        Box::new(arr(hashset_of(Expr::BVar(0)), cst("Prop"))),
749    );
750    add("HashSet.isFinite", is_finite_ty)?;
751    let as_finite_ty = Expr::Pi(
752        Bi::Implicit,
753        Name::str("α"),
754        Box::new(type1()),
755        Box::new(arr(hashset_of(Expr::BVar(0)), type1())),
756    );
757    add("HashSet.asFiniteSubset", as_finite_ty)?;
758    Ok(())
759}
760pub fn hs_ext_membership_axioms(
761    add: &mut impl FnMut(&str, oxilean_kernel::Expr) -> Result<(), String>,
762) -> Result<(), String> {
763    use oxilean_kernel::{BinderInfo as Bi, Expr, Level, Name};
764    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
765    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
766    let arr = |a: Expr, b: Expr| -> Expr {
767        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
768    };
769    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
770    let prop = || -> Expr { Expr::Sort(Level::zero()) };
771    let bool_ty = || -> Expr { cst("Bool") };
772    let hashset_of = |ty: Expr| -> Expr { app(cst("HashSet"), ty) };
773    let mem_ty = Expr::Pi(
774        Bi::Implicit,
775        Name::str("α"),
776        Box::new(type1()),
777        Box::new(arr(Expr::BVar(0), arr(hashset_of(Expr::BVar(1)), prop()))),
778    );
779    add("HashSet.mem", mem_ty)?;
780    let mem_iff_ty = Expr::Pi(
781        Bi::Implicit,
782        Name::str("α"),
783        Box::new(type1()),
784        Box::new(arr(
785            hashset_of(Expr::BVar(0)),
786            arr(
787                Expr::BVar(1),
788                app(
789                    app(
790                        cst("Iff"),
791                        app(app(cst("HashSet.mem"), Expr::BVar(2)), Expr::BVar(1)),
792                    ),
793                    app(
794                        app(
795                            cst("Eq"),
796                            app(app(cst("HashSet.contains"), Expr::BVar(2)), Expr::BVar(1)),
797                        ),
798                        bool_ty(),
799                    ),
800                ),
801            ),
802        )),
803    );
804    add("HashSet.mem_iff_contains", mem_iff_ty)?;
805    let not_mem_empty_ty = Expr::Pi(
806        Bi::Implicit,
807        Name::str("α"),
808        Box::new(type1()),
809        Box::new(arr(
810            Expr::BVar(0),
811            arr(
812                app(app(cst("HashSet.mem"), Expr::BVar(1)), cst("HashSet.empty")),
813                cst("False"),
814            ),
815        )),
816    );
817    add("HashSet.not_mem_empty", not_mem_empty_ty)?;
818    Ok(())
819}
820pub fn hs_ext_insert_delete_axioms(
821    add: &mut impl FnMut(&str, oxilean_kernel::Expr) -> Result<(), String>,
822) -> Result<(), String> {
823    use oxilean_kernel::{BinderInfo as Bi, Expr, Level, Name};
824    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
825    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
826    let arr = |a: Expr, b: Expr| -> Expr {
827        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
828    };
829    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
830    let _prop = || -> Expr { Expr::Sort(Level::zero()) };
831    let hashset_of = |ty: Expr| -> Expr { app(cst("HashSet"), ty) };
832    let mem_insert_ty = Expr::Pi(
833        Bi::Implicit,
834        Name::str("α"),
835        Box::new(type1()),
836        Box::new(arr(
837            Expr::BVar(0),
838            arr(
839                Expr::BVar(1),
840                arr(
841                    hashset_of(Expr::BVar(2)),
842                    app(
843                        app(
844                            cst("Iff"),
845                            app(
846                                app(cst("HashSet.mem"), Expr::BVar(0)),
847                                app(app(cst("HashSet.insert"), Expr::BVar(1)), Expr::BVar(2)),
848                            ),
849                        ),
850                        app(
851                            app(cst("Or"), app(app(cst("Eq"), Expr::BVar(0)), Expr::BVar(1))),
852                            app(app(cst("HashSet.mem"), Expr::BVar(0)), Expr::BVar(2)),
853                        ),
854                    ),
855                ),
856            ),
857        )),
858    );
859    add("HashSet.mem_insert", mem_insert_ty)?;
860    let mem_erase_ty = Expr::Pi(
861        Bi::Implicit,
862        Name::str("α"),
863        Box::new(type1()),
864        Box::new(arr(
865            Expr::BVar(0),
866            arr(
867                Expr::BVar(1),
868                arr(
869                    hashset_of(Expr::BVar(2)),
870                    app(
871                        app(
872                            cst("Iff"),
873                            app(
874                                app(cst("HashSet.mem"), Expr::BVar(0)),
875                                app(app(cst("HashSet.erase"), Expr::BVar(1)), Expr::BVar(2)),
876                            ),
877                        ),
878                        app(
879                            app(
880                                cst("And"),
881                                arr(
882                                    app(app(cst("Eq"), Expr::BVar(0)), Expr::BVar(1)),
883                                    cst("False"),
884                                ),
885                            ),
886                            app(app(cst("HashSet.mem"), Expr::BVar(0)), Expr::BVar(2)),
887                        ),
888                    ),
889                ),
890            ),
891        )),
892    );
893    add("HashSet.mem_erase", mem_erase_ty)?;
894    let insert_insert_ty = Expr::Pi(
895        Bi::Implicit,
896        Name::str("α"),
897        Box::new(type1()),
898        Box::new(arr(
899            Expr::BVar(0),
900            arr(
901                hashset_of(Expr::BVar(1)),
902                app(
903                    app(
904                        cst("Eq"),
905                        app(
906                            app(cst("HashSet.insert"), Expr::BVar(0)),
907                            app(app(cst("HashSet.insert"), Expr::BVar(0)), Expr::BVar(1)),
908                        ),
909                    ),
910                    app(app(cst("HashSet.insert"), Expr::BVar(0)), Expr::BVar(1)),
911                ),
912            ),
913        )),
914    );
915    add("HashSet.insert_insert_idempotent", insert_insert_ty)?;
916    let erase_empty_ty = Expr::Pi(
917        Bi::Implicit,
918        Name::str("α"),
919        Box::new(type1()),
920        Box::new(arr(
921            Expr::BVar(0),
922            app(
923                app(
924                    cst("Eq"),
925                    app(
926                        app(cst("HashSet.erase"), Expr::BVar(0)),
927                        cst("HashSet.empty"),
928                    ),
929                ),
930                cst("HashSet.empty"),
931            ),
932        )),
933    );
934    add("HashSet.erase_empty", erase_empty_ty)?;
935    let insert_erase_ty = Expr::Pi(
936        Bi::Implicit,
937        Name::str("α"),
938        Box::new(type1()),
939        Box::new(arr(
940            Expr::BVar(0),
941            arr(
942                hashset_of(Expr::BVar(1)),
943                arr(
944                    app(app(cst("HashSet.mem"), Expr::BVar(0)), Expr::BVar(1)),
945                    app(
946                        app(
947                            cst("Eq"),
948                            app(
949                                app(cst("HashSet.insert"), Expr::BVar(0)),
950                                app(app(cst("HashSet.erase"), Expr::BVar(0)), Expr::BVar(1)),
951                            ),
952                        ),
953                        Expr::BVar(1),
954                    ),
955                ),
956            ),
957        )),
958    );
959    add("HashSet.insert_erase_mem", insert_erase_ty)?;
960    let size_insert_ty = Expr::Pi(
961        Bi::Implicit,
962        Name::str("α"),
963        Box::new(type1()),
964        Box::new(arr(
965            Expr::BVar(0),
966            arr(
967                hashset_of(Expr::BVar(1)),
968                arr(
969                    arr(
970                        app(app(cst("HashSet.mem"), Expr::BVar(0)), Expr::BVar(1)),
971                        cst("False"),
972                    ),
973                    app(
974                        app(
975                            cst("Eq"),
976                            app(
977                                cst("HashSet.size"),
978                                app(app(cst("HashSet.insert"), Expr::BVar(0)), Expr::BVar(1)),
979                            ),
980                        ),
981                        app(
982                            app(cst("Nat.succ"), app(cst("HashSet.size"), Expr::BVar(1))),
983                            cst("Nat.zero"),
984                        ),
985                    ),
986                ),
987            ),
988        )),
989    );
990    add("HashSet.size_insert_new", size_insert_ty)?;
991    let size_erase_ty = Expr::Pi(
992        Bi::Implicit,
993        Name::str("α"),
994        Box::new(type1()),
995        Box::new(arr(
996            Expr::BVar(0),
997            arr(
998                hashset_of(Expr::BVar(1)),
999                arr(
1000                    app(app(cst("HashSet.mem"), Expr::BVar(0)), Expr::BVar(1)),
1001                    app(
1002                        app(
1003                            cst("Eq"),
1004                            app(
1005                                app(
1006                                    cst("Nat.add"),
1007                                    app(
1008                                        cst("HashSet.size"),
1009                                        app(
1010                                            app(cst("HashSet.erase"), Expr::BVar(0)),
1011                                            Expr::BVar(1),
1012                                        ),
1013                                    ),
1014                                ),
1015                                cst("1"),
1016                            ),
1017                        ),
1018                        app(cst("HashSet.size"), Expr::BVar(1)),
1019                    ),
1020                ),
1021            ),
1022        )),
1023    );
1024    add("HashSet.size_erase_mem", size_erase_ty)?;
1025    Ok(())
1026}
1027pub fn hs_ext_union_laws(
1028    add: &mut impl FnMut(&str, oxilean_kernel::Expr) -> Result<(), String>,
1029) -> Result<(), String> {
1030    use oxilean_kernel::{BinderInfo as Bi, Expr, Level, Name};
1031    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
1032    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
1033    let arr = |a: Expr, b: Expr| -> Expr {
1034        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
1035    };
1036    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
1037    let hashset_of = |ty: Expr| -> Expr { app(cst("HashSet"), ty) };
1038    let union_comm_ty = Expr::Pi(
1039        Bi::Implicit,
1040        Name::str("α"),
1041        Box::new(type1()),
1042        Box::new(arr(
1043            hashset_of(Expr::BVar(0)),
1044            arr(
1045                hashset_of(Expr::BVar(1)),
1046                app(
1047                    app(
1048                        cst("Eq"),
1049                        app(app(cst("HashSet.union"), Expr::BVar(0)), Expr::BVar(1)),
1050                    ),
1051                    app(app(cst("HashSet.union"), Expr::BVar(1)), Expr::BVar(0)),
1052                ),
1053            ),
1054        )),
1055    );
1056    add("HashSet.union_comm", union_comm_ty)?;
1057    let union_assoc_ty = Expr::Pi(
1058        Bi::Implicit,
1059        Name::str("α"),
1060        Box::new(type1()),
1061        Box::new(arr(
1062            hashset_of(Expr::BVar(0)),
1063            arr(
1064                hashset_of(Expr::BVar(1)),
1065                arr(
1066                    hashset_of(Expr::BVar(2)),
1067                    app(
1068                        app(
1069                            cst("Eq"),
1070                            app(
1071                                app(
1072                                    cst("HashSet.union"),
1073                                    app(app(cst("HashSet.union"), Expr::BVar(0)), Expr::BVar(1)),
1074                                ),
1075                                Expr::BVar(2),
1076                            ),
1077                        ),
1078                        app(
1079                            app(cst("HashSet.union"), Expr::BVar(0)),
1080                            app(app(cst("HashSet.union"), Expr::BVar(1)), Expr::BVar(2)),
1081                        ),
1082                    ),
1083                ),
1084            ),
1085        )),
1086    );
1087    add("HashSet.union_assoc", union_assoc_ty)?;
1088    let union_empty_ty = Expr::Pi(
1089        Bi::Implicit,
1090        Name::str("α"),
1091        Box::new(type1()),
1092        Box::new(arr(
1093            hashset_of(Expr::BVar(0)),
1094            app(
1095                app(
1096                    cst("Eq"),
1097                    app(
1098                        app(cst("HashSet.union"), Expr::BVar(0)),
1099                        cst("HashSet.empty"),
1100                    ),
1101                ),
1102                Expr::BVar(0),
1103            ),
1104        )),
1105    );
1106    add("HashSet.union_empty", union_empty_ty)?;
1107    let empty_union_ty = Expr::Pi(
1108        Bi::Implicit,
1109        Name::str("α"),
1110        Box::new(type1()),
1111        Box::new(arr(
1112            hashset_of(Expr::BVar(0)),
1113            app(
1114                app(
1115                    cst("Eq"),
1116                    app(
1117                        app(cst("HashSet.union"), cst("HashSet.empty")),
1118                        Expr::BVar(0),
1119                    ),
1120                ),
1121                Expr::BVar(0),
1122            ),
1123        )),
1124    );
1125    add("HashSet.empty_union", empty_union_ty)?;
1126    let union_self_ty = Expr::Pi(
1127        Bi::Implicit,
1128        Name::str("α"),
1129        Box::new(type1()),
1130        Box::new(arr(
1131            hashset_of(Expr::BVar(0)),
1132            app(
1133                app(
1134                    cst("Eq"),
1135                    app(app(cst("HashSet.union"), Expr::BVar(0)), Expr::BVar(0)),
1136                ),
1137                Expr::BVar(0),
1138            ),
1139        )),
1140    );
1141    add("HashSet.union_self", union_self_ty)?;
1142    let mem_union_ty = Expr::Pi(
1143        Bi::Implicit,
1144        Name::str("α"),
1145        Box::new(type1()),
1146        Box::new(arr(
1147            Expr::BVar(0),
1148            arr(
1149                hashset_of(Expr::BVar(1)),
1150                arr(
1151                    hashset_of(Expr::BVar(2)),
1152                    app(
1153                        app(
1154                            cst("Iff"),
1155                            app(
1156                                app(cst("HashSet.mem"), Expr::BVar(0)),
1157                                app(app(cst("HashSet.union"), Expr::BVar(1)), Expr::BVar(2)),
1158                            ),
1159                        ),
1160                        app(
1161                            app(
1162                                cst("Or"),
1163                                app(app(cst("HashSet.mem"), Expr::BVar(0)), Expr::BVar(1)),
1164                            ),
1165                            app(app(cst("HashSet.mem"), Expr::BVar(0)), Expr::BVar(2)),
1166                        ),
1167                    ),
1168                ),
1169            ),
1170        )),
1171    );
1172    add("HashSet.mem_union", mem_union_ty)?;
1173    Ok(())
1174}
1175pub fn hs_ext_intersection_laws(
1176    add: &mut impl FnMut(&str, oxilean_kernel::Expr) -> Result<(), String>,
1177) -> Result<(), String> {
1178    use oxilean_kernel::{BinderInfo as Bi, Expr, Level, Name};
1179    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
1180    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
1181    let arr = |a: Expr, b: Expr| -> Expr {
1182        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
1183    };
1184    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
1185    let hashset_of = |ty: Expr| -> Expr { app(cst("HashSet"), ty) };
1186    let inter_comm_ty = Expr::Pi(
1187        Bi::Implicit,
1188        Name::str("α"),
1189        Box::new(type1()),
1190        Box::new(arr(
1191            hashset_of(Expr::BVar(0)),
1192            arr(
1193                hashset_of(Expr::BVar(1)),
1194                app(
1195                    app(
1196                        cst("Eq"),
1197                        app(app(cst("HashSet.inter"), Expr::BVar(0)), Expr::BVar(1)),
1198                    ),
1199                    app(app(cst("HashSet.inter"), Expr::BVar(1)), Expr::BVar(0)),
1200                ),
1201            ),
1202        )),
1203    );
1204    add("HashSet.inter_comm", inter_comm_ty)?;
1205    let inter_assoc_ty = Expr::Pi(
1206        Bi::Implicit,
1207        Name::str("α"),
1208        Box::new(type1()),
1209        Box::new(arr(
1210            hashset_of(Expr::BVar(0)),
1211            arr(
1212                hashset_of(Expr::BVar(1)),
1213                arr(
1214                    hashset_of(Expr::BVar(2)),
1215                    app(
1216                        app(
1217                            cst("Eq"),
1218                            app(
1219                                app(
1220                                    cst("HashSet.inter"),
1221                                    app(app(cst("HashSet.inter"), Expr::BVar(0)), Expr::BVar(1)),
1222                                ),
1223                                Expr::BVar(2),
1224                            ),
1225                        ),
1226                        app(
1227                            app(cst("HashSet.inter"), Expr::BVar(0)),
1228                            app(app(cst("HashSet.inter"), Expr::BVar(1)), Expr::BVar(2)),
1229                        ),
1230                    ),
1231                ),
1232            ),
1233        )),
1234    );
1235    add("HashSet.inter_assoc", inter_assoc_ty)?;
1236    let inter_self_ty = Expr::Pi(
1237        Bi::Implicit,
1238        Name::str("α"),
1239        Box::new(type1()),
1240        Box::new(arr(
1241            hashset_of(Expr::BVar(0)),
1242            app(
1243                app(
1244                    cst("Eq"),
1245                    app(app(cst("HashSet.inter"), Expr::BVar(0)), Expr::BVar(0)),
1246                ),
1247                Expr::BVar(0),
1248            ),
1249        )),
1250    );
1251    add("HashSet.inter_self", inter_self_ty)?;
1252    let inter_empty_ty = Expr::Pi(
1253        Bi::Implicit,
1254        Name::str("α"),
1255        Box::new(type1()),
1256        Box::new(arr(
1257            hashset_of(Expr::BVar(0)),
1258            app(
1259                app(
1260                    cst("Eq"),
1261                    app(
1262                        app(cst("HashSet.inter"), Expr::BVar(0)),
1263                        cst("HashSet.empty"),
1264                    ),
1265                ),
1266                cst("HashSet.empty"),
1267            ),
1268        )),
1269    );
1270    add("HashSet.inter_empty", inter_empty_ty)?;
1271    let mem_inter_ty = Expr::Pi(
1272        Bi::Implicit,
1273        Name::str("α"),
1274        Box::new(type1()),
1275        Box::new(arr(
1276            Expr::BVar(0),
1277            arr(
1278                hashset_of(Expr::BVar(1)),
1279                arr(
1280                    hashset_of(Expr::BVar(2)),
1281                    app(
1282                        app(
1283                            cst("Iff"),
1284                            app(
1285                                app(cst("HashSet.mem"), Expr::BVar(0)),
1286                                app(app(cst("HashSet.inter"), Expr::BVar(1)), Expr::BVar(2)),
1287                            ),
1288                        ),
1289                        app(
1290                            app(
1291                                cst("And"),
1292                                app(app(cst("HashSet.mem"), Expr::BVar(0)), Expr::BVar(1)),
1293                            ),
1294                            app(app(cst("HashSet.mem"), Expr::BVar(0)), Expr::BVar(2)),
1295                        ),
1296                    ),
1297                ),
1298            ),
1299        )),
1300    );
1301    add("HashSet.mem_inter", mem_inter_ty)?;
1302    let union_distrib_ty = Expr::Pi(
1303        Bi::Implicit,
1304        Name::str("α"),
1305        Box::new(type1()),
1306        Box::new(arr(
1307            hashset_of(Expr::BVar(0)),
1308            arr(
1309                hashset_of(Expr::BVar(1)),
1310                arr(
1311                    hashset_of(Expr::BVar(2)),
1312                    app(
1313                        app(
1314                            cst("Eq"),
1315                            app(
1316                                app(cst("HashSet.union"), Expr::BVar(0)),
1317                                app(app(cst("HashSet.inter"), Expr::BVar(1)), Expr::BVar(2)),
1318                            ),
1319                        ),
1320                        app(
1321                            app(
1322                                cst("HashSet.inter"),
1323                                app(app(cst("HashSet.union"), Expr::BVar(0)), Expr::BVar(1)),
1324                            ),
1325                            app(app(cst("HashSet.union"), Expr::BVar(0)), Expr::BVar(2)),
1326                        ),
1327                    ),
1328                ),
1329            ),
1330        )),
1331    );
1332    add("HashSet.union_distrib_inter", union_distrib_ty)?;
1333    Ok(())
1334}
1335pub fn hs_ext_difference_laws(
1336    add: &mut impl FnMut(&str, oxilean_kernel::Expr) -> Result<(), String>,
1337) -> Result<(), String> {
1338    use oxilean_kernel::{BinderInfo as Bi, Expr, Level, Name};
1339    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
1340    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
1341    let arr = |a: Expr, b: Expr| -> Expr {
1342        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
1343    };
1344    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
1345    let prop = || -> Expr { Expr::Sort(Level::zero()) };
1346    let hashset_of = |ty: Expr| -> Expr { app(cst("HashSet"), ty) };
1347    let mem_sdiff_ty = Expr::Pi(
1348        Bi::Implicit,
1349        Name::str("α"),
1350        Box::new(type1()),
1351        Box::new(arr(
1352            Expr::BVar(0),
1353            arr(
1354                hashset_of(Expr::BVar(1)),
1355                arr(
1356                    hashset_of(Expr::BVar(2)),
1357                    app(
1358                        app(
1359                            cst("Iff"),
1360                            app(
1361                                app(cst("HashSet.mem"), Expr::BVar(0)),
1362                                app(app(cst("HashSet.sdiff"), Expr::BVar(1)), Expr::BVar(2)),
1363                            ),
1364                        ),
1365                        app(
1366                            app(
1367                                cst("And"),
1368                                app(app(cst("HashSet.mem"), Expr::BVar(0)), Expr::BVar(1)),
1369                            ),
1370                            arr(
1371                                app(app(cst("HashSet.mem"), Expr::BVar(0)), Expr::BVar(2)),
1372                                cst("False"),
1373                            ),
1374                        ),
1375                    ),
1376                ),
1377            ),
1378        )),
1379    );
1380    add("HashSet.mem_sdiff", mem_sdiff_ty)?;
1381    let sdiff_empty_ty = Expr::Pi(
1382        Bi::Implicit,
1383        Name::str("α"),
1384        Box::new(type1()),
1385        Box::new(arr(
1386            hashset_of(Expr::BVar(0)),
1387            app(
1388                app(
1389                    cst("Eq"),
1390                    app(
1391                        app(cst("HashSet.sdiff"), Expr::BVar(0)),
1392                        cst("HashSet.empty"),
1393                    ),
1394                ),
1395                Expr::BVar(0),
1396            ),
1397        )),
1398    );
1399    add("HashSet.sdiff_empty", sdiff_empty_ty)?;
1400    let empty_sdiff_ty = Expr::Pi(
1401        Bi::Implicit,
1402        Name::str("α"),
1403        Box::new(type1()),
1404        Box::new(arr(
1405            hashset_of(Expr::BVar(0)),
1406            app(
1407                app(
1408                    cst("Eq"),
1409                    app(
1410                        app(cst("HashSet.sdiff"), cst("HashSet.empty")),
1411                        Expr::BVar(0),
1412                    ),
1413                ),
1414                cst("HashSet.empty"),
1415            ),
1416        )),
1417    );
1418    add("HashSet.empty_sdiff", empty_sdiff_ty)?;
1419    let sdiff_self_ty = Expr::Pi(
1420        Bi::Implicit,
1421        Name::str("α"),
1422        Box::new(type1()),
1423        Box::new(arr(
1424            hashset_of(Expr::BVar(0)),
1425            app(
1426                app(
1427                    cst("Eq"),
1428                    app(app(cst("HashSet.sdiff"), Expr::BVar(0)), Expr::BVar(0)),
1429                ),
1430                cst("HashSet.empty"),
1431            ),
1432        )),
1433    );
1434    add("HashSet.sdiff_self", sdiff_self_ty)?;
1435    let _ = prop();
1436    let sdiff_union_ty = Expr::Pi(
1437        Bi::Implicit,
1438        Name::str("α"),
1439        Box::new(type1()),
1440        Box::new(arr(
1441            hashset_of(Expr::BVar(0)),
1442            arr(
1443                hashset_of(Expr::BVar(1)),
1444                arr(
1445                    app(app(cst("HashSet.subset"), Expr::BVar(0)), Expr::BVar(1)),
1446                    app(
1447                        app(
1448                            cst("Eq"),
1449                            app(
1450                                app(
1451                                    cst("HashSet.union"),
1452                                    app(app(cst("HashSet.sdiff"), Expr::BVar(1)), Expr::BVar(0)),
1453                                ),
1454                                Expr::BVar(0),
1455                            ),
1456                        ),
1457                        Expr::BVar(1),
1458                    ),
1459                ),
1460            ),
1461        )),
1462    );
1463    add("HashSet.sdiff_union_of_subset", sdiff_union_ty)?;
1464    Ok(())
1465}
1466pub fn hs_ext_subset_partial_order(
1467    add: &mut impl FnMut(&str, oxilean_kernel::Expr) -> Result<(), String>,
1468) -> Result<(), String> {
1469    use oxilean_kernel::{BinderInfo as Bi, Expr, Level, Name};
1470    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
1471    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
1472    let arr = |a: Expr, b: Expr| -> Expr {
1473        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
1474    };
1475    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
1476    let hashset_of = |ty: Expr| -> Expr { app(cst("HashSet"), ty) };
1477    let subset_refl_ty = Expr::Pi(
1478        Bi::Implicit,
1479        Name::str("α"),
1480        Box::new(type1()),
1481        Box::new(arr(
1482            hashset_of(Expr::BVar(0)),
1483            app(app(cst("HashSet.subset"), Expr::BVar(0)), Expr::BVar(0)),
1484        )),
1485    );
1486    add("HashSet.subset_refl", subset_refl_ty)?;
1487    let subset_trans_ty = Expr::Pi(
1488        Bi::Implicit,
1489        Name::str("α"),
1490        Box::new(type1()),
1491        Box::new(arr(
1492            hashset_of(Expr::BVar(0)),
1493            arr(
1494                hashset_of(Expr::BVar(1)),
1495                arr(
1496                    hashset_of(Expr::BVar(2)),
1497                    arr(
1498                        app(app(cst("HashSet.subset"), Expr::BVar(0)), Expr::BVar(1)),
1499                        arr(
1500                            app(app(cst("HashSet.subset"), Expr::BVar(1)), Expr::BVar(2)),
1501                            app(app(cst("HashSet.subset"), Expr::BVar(0)), Expr::BVar(2)),
1502                        ),
1503                    ),
1504                ),
1505            ),
1506        )),
1507    );
1508    add("HashSet.subset_trans", subset_trans_ty)?;
1509    let subset_antisymm_ty = Expr::Pi(
1510        Bi::Implicit,
1511        Name::str("α"),
1512        Box::new(type1()),
1513        Box::new(arr(
1514            hashset_of(Expr::BVar(0)),
1515            arr(
1516                hashset_of(Expr::BVar(1)),
1517                arr(
1518                    app(app(cst("HashSet.subset"), Expr::BVar(0)), Expr::BVar(1)),
1519                    arr(
1520                        app(app(cst("HashSet.subset"), Expr::BVar(1)), Expr::BVar(0)),
1521                        app(app(cst("Eq"), Expr::BVar(0)), Expr::BVar(1)),
1522                    ),
1523                ),
1524            ),
1525        )),
1526    );
1527    add("HashSet.subset_antisymm", subset_antisymm_ty)?;
1528    let empty_subset_ty = Expr::Pi(
1529        Bi::Implicit,
1530        Name::str("α"),
1531        Box::new(type1()),
1532        Box::new(arr(
1533            hashset_of(Expr::BVar(0)),
1534            app(
1535                app(cst("HashSet.subset"), cst("HashSet.empty")),
1536                Expr::BVar(0),
1537            ),
1538        )),
1539    );
1540    add("HashSet.empty_subset", empty_subset_ty)?;
1541    let subset_union_ty = Expr::Pi(
1542        Bi::Implicit,
1543        Name::str("α"),
1544        Box::new(type1()),
1545        Box::new(arr(
1546            hashset_of(Expr::BVar(0)),
1547            arr(
1548                hashset_of(Expr::BVar(1)),
1549                app(
1550                    app(cst("HashSet.subset"), Expr::BVar(0)),
1551                    app(app(cst("HashSet.union"), Expr::BVar(0)), Expr::BVar(1)),
1552                ),
1553            ),
1554        )),
1555    );
1556    add("HashSet.subset_self_union_left", subset_union_ty)?;
1557    let inter_subset_ty = Expr::Pi(
1558        Bi::Implicit,
1559        Name::str("α"),
1560        Box::new(type1()),
1561        Box::new(arr(
1562            hashset_of(Expr::BVar(0)),
1563            arr(
1564                hashset_of(Expr::BVar(1)),
1565                app(
1566                    app(
1567                        cst("HashSet.subset"),
1568                        app(app(cst("HashSet.inter"), Expr::BVar(0)), Expr::BVar(1)),
1569                    ),
1570                    Expr::BVar(0),
1571                ),
1572            ),
1573        )),
1574    );
1575    add("HashSet.inter_subset_left", inter_subset_ty)?;
1576    Ok(())
1577}
1578pub fn hs_ext_power_set_axioms(
1579    add: &mut impl FnMut(&str, oxilean_kernel::Expr) -> Result<(), String>,
1580) -> Result<(), String> {
1581    use super::functions::*;
1582    use oxilean_kernel::{BinderInfo as Bi, Expr, Level, Name};
1583    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
1584    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
1585    let arr = |a: Expr, b: Expr| -> Expr {
1586        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
1587    };
1588    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
1589    let nat_ty = || -> Expr { cst("Nat") };
1590    let hashset_of = |ty: Expr| -> Expr { app(cst("HashSet"), ty) };
1591    let powerset_ty = Expr::Pi(
1592        Bi::Implicit,
1593        Name::str("α"),
1594        Box::new(type1()),
1595        Box::new(arr(
1596            hashset_of(Expr::BVar(0)),
1597            hashset_of(hashset_of(Expr::BVar(1))),
1598        )),
1599    );
1600    add("HashSet.powerset", powerset_ty)?;
1601    let mem_powerset_ty = Expr::Pi(
1602        Bi::Implicit,
1603        Name::str("α"),
1604        Box::new(type1()),
1605        Box::new(arr(
1606            hashset_of(Expr::BVar(0)),
1607            arr(
1608                hashset_of(Expr::BVar(1)),
1609                app(
1610                    app(
1611                        cst("Iff"),
1612                        app(
1613                            app(cst("HashSet.mem"), Expr::BVar(0)),
1614                            app(cst("HashSet.powerset"), Expr::BVar(1)),
1615                        ),
1616                    ),
1617                    app(app(cst("HashSet.subset"), Expr::BVar(0)), Expr::BVar(1)),
1618                ),
1619            ),
1620        )),
1621    );
1622    add("HashSet.mem_powerset", mem_powerset_ty)?;
1623    let card_powerset_ty = Expr::Pi(
1624        Bi::Implicit,
1625        Name::str("α"),
1626        Box::new(type1()),
1627        Box::new(arr(
1628            hashset_of(Expr::BVar(0)),
1629            app(
1630                app(
1631                    cst("Eq"),
1632                    app(
1633                        cst("HashSet.size"),
1634                        app(cst("HashSet.powerset"), Expr::BVar(0)),
1635                    ),
1636                ),
1637                app(
1638                    app(cst("Nat.pow"), nat_ty()),
1639                    app(cst("HashSet.size"), Expr::BVar(0)),
1640                ),
1641            ),
1642        )),
1643    );
1644    add("HashSet.card_powerset", card_powerset_ty)?;
1645    let cantor_ty = Expr::Pi(
1646        Bi::Implicit,
1647        Name::str("α"),
1648        Box::new(type1()),
1649        Box::new(arr(
1650            hashset_of(Expr::BVar(0)),
1651            app(
1652                app(cst("Nat.lt"), app(cst("HashSet.size"), Expr::BVar(0))),
1653                app(
1654                    cst("HashSet.size"),
1655                    app(cst("HashSet.powerset"), Expr::BVar(0)),
1656                ),
1657            ),
1658        )),
1659    );
1660    add("HashSet.cantor_strict_lt", cantor_ty)?;
1661    Ok(())
1662}