vstd/
set_lib.rs

1#[allow(unused_imports)]
2use super::multiset::Multiset;
3#[allow(unused_imports)]
4use super::pervasive::*;
5use super::prelude::Seq;
6#[allow(unused_imports)]
7use super::prelude::*;
8#[allow(unused_imports)]
9use super::relations::*;
10#[allow(unused_imports)]
11use super::set::*;
12
13verus! {
14
15broadcast use super::set::group_set_axioms;
16
17impl<A> Set<A> {
18    /// Is `true` if called by a "full" set, i.e., a set containing every element of type `A`.
19    pub open spec fn is_full(self) -> bool {
20        self == Set::<A>::full()
21    }
22
23    /// Is `true` if called by an "empty" set, i.e., a set containing no elements and has length 0
24    pub open spec fn is_empty(self) -> (b: bool) {
25        self =~= Set::<A>::empty()
26    }
27
28    /// Returns the set contains an element `f(x)` for every element `x` in `self`.
29    pub open spec fn map<B>(self, f: spec_fn(A) -> B) -> Set<B> {
30        Set::new(|a: B| exists|x: A| self.contains(x) && a == f(x))
31    }
32
33    /// `Set::map_by` is like `Set::map`, but `map` only takes a forward function `fwd: spec_fn(A) -> B`,
34    /// while `map_by` also takes a reverse function `rev: spec_fn(B) -> A`
35    /// such that `rev(fwd(a)) == a`.
36    /// When `fwd` has such a reverse function, `Set::map_by` can make proofs easier
37    /// by avoiding the "exists" that appears in lemmas about `Set::map`.
38    /// Example: for a set `s: Set<int>`, to map each `i` in `s` to `(i, 10 * i)`,
39    /// we can write either `s.map(|i: int| (i, 10 * i))`
40    /// or `s.map_by(|i: int| (i, 10 * i), |p: (int, int)| p.0)`;
41    /// the version with `map_by` is usually easier to use in proofs.
42    /// If the recommendation `forall|a: A| self.contains(a) ==> rev(fwd(a)) == a` is satisfied,
43    /// it is trivially guaranteed that `self.map_by(fwd, rev) == self.map(fwd)`.
44    /// Also see the `set_build!` macro for a convenient interface to `map_by`.
45    pub open spec fn map_by<B>(self, fwd: spec_fn(A) -> B, rev: spec_fn(B) -> A) -> Set<B>
46        recommends
47            forall|a: A| self.contains(a) ==> rev(fwd(a)) == a,
48    {
49        Set::new(|b: B| self.contains(rev(b)) && b == fwd(rev(b)))
50    }
51
52    /// Similar to `Set::map_by`, but the forward function returns `Set<B>` rather than `B`,
53    /// and `map_flatten_by` flattens the final result from `Set<Set<B>>` to just `Set<B>`.
54    /// This can be easier to work with in proofs than calling `map` and `flatten` separately,
55    /// since `map` and `flatten` introduce "exists", while `map_flatten_by` does not.
56    /// Also see the `set_build!` macro for a convenient interface to `map_flatten_by`.
57    pub open spec fn map_flatten_by<B>(
58        self,
59        fwd: spec_fn(A) -> Set<B>,
60        rev: spec_fn(B) -> A,
61    ) -> Set<B>
62        recommends
63            forall|a: A, b: B| #[trigger]
64                self.contains(a) && fwd(a).contains(b) ==> #[trigger] rev(b) == a,
65    {
66        Set::new(|b: B| self.contains(rev(b)) && fwd(rev(b)).contains(b))
67    }
68
69    pub proof fn map_flatten_by_is_map_flatten<B>(
70        self,
71        fwd: spec_fn(A) -> Set<B>,
72        rev: spec_fn(B) -> A,
73    )
74        requires
75            forall|a: A, b: B| #[trigger]
76                self.contains(a) && fwd(a).contains(b) ==> #[trigger] rev(b) == a,
77        ensures
78            self.map_flatten_by(fwd, rev) == self.map(fwd).flatten(),
79    {
80        assert forall|b: B| self.map_flatten_by(fwd, rev).contains(b) implies #[trigger] self.map(
81            fwd,
82        ).flatten().contains(b) by {
83            let bs = choose|bs: Set<B>|
84                (exists|a: A| self.contains(a) && bs == fwd(a)) && bs.contains(b);
85            assert(self.map(fwd).contains(bs) <==> (exists|a: A| self.contains(a) && bs == fwd(a)));
86        }
87    }
88
89    /// Converts a set into a sequence with an arbitrary ordering.
90    pub open spec fn to_seq(self) -> Seq<A>
91        recommends
92            self.finite(),
93        decreases self.len(),
94        when self.finite()
95    {
96        if self.len() == 0 {
97            Seq::<A>::empty()
98        } else {
99            let x = self.choose();
100            Seq::<A>::empty().push(x) + self.remove(x).to_seq()
101        }
102    }
103
104    /// Converts a set into a sequence sorted by the given ordering function `leq`
105    pub open spec fn to_sorted_seq(self, leq: spec_fn(A, A) -> bool) -> Seq<A> {
106        self.to_seq().sort_by(leq)
107    }
108
109    /// A singleton set has at least one element and any two elements are equal.
110    pub open spec fn is_singleton(self) -> bool {
111        &&& self.len() > 0
112        &&& (forall|x: A, y: A| self.contains(x) && self.contains(y) ==> x == y)
113    }
114
115    /// Any totally-ordered set contains a unique minimal (equivalently, least) element.
116    /// Returns an arbitrary value if r is not a total ordering
117    pub closed spec fn find_unique_minimal(self, r: spec_fn(A, A) -> bool) -> A
118        recommends
119            total_ordering(r),
120            self.len() > 0,
121            self.finite(),
122        decreases self.len(),
123        when self.finite()
124    {
125        proof {
126            broadcast use group_set_properties;
127
128        }
129        if self.len() <= 1 {
130            self.choose()
131        } else {
132            let x = choose|x: A| self.contains(x);
133            let min = self.remove(x).find_unique_minimal(r);
134            if r(min, x) {
135                min
136            } else {
137                x
138            }
139        }
140    }
141
142    /// Proof of correctness and expected behavior for `Set::find_unique_minimal`.
143    pub proof fn find_unique_minimal_ensures(self, r: spec_fn(A, A) -> bool)
144        requires
145            self.finite(),
146            self.len() > 0,
147            total_ordering(r),
148        ensures
149            is_minimal(r, self.find_unique_minimal(r), self) && (forall|min: A|
150                is_minimal(r, min, self) ==> self.find_unique_minimal(r) == min),
151        decreases self.len(),
152    {
153        broadcast use group_set_properties;
154
155        if self.len() == 1 {
156            let x = choose|x: A| self.contains(x);
157            assert(self.remove(x).insert(x) =~= self);
158            assert(is_minimal(r, self.find_unique_minimal(r), self));
159        } else {
160            let x = choose|x: A| self.contains(x);
161            self.remove(x).find_unique_minimal_ensures(r);
162            assert(is_minimal(r, self.remove(x).find_unique_minimal(r), self.remove(x)));
163            let y = self.remove(x).find_unique_minimal(r);
164            let min_updated = self.find_unique_minimal(r);
165            assert(!r(y, x) ==> min_updated == x);
166            assert(forall|elt: A|
167                self.remove(x).contains(elt) && #[trigger] r(elt, y) ==> #[trigger] r(y, elt));
168            assert forall|elt: A|
169                self.contains(elt) && #[trigger] r(elt, min_updated) implies #[trigger] r(
170                min_updated,
171                elt,
172            ) by {
173                assert(r(min_updated, x) || r(min_updated, y));
174                if min_updated == y {  // Case where the new min is the old min
175                    assert(is_minimal(r, self.find_unique_minimal(r), self));
176                } else {  //Case where the new min is the newest element
177                    assert(self.remove(x).contains(elt) || elt == x);
178                    assert(min_updated == x);
179                    assert(r(x, y) || r(y, x));
180                    assert(!r(x, y) || !r(y, x));
181                    assert(!(min_updated == y) ==> !r(y, x));
182                    assert(r(x, y));
183                    if (self.remove(x).contains(elt)) {
184                        assert(r(elt, y) && r(y, elt) ==> elt == y);
185                    } else {
186                    }
187                }
188            }
189            assert forall|min_poss: A|
190                is_minimal(r, min_poss, self) implies self.find_unique_minimal(r) == min_poss by {
191                assert(is_minimal(r, min_poss, self.remove(x)) || x == min_poss);
192                assert(r(min_poss, self.find_unique_minimal(r)));
193            }
194        }
195    }
196
197    /// Any totally-ordered set contains a unique maximal (equivalently, greatest) element.
198    /// Returns an arbitrary value if r is not a total ordering
199    pub closed spec fn find_unique_maximal(self, r: spec_fn(A, A) -> bool) -> A
200        recommends
201            total_ordering(r),
202            self.len() > 0,
203        decreases self.len(),
204        when self.finite()
205    {
206        proof {
207            broadcast use group_set_properties;
208
209        }
210        if self.len() <= 1 {
211            self.choose()
212        } else {
213            let x = choose|x: A| self.contains(x);
214            let max = self.remove(x).find_unique_maximal(r);
215            if r(x, max) {
216                max
217            } else {
218                x
219            }
220        }
221    }
222
223    /// Proof of correctness and expected behavior for `Set::find_unique_maximal`.
224    pub proof fn find_unique_maximal_ensures(self, r: spec_fn(A, A) -> bool)
225        requires
226            self.finite(),
227            self.len() > 0,
228            total_ordering(r),
229        ensures
230            is_maximal(r, self.find_unique_maximal(r), self) && (forall|max: A|
231                is_maximal(r, max, self) ==> self.find_unique_maximal(r) == max),
232        decreases self.len(),
233    {
234        broadcast use group_set_properties;
235
236        if self.len() == 1 {
237            let x = choose|x: A| self.contains(x);
238            assert(self.remove(x) =~= Set::<A>::empty());
239            assert(self.contains(self.find_unique_maximal(r)));
240        } else {
241            let x = choose|x: A| self.contains(x);
242            self.remove(x).find_unique_maximal_ensures(r);
243            assert(is_maximal(r, self.remove(x).find_unique_maximal(r), self.remove(x)));
244            assert(self.remove(x).insert(x) =~= self);
245            let y = self.remove(x).find_unique_maximal(r);
246            let max_updated = self.find_unique_maximal(r);
247            assert(max_updated == x || max_updated == y);
248            assert(!r(x, y) ==> max_updated == x);
249            assert forall|elt: A|
250                self.contains(elt) && #[trigger] r(max_updated, elt) implies #[trigger] r(
251                elt,
252                max_updated,
253            ) by {
254                assert(r(x, max_updated) || r(y, max_updated));
255                if max_updated == y {  // Case where the new max is the old max
256                    assert(r(elt, max_updated));
257                    assert(r(x, max_updated));
258                    assert(is_maximal(r, self.find_unique_maximal(r), self));
259                } else {  //Case where the new max is the newest element
260                    assert(self.remove(x).contains(elt) || elt == x);
261                    assert(max_updated == x);
262                    assert(r(x, y) || r(y, x));
263                    assert(!r(x, y) || !r(y, x));
264                    assert(!(max_updated == y) ==> !r(x, y));
265                    assert(r(y, x));
266                    if (self.remove(x).contains(elt)) {
267                        assert(r(y, elt) ==> r(elt, y));
268                        assert(r(y, elt) && r(elt, y) ==> elt == y);
269                        assert(r(elt, x));
270                        assert(r(elt, max_updated))
271                    } else {
272                    }
273                }
274            }
275            assert forall|max_poss: A|
276                is_maximal(r, max_poss, self) implies self.find_unique_maximal(r) == max_poss by {
277                assert(is_maximal(r, max_poss, self.remove(x)) || x == max_poss);
278                assert(r(max_poss, self.find_unique_maximal(r)));
279                assert(r(self.find_unique_maximal(r), max_poss));
280            }
281        }
282    }
283
284    /// Converts a set into a multiset where each element from the set has
285    /// multiplicity 1 and any other element has multiplicity 0.
286    pub open spec fn to_multiset(self) -> Multiset<A>
287        decreases self.len(),
288        when self.finite()
289    {
290        if self.len() == 0 {
291            Multiset::<A>::empty()
292        } else {
293            Multiset::<A>::empty().insert(self.choose()).add(
294                self.remove(self.choose()).to_multiset(),
295            )
296        }
297    }
298
299    /// A finite set with length 0 is equivalent to the empty set.
300    pub proof fn lemma_len0_is_empty(self)
301        requires
302            self.finite(),
303            self.len() == 0,
304        ensures
305            self == Set::<A>::empty(),
306    {
307        if exists|a: A| self.contains(a) {
308            // derive contradiction:
309            assert(self.remove(self.choose()).len() + 1 == 0);
310        }
311        assert(self =~= Set::empty());
312    }
313
314    /// A singleton set has length 1.
315    pub proof fn lemma_singleton_size(self)
316        requires
317            self.is_singleton(),
318        ensures
319            self.len() == 1,
320    {
321        broadcast use group_set_properties;
322
323        assert(self.remove(self.choose()) =~= Set::empty());
324    }
325
326    /// A set has exactly one element, if and only if, it has at least one element and any two elements are equal.
327    pub proof fn lemma_is_singleton(s: Set<A>)
328        requires
329            s.finite(),
330        ensures
331            s.is_singleton() == (s.len() == 1),
332    {
333        if s.is_singleton() {
334            s.lemma_singleton_size();
335        }
336        if s.len() == 1 {
337            assert forall|x: A, y: A| s.contains(x) && s.contains(y) implies x == y by {
338                let x = choose|x: A| s.contains(x);
339                broadcast use group_set_properties;
340
341                assert(s.remove(x).len() == 0);
342                assert(s.insert(x) =~= s);
343            }
344        }
345    }
346
347    /// The result of filtering a finite set is finite and has size less than or equal to the original set.
348    pub proof fn lemma_len_filter(self, f: spec_fn(A) -> bool)
349        requires
350            self.finite(),
351        ensures
352            self.filter(f).finite(),
353            self.filter(f).len() <= self.len(),
354        decreases self.len(),
355    {
356        lemma_len_intersect::<A>(self, Set::new(f));
357    }
358
359    /// In a pre-ordered set, a greatest element is necessarily maximal.
360    pub proof fn lemma_greatest_implies_maximal(self, r: spec_fn(A, A) -> bool, max: A)
361        requires
362            pre_ordering(r),
363        ensures
364            is_greatest(r, max, self) ==> is_maximal(r, max, self),
365    {
366    }
367
368    /// In a pre-ordered set, a least element is necessarily minimal.
369    pub proof fn lemma_least_implies_minimal(self, r: spec_fn(A, A) -> bool, min: A)
370        requires
371            pre_ordering(r),
372        ensures
373            is_least(r, min, self) ==> is_minimal(r, min, self),
374    {
375    }
376
377    /// In a totally-ordered set, an element is maximal if and only if it is a greatest element.
378    pub proof fn lemma_maximal_equivalent_greatest(self, r: spec_fn(A, A) -> bool, max: A)
379        requires
380            total_ordering(r),
381        ensures
382            is_greatest(r, max, self) <==> is_maximal(r, max, self),
383    {
384        assert(is_maximal(r, max, self) ==> forall|x: A|
385            !self.contains(x) || !r(max, x) || r(x, max));
386    }
387
388    /// In a totally-ordered set, an element is maximal if and only if it is a greatest element.
389    pub proof fn lemma_minimal_equivalent_least(self, r: spec_fn(A, A) -> bool, min: A)
390        requires
391            total_ordering(r),
392        ensures
393            is_least(r, min, self) <==> is_minimal(r, min, self),
394    {
395        assert(is_minimal(r, min, self) ==> forall|x: A|
396            !self.contains(x) || !r(x, min) || r(min, x));
397    }
398
399    /// In a partially-ordered set, there exists at most one least element.
400    pub proof fn lemma_least_is_unique(self, r: spec_fn(A, A) -> bool)
401        requires
402            partial_ordering(r),
403        ensures
404            forall|min: A, min_prime: A|
405                is_least(r, min, self) && is_least(r, min_prime, self) ==> min == min_prime,
406    {
407        assert forall|min: A, min_prime: A|
408            is_least(r, min, self) && is_least(r, min_prime, self) implies min == min_prime by {
409            assert(r(min, min_prime));
410            assert(r(min_prime, min));
411        }
412    }
413
414    /// In a partially-ordered set, there exists at most one greatest element.
415    pub proof fn lemma_greatest_is_unique(self, r: spec_fn(A, A) -> bool)
416        requires
417            partial_ordering(r),
418        ensures
419            forall|max: A, max_prime: A|
420                is_greatest(r, max, self) && is_greatest(r, max_prime, self) ==> max == max_prime,
421    {
422        assert forall|max: A, max_prime: A|
423            is_greatest(r, max, self) && is_greatest(r, max_prime, self) implies max
424            == max_prime by {
425            assert(r(max_prime, max));
426            assert(r(max, max_prime));
427        }
428    }
429
430    /// In a totally-ordered set, there exists at most one minimal element.
431    pub proof fn lemma_minimal_is_unique(self, r: spec_fn(A, A) -> bool)
432        requires
433            total_ordering(r),
434        ensures
435            forall|min: A, min_prime: A|
436                is_minimal(r, min, self) && is_minimal(r, min_prime, self) ==> min == min_prime,
437    {
438        assert forall|min: A, min_prime: A|
439            is_minimal(r, min, self) && is_minimal(r, min_prime, self) implies min == min_prime by {
440            self.lemma_minimal_equivalent_least(r, min);
441            self.lemma_minimal_equivalent_least(r, min_prime);
442            self.lemma_least_is_unique(r);
443        }
444    }
445
446    /// In a totally-ordered set, there exists at most one maximal element.
447    pub proof fn lemma_maximal_is_unique(self, r: spec_fn(A, A) -> bool)
448        requires
449            self.finite(),
450            total_ordering(r),
451        ensures
452            forall|max: A, max_prime: A|
453                is_maximal(r, max, self) && is_maximal(r, max_prime, self) ==> max == max_prime,
454    {
455        assert forall|max: A, max_prime: A|
456            is_maximal(r, max, self) && is_maximal(r, max_prime, self) implies max == max_prime by {
457            self.lemma_maximal_equivalent_greatest(r, max);
458            self.lemma_maximal_equivalent_greatest(r, max_prime);
459            self.lemma_greatest_is_unique(r);
460        }
461    }
462
463    /// Set difference with an additional element inserted decreases the size of
464    /// the result. This can be useful for proving termination when traversing
465    /// a set while tracking the elements that have already been handled.
466    pub broadcast proof fn lemma_set_insert_diff_decreases(self, s: Set<A>, elt: A)
467        requires
468            self.contains(elt),
469            !s.contains(elt),
470            self.finite(),
471        ensures
472            #[trigger] self.difference(s.insert(elt)).len() < self.difference(s).len(),
473    {
474        self.difference(s.insert(elt)).lemma_subset_not_in_lt(self.difference(s), elt);
475    }
476
477    /// If there is an element not present in a subset, its length is stricly smaller.
478    pub proof fn lemma_subset_not_in_lt(self: Set<A>, s2: Set<A>, elt: A)
479        requires
480            self.subset_of(s2),
481            s2.finite(),
482            !self.contains(elt),
483            s2.contains(elt),
484        ensures
485            self.len() < s2.len(),
486    {
487        let s2_no_elt = s2.remove(elt);
488        assert(self.len() <= s2_no_elt.len()) by {
489            lemma_len_subset(self, s2_no_elt);
490        }
491    }
492
493    /// Inserting an element and mapping a function over a set commute
494    pub broadcast proof fn lemma_set_map_insert_commute<B>(self, elt: A, f: spec_fn(A) -> B)
495        ensures
496            #[trigger] self.insert(elt).map(f) =~= self.map(f).insert(f(elt)),
497    {
498        assert forall|x: B| self.map(f).insert(f(elt)).contains(x) implies self.insert(elt).map(
499            f,
500        ).contains(x) by {
501            if x == f(elt) {
502                assert(self.insert(elt).contains(elt));
503            } else {
504                let y = choose|y: A| self.contains(y) && f(y) == x;
505                assert(self.insert(elt).contains(y));
506            }
507        }
508    }
509
510    /// `map` and `union` commute
511    pub proof fn lemma_map_union_commute<B>(self, t: Set<A>, f: spec_fn(A) -> B)
512        ensures
513            (self.union(t)).map(f) =~= self.map(f).union(t.map(f)),
514    {
515        broadcast use group_set_axioms;
516
517        let lhs = self.union(t).map(f);
518        let rhs = self.map(f).union(t.map(f));
519
520        assert forall|elem: B| rhs.contains(elem) implies lhs.contains(elem) by {
521            if self.map(f).contains(elem) {
522                let preimage = choose|preimage: A| self.contains(preimage) && f(preimage) == elem;
523                assert(self.union(t).contains(preimage));
524            } else {
525                assert(t.map(f).contains(elem));
526                let preimage = choose|preimage: A| t.contains(preimage) && f(preimage) == elem;
527                assert(self.union(t).contains(preimage));
528            }
529        }
530    }
531
532    /// Utility function for more concise universal quantification over sets
533    pub open spec fn all(&self, pred: spec_fn(A) -> bool) -> bool {
534        forall|x: A| self.contains(x) ==> pred(x)
535    }
536
537    /// Utility function for more concise existential quantification over sets
538    pub open spec fn any(&self, pred: spec_fn(A) -> bool) -> bool {
539        exists|x: A| self.contains(x) && pred(x)
540    }
541
542    /// `any` is preserved between predicates `p` and `q` if `p` implies `q`.
543    pub broadcast proof fn lemma_any_map_preserved_pred<B>(
544        self,
545        p: spec_fn(A) -> bool,
546        q: spec_fn(B) -> bool,
547        f: spec_fn(A) -> B,
548    )
549        requires
550            #[trigger] self.any(p),
551            forall|x: A| #[trigger] p(x) ==> q(f(x)),
552        ensures
553            #[trigger] self.map(f).any(q),
554    {
555        let x = choose|x: A| self.contains(x) && p(x);
556        assert(self.map(f).contains(f(x)));
557    }
558
559    /// Collecting all elements `b` where `f` returns `Some(b)`
560    pub open spec fn filter_map<B>(self, f: spec_fn(A) -> Option<B>) -> Set<B> {
561        self.map(
562            |elem: A|
563                match f(elem) {
564                    Option::Some(r) => set!{r},
565                    Option::None => set!{},
566                },
567        ).flatten()
568    }
569
570    /// Inserting commutes with `filter_map`
571    pub broadcast proof fn lemma_filter_map_insert<B>(
572        s: Set<A>,
573        f: spec_fn(A) -> Option<B>,
574        elem: A,
575    )
576        ensures
577            #[trigger] s.insert(elem).filter_map(f) == (match f(elem) {
578                Some(res) => s.filter_map(f).insert(res),
579                None => s.filter_map(f),
580            }),
581    {
582        broadcast use group_set_axioms;
583        broadcast use Set::lemma_set_map_insert_commute;
584
585        let lhs = s.insert(elem).filter_map(f);
586        let rhs = match f(elem) {
587            Some(res) => s.filter_map(f).insert(res),
588            None => s.filter_map(f),
589        };
590        let to_set = |elem: A|
591            match f(elem) {
592                Option::Some(r) => set!{r},
593                Option::None => set!{},
594            };
595        assert forall|r: B| #[trigger] lhs.contains(r) implies rhs.contains(r) by {
596            if f(elem) != Some(r) {
597                let orig = choose|orig: A| #[trigger]
598                    s.contains(orig) && f(orig) == Option::Some(r);
599                assert(to_set(orig) == set!{r});
600                assert(s.map(to_set).contains(to_set(orig)));
601            }
602        }
603        assert forall|r: B| #[trigger] rhs.contains(r) implies lhs.contains(r) by {
604            if Some(r) == f(elem) {
605                assert(s.insert(elem).map(to_set).contains(to_set(elem)));
606            } else {
607                let orig = choose|orig: A| #[trigger]
608                    s.contains(orig) && f(orig) == Option::Some(r);
609                assert(s.insert(elem).map(to_set).contains(to_set(orig)));
610            }
611        }
612        assert(lhs =~= rhs);
613    }
614
615    /// `filter_map` and `union` commute.
616    pub broadcast proof fn lemma_filter_map_union<B>(self, f: spec_fn(A) -> Option<B>, t: Set<A>)
617        ensures
618            #[trigger] self.union(t).filter_map(f) == self.filter_map(f).union(t.filter_map(f)),
619    {
620        broadcast use group_set_axioms;
621
622        let lhs = self.union(t).filter_map(f);
623        let rhs = self.filter_map(f).union(t.filter_map(f));
624        let to_set = |elem: A|
625            match f(elem) {
626                Option::Some(r) => set!{r},
627                Option::None => set!{},
628            };
629
630        assert forall|elem: B| rhs.contains(elem) implies lhs.contains(elem) by {
631            if self.filter_map(f).contains(elem) {
632                let x = choose|x: A| self.contains(x) && f(x) == Option::Some(elem);
633                assert(self.union(t).contains(x));
634                assert(self.union(t).map(to_set).contains(to_set(x)));
635            }
636            if t.filter_map(f).contains(elem) {
637                let x = choose|x: A| t.contains(x) && f(x) == Option::Some(elem);
638                assert(self.union(t).contains(x));
639                assert(self.union(t).map(to_set).contains(to_set(x)));
640            }
641        }
642        assert forall|elem: B| lhs.contains(elem) implies rhs.contains(elem) by {
643            let x = choose|x: A| self.union(t).contains(x) && f(x) == Option::Some(elem);
644            if self.contains(x) {
645                assert(self.map(to_set).contains(to_set(x)));
646                assert(self.filter_map(f).contains(elem));
647            } else {
648                assert(t.contains(x));
649                assert(t.map(to_set).contains(to_set(x)));
650                assert(t.filter_map(f).contains(elem));
651            }
652        }
653        assert(lhs =~= rhs);
654    }
655
656    /// `map` preserves finiteness
657    pub proof fn lemma_map_finite<B>(self, f: spec_fn(A) -> B)
658        requires
659            self.finite(),
660        ensures
661            self.map(f).finite(),
662        decreases self.len(),
663    {
664        broadcast use group_set_axioms;
665        broadcast use lemma_set_empty_equivalency_len;
666
667        if self.len() == 0 {
668            assert(forall|elem: A| !(#[trigger] self.contains(elem)));
669            assert forall|res: B| #[trigger] self.map(f).contains(res) implies false by {
670                let x = choose|x: A| self.contains(x) && f(x) == res;
671            }
672            assert(self.map(f) =~= Set::<B>::empty());
673        } else {
674            let x = choose|x: A| self.contains(x);
675            assert(self.map(f).contains(f(x)));
676            self.remove(x).lemma_map_finite(f);
677            assert(self.remove(x).insert(x) == self);
678            assert(self.map(f) == self.remove(x).map(f).insert(f(x)));
679        }
680    }
681
682    pub broadcast proof fn lemma_map_by_finite<B>(self, fwd: spec_fn(A) -> B, rev: spec_fn(B) -> A)
683        requires
684            self.finite(),
685        ensures
686            #[trigger] self.map_by(fwd, rev).finite(),
687    {
688        broadcast use lemma_set_subset_finite;
689
690        assert(self.map_by(fwd, rev).subset_of(self.map(fwd)));
691        self.lemma_map_finite(fwd);
692    }
693
694    pub broadcast proof fn lemma_map_flatten_by_finite<B>(
695        self,
696        fwd: spec_fn(A) -> Set<B>,
697        rev: spec_fn(B) -> A,
698    )
699        requires
700            self.finite(),
701            forall|a: A| self.contains(a) ==> fwd(a).finite(),
702        ensures
703            #[trigger] self.map_flatten_by(fwd, rev).finite(),
704    {
705        broadcast use lemma_set_subset_finite;
706
707        let s1 = self.map_flatten_by(fwd, rev);
708        let s2 = self.map(fwd).flatten();
709        assert forall|b: B| s1.contains(b) implies s2.contains(b) by {
710            assert(self.map(fwd).contains(fwd(rev(b))));
711        }
712        assert(s1.subset_of(s2));
713        self.lemma_map_finite(fwd);
714        self.map(fwd).lemma_flatten_finite();
715    }
716
717    pub broadcast proof fn lemma_set_all_subset(self, s2: Set<A>, p: spec_fn(A) -> bool)
718        requires
719            #[trigger] self.subset_of(s2),
720            s2.all(p),
721        ensures
722            #[trigger] self.all(p),
723    {
724        broadcast use group_set_axioms;
725
726    }
727
728    /// `filter_map` preserves finiteness.
729    pub broadcast proof fn lemma_filter_map_finite<B>(self, f: spec_fn(A) -> Option<B>)
730        requires
731            self.finite(),
732        ensures
733            #[trigger] self.filter_map(f).finite(),
734        decreases self.len(),
735    {
736        broadcast use group_set_axioms;
737        broadcast use Set::lemma_filter_map_insert;
738
739        let mapped = self.filter_map(f);
740        if self.len() == 0 {
741            assert(self.filter_map(f) =~= Set::<B>::empty());
742        } else {
743            let elem = self.choose();
744            self.remove(elem).lemma_filter_map_finite(f);
745            assert(self =~= self.remove(elem).insert(elem));
746        }
747    }
748
749    /// Conversion to a sequence and back to a set is the identity function.
750    pub broadcast proof fn lemma_to_seq_to_set_id(self)
751        requires
752            self.finite(),
753        ensures
754            #[trigger] self.to_seq().to_set() =~= self,
755        decreases self.len(),
756    {
757        broadcast use group_set_axioms;
758        broadcast use lemma_set_empty_equivalency_len;
759        broadcast use super::seq_lib::group_seq_properties;
760
761        if self.len() == 0 {
762            assert(self.to_seq().to_set() =~= Set::<A>::empty());
763        } else {
764            let elem = self.choose();
765            self.remove(elem).lemma_to_seq_to_set_id();
766            assert(self =~= self.remove(elem).insert(elem));
767            assert(self.to_seq().to_set() =~= self.remove(elem).to_seq().to_set().insert(elem));
768        }
769    }
770}
771
772impl<A> Set<Set<A>> {
773    pub open spec fn flatten(self) -> Set<A> {
774        Set::new(
775            |elem| exists|elem_s: Set<A>| #[trigger] self.contains(elem_s) && elem_s.contains(elem),
776        )
777    }
778
779    pub broadcast proof fn flatten_insert_union_commute(self, other: Set<A>)
780        ensures
781            self.flatten().union(other) =~= #[trigger] self.insert(other).flatten(),
782    {
783        broadcast use group_set_axioms;
784
785        let lhs = self.flatten().union(other);
786        let rhs = self.insert(other).flatten();
787
788        assert forall|elem: A| lhs.contains(elem) implies rhs.contains(elem) by {
789            if exists|s: Set<A>| self.contains(s) && s.contains(elem) {
790                let s = choose|s: Set<A>| self.contains(s) && s.contains(elem);
791                assert(self.insert(other).contains(s));
792                assert(s.contains(elem));
793            } else {
794                assert(self.insert(other).contains(other));
795            }
796        }
797    }
798
799    pub proof fn lemma_flatten_finite(self)
800        requires
801            self.finite(),
802            forall|s: Set<A>| self.contains(s) ==> #[trigger] s.finite(),
803        ensures
804            self.flatten().finite(),
805        decreases self.len(),
806    {
807        broadcast use group_set_axioms;
808
809        if self.len() == 0 {
810            assert(self.flatten() =~= Set::<A>::empty());
811        } else {
812            let s = self.choose();
813            let self2 = self.remove(s);
814            self2.lemma_flatten_finite();
815            self2.flatten_insert_union_commute(s);
816        }
817    }
818}
819
820pub trait FiniteRange: Sized {
821    spec fn range_set(lo: Self, hi: Self) -> Set<Self>;
822
823    spec fn range_len(lo: Self, hi: Self) -> nat;
824
825    proof fn range_properties(lo: Self, hi: Self)
826        ensures
827            Self::range_set(lo, hi).finite(),
828            Self::range_set(lo, hi).len() == Self::range_len(lo, hi),
829    ;
830}
831
832pub broadcast proof fn range_set_properties<A: FiniteRange>(lo: A, hi: A)
833    ensures
834        (#[trigger] A::range_set(lo, hi)).finite(),
835        A::range_set(lo, hi).len() == A::range_len(lo, hi),
836{
837    A::range_properties(lo, hi);
838}
839
840pub trait FiniteFull: Sized {
841    proof fn full_properties()
842        ensures
843            Set::<Self>::full().finite(),
844    ;
845}
846
847pub broadcast proof fn full_set_properties<A: FiniteFull>()
848    ensures
849        #![trigger Set::<A>::full()]
850        (Set::<A>::full()).finite(),
851{
852    A::full_properties();
853}
854
855impl<A: FiniteRange> Set<A> {
856    #[verifier::inline]
857    pub open spec fn range(lo: A, hi: A) -> Set<A> {
858        A::range_set(lo, hi)
859    }
860
861    #[verifier::inline]
862    pub open spec fn range_inclusive(lo: A, hi: A) -> Set<A> {
863        A::range_set(lo, hi).insert(hi)
864    }
865}
866
867impl<A: FiniteFull> Set<A> {
868    #[verifier::inline]
869    pub open spec fn from_finite_type(f: spec_fn(A) -> bool) -> Set<A> {
870        Set::<A>::full().filter(f)
871    }
872}
873
874// Macro to implement the trait for every numeric type. We need a macro here
875// because 'as nat' can't be written as a type generic.
876macro_rules! range_impls {
877    ([$($t:ty)*]) => {
878        $(
879            verus! {
880                impl FiniteRange for $t {
881                    open spec fn range_set(lo: Self, hi: Self) -> Set<Self> {
882                        Set::new(|i: Self| lo <= i < hi)
883                    }
884                    open spec fn range_len(lo: Self, hi: Self) -> nat {
885                        if lo <= hi { (hi - lo) as nat } else { 0 }
886                    }
887                    proof fn range_properties(lo: Self, hi: Self)
888                        decreases hi - lo
889                    {
890                        broadcast use axiom_set_empty_finite;
891                        broadcast use axiom_set_empty_len;
892                        broadcast use axiom_set_insert_finite;
893
894                        if hi <= lo {
895                            assert(Self::range_set(lo, hi).is_empty());
896                        } else {
897                            let hi1 = (hi - 1) as $t;
898                            Self::range_properties(lo, hi1);
899                            assert(Self::range_set(lo, hi) == Self::range_set(lo, hi1).insert(hi1));
900                            axiom_set_insert_finite(Self::range_set(lo, hi1), hi1);
901                        }
902                    }
903                }
904            } // verus!
905        )*
906    }
907}
908
909macro_rules! full_impls {
910    ([$($t:ty)*]) => {
911        $(
912            verus! {
913                impl FiniteFull for $t {
914                    proof fn full_properties() {
915                        broadcast use axiom_set_insert_finite;
916
917                        assert(Set::<$t>::full() == Set::range_inclusive($t::MIN, $t::MAX));
918                        <$t as FiniteRange>::range_properties($t::MIN, $t::MAX);
919                    }
920                }
921            } // verus!
922        )*
923    }
924}
925
926// Make Set::range available for all of the Verus numeric types
927range_impls!([
928    int nat
929    usize u8 u16 u32 u64 u128
930    isize i8 i16 i32 i64 i128
931]);
932
933// Make Set::full available for all of the Verus numeric types
934full_impls!([
935    usize u8 u16 u32 u64 u128
936    isize i8 i16 i32 i64 i128
937]);
938
939/// Two sets are equal iff mapping `f` results in equal sets, if `f` is injective.
940pub proof fn lemma_sets_eq_iff_injective_map_eq<T, S>(s1: Set<T>, s2: Set<T>, f: spec_fn(T) -> S)
941    requires
942        super::relations::injective(f),
943    ensures
944        (s1 == s2) <==> (s1.map(f) == s2.map(f)),
945{
946    broadcast use group_set_axioms;
947
948    if (s1.map(f) == s2.map(f)) {
949        assert(s1.map(f).len() == s2.map(f).len());
950        if !s1.subset_of(s2) {
951            let x = choose|x: T| s1.contains(x) && !s2.contains(x);
952            assert(s1.map(f).contains(f(x)));
953        } else if !s2.subset_of(s1) {
954            let x = choose|x: T| s2.contains(x) && !s1.contains(x);
955            assert(s2.map(f).contains(f(x)));
956        }
957        assert(s1 =~= s2);
958    }
959}
960
961/// Two sets are equal iff applying an injective (in the union of the sets) function `f` to each set produces equal sets.
962pub proof fn lemma_sets_eq_iff_injective_map_on_eq<T, S>(s1: Set<T>, s2: Set<T>, f: spec_fn(T) -> S)
963    requires
964        super::relations::injective_on(f, s1 + s2),
965    ensures
966        (s1 == s2) <==> (s1.map(f) == s2.map(f)),
967{
968    broadcast use group_set_axioms;
969
970    if (s1.map(f) == s2.map(f)) {
971        assert(s1.map(f).len() == s2.map(f).len());
972        if !s1.subset_of(s2) {
973            let x = choose|x: T| s1.contains(x) && !s2.contains(x);
974            assert(s1.map(f).contains(f(x)));
975        } else if !s2.subset_of(s1) {
976            let x = choose|x: T| s2.contains(x) && !s1.contains(x);
977            assert(s2.map(f).contains(f(x)));
978        }
979        assert(s1 =~= s2);
980    }
981}
982
983/// The result of inserting an element `a` into a set `s` is finite iff `s` is finite.
984pub broadcast proof fn lemma_set_insert_finite_iff<A>(s: Set<A>, a: A)
985    ensures
986        #[trigger] s.insert(a).finite() <==> s.finite(),
987{
988    if s.insert(a).finite() {
989        if s.contains(a) {
990            assert(s == s.insert(a));
991        } else {
992            assert(s == s.insert(a).remove(a));
993        }
994    }
995    assert(s.insert(a).finite() ==> s.finite());
996}
997
998/// The result of removing an element `a` into a set `s` is finite iff `s` is finite.
999pub broadcast proof fn lemma_set_remove_finite_iff<A>(s: Set<A>, a: A)
1000    ensures
1001        #[trigger] s.remove(a).finite() <==> s.finite(),
1002{
1003    if s.remove(a).finite() {
1004        if s.contains(a) {
1005            assert(s == s.remove(a).insert(a));
1006        } else {
1007            assert(s == s.remove(a));
1008        }
1009    }
1010}
1011
1012/// The union of two sets is finite iff both sets are finite.
1013pub broadcast proof fn lemma_set_union_finite_iff<A>(s1: Set<A>, s2: Set<A>)
1014    ensures
1015        #[trigger] s1.union(s2).finite() <==> s1.finite() && s2.finite(),
1016{
1017    if s1.union(s2).finite() {
1018        lemma_set_union_finite_implies_sets_finite(s1, s2);
1019    }
1020}
1021
1022pub proof fn lemma_set_union_finite_implies_sets_finite<A>(s1: Set<A>, s2: Set<A>)
1023    requires
1024        s1.union(s2).finite(),
1025    ensures
1026        s1.finite(),
1027        s2.finite(),
1028    decreases s1.union(s2).len(),
1029{
1030    if s1.union(s2) =~= set![] {
1031        assert(s1 =~= set![]);
1032        assert(s2 =~= set![]);
1033    } else {
1034        let a = s1.union(s2).choose();
1035        assert(s1.remove(a).union(s2.remove(a)) == s1.union(s2).remove(a));
1036        axiom_set_remove_len(s1.union(s2), a);
1037        lemma_set_union_finite_implies_sets_finite(s1.remove(a), s2.remove(a));
1038        assert(forall|s: Set<A>|
1039            #![auto]
1040            s.remove(a).insert(a) == if s.contains(a) {
1041                s
1042            } else {
1043                s.insert(a)
1044            });
1045        lemma_set_insert_finite_iff(s1, a);
1046        lemma_set_insert_finite_iff(s2, a);
1047    }
1048}
1049
1050/// The size of a union of two sets is less than or equal to the size of
1051/// both individual sets combined.
1052pub proof fn lemma_len_union<A>(s1: Set<A>, s2: Set<A>)
1053    requires
1054        s1.finite(),
1055        s2.finite(),
1056    ensures
1057        s1.union(s2).len() <= s1.len() + s2.len(),
1058    decreases s1.len(),
1059{
1060    if s1.is_empty() {
1061        assert(s1.union(s2) =~= s2);
1062    } else {
1063        let a = s1.choose();
1064        if s2.contains(a) {
1065            assert(s1.union(s2) =~= s1.remove(a).union(s2));
1066        } else {
1067            assert(s1.union(s2).remove(a) =~= s1.remove(a).union(s2));
1068        }
1069        lemma_len_union::<A>(s1.remove(a), s2);
1070    }
1071}
1072
1073/// The size of a union of two sets is greater than or equal to the size of
1074/// both individual sets.
1075pub proof fn lemma_len_union_ind<A>(s1: Set<A>, s2: Set<A>)
1076    requires
1077        s1.finite(),
1078        s2.finite(),
1079    ensures
1080        s1.union(s2).len() >= s1.len(),
1081        s1.union(s2).len() >= s2.len(),
1082    decreases s2.len(),
1083{
1084    broadcast use group_set_properties;
1085
1086    if s2.len() == 0 {
1087    } else {
1088        let y = choose|y: A| s2.contains(y);
1089        if s1.contains(y) {
1090            assert(s1.remove(y).union(s2.remove(y)) =~= s1.union(s2).remove(y));
1091            lemma_len_union_ind(s1.remove(y), s2.remove(y))
1092        } else {
1093            assert(s1.union(s2.remove(y)) =~= s1.union(s2).remove(y));
1094            lemma_len_union_ind(s1, s2.remove(y))
1095        }
1096    }
1097}
1098
1099/// The size of the intersection of finite set `s1` and set `s2` is less than or equal to the size of `s1`.
1100pub proof fn lemma_len_intersect<A>(s1: Set<A>, s2: Set<A>)
1101    requires
1102        s1.finite(),
1103    ensures
1104        s1.intersect(s2).len() <= s1.len(),
1105    decreases s1.len(),
1106{
1107    if s1.is_empty() {
1108        assert(s1.intersect(s2) =~= s1);
1109    } else {
1110        let a = s1.choose();
1111        assert(s1.intersect(s2).remove(a) =~= s1.remove(a).intersect(s2));
1112        lemma_len_intersect::<A>(s1.remove(a), s2);
1113    }
1114}
1115
1116/// If `s1` is a subset of finite set `s2`, then the size of `s1` is less than or equal to
1117/// the size of `s2` and `s1` must be finite.
1118pub proof fn lemma_len_subset<A>(s1: Set<A>, s2: Set<A>)
1119    requires
1120        s2.finite(),
1121        s1.subset_of(s2),
1122    ensures
1123        s1.len() <= s2.len(),
1124        s1.finite(),
1125{
1126    lemma_len_intersect::<A>(s2, s1);
1127    assert(s2.intersect(s1) =~= s1);
1128}
1129
1130/// A subset of a finite set `s` is finite.
1131pub broadcast proof fn lemma_set_subset_finite<A>(s: Set<A>, sub: Set<A>)
1132    requires
1133        s.finite(),
1134        sub.subset_of(s),
1135    ensures
1136        #![trigger sub.subset_of(s)]
1137        sub.finite(),
1138{
1139    let complement = s.difference(sub);
1140    assert(sub =~= s.difference(complement));
1141}
1142
1143/// The size of the difference of finite set `s1` and set `s2` is less than or equal to the size of `s1`.
1144pub proof fn lemma_len_difference<A>(s1: Set<A>, s2: Set<A>)
1145    requires
1146        s1.finite(),
1147    ensures
1148        s1.difference(s2).len() <= s1.len(),
1149    decreases s1.len(),
1150{
1151    if s1.is_empty() {
1152        assert(s1.difference(s2) =~= s1);
1153    } else {
1154        let a = s1.choose();
1155        assert(s1.difference(s2).remove(a) =~= s1.remove(a).difference(s2));
1156        lemma_len_difference::<A>(s1.remove(a), s2);
1157    }
1158}
1159
1160/// Creates a finite set of integers in the range [lo, hi).
1161pub open spec fn set_int_range(lo: int, hi: int) -> Set<int> {
1162    Set::new(|i: int| lo <= i && i < hi)
1163}
1164
1165/// If a set solely contains integers in the range [a, b), then its size is
1166/// bounded by b - a.
1167pub proof fn lemma_int_range(lo: int, hi: int)
1168    requires
1169        lo <= hi,
1170    ensures
1171        set_int_range(lo, hi).finite(),
1172        set_int_range(lo, hi).len() == hi - lo,
1173    decreases hi - lo,
1174{
1175    if lo == hi {
1176        assert(set_int_range(lo, hi) =~= Set::empty());
1177    } else {
1178        lemma_int_range(lo, hi - 1);
1179        assert(set_int_range(lo, hi - 1).insert(hi - 1) =~= set_int_range(lo, hi));
1180    }
1181}
1182
1183/// If x is a subset of y and the size of x is equal to the size of y, x is equal to y.
1184pub proof fn lemma_subset_equality<A>(x: Set<A>, y: Set<A>)
1185    requires
1186        x.subset_of(y),
1187        x.finite(),
1188        y.finite(),
1189        x.len() == y.len(),
1190    ensures
1191        x =~= y,
1192    decreases x.len(),
1193{
1194    broadcast use group_set_properties;
1195
1196    if x =~= Set::<A>::empty() {
1197    } else {
1198        let e = x.choose();
1199        lemma_subset_equality(x.remove(e), y.remove(e));
1200    }
1201}
1202
1203/// If an injective function is applied to each element of a set to construct
1204/// another set, the two sets have the same size.
1205pub proof fn lemma_map_size<A, B>(x: Set<A>, y: Set<B>, f: spec_fn(A) -> B)
1206    requires
1207        x.finite(),
1208        injective_on(f, x),
1209        x.map(f) == y,
1210    ensures
1211        y.finite(),
1212        x.len() == y.len(),
1213    decreases x.len(),
1214{
1215    broadcast use group_set_properties;
1216
1217    if x.len() == 0 {
1218        if !y.is_empty() {
1219            let e = y.choose();
1220        }
1221    } else {
1222        let a = x.choose();
1223        assert(x.remove(a).map(f) == y.remove(f(a)));
1224        lemma_map_size(x.remove(a), y.remove(f(a)), f);
1225        assert(y == y.remove(f(a)).insert(f(a)));
1226    }
1227}
1228
1229/// If any function is applied to each element of a set to construct
1230/// another set, the constructed set's length is at most the original's
1231pub proof fn lemma_map_size_bound<A, B>(x: Set<A>, y: Set<B>, f: spec_fn(A) -> B)
1232    requires
1233        x.finite(),
1234        x.map(f) == y,
1235    ensures
1236        y.finite(),
1237        y.len() <= x.len(),
1238    decreases x.len(),
1239{
1240    broadcast use group_set_properties;
1241
1242    if x.is_empty() {
1243        if !y.is_empty() {
1244            let e = y.choose();
1245        }
1246    } else {
1247        let xx = x.choose();
1248        let img = f(xx);
1249        let pre = x.filter(|a: A| f(a) == f(xx));
1250        x.lemma_len_filter(|a: A| f(a) == f(xx));
1251        let wit = choose|a: A| x.contains(a) && f(a) == f(xx);
1252        assert forall|b: B| (#[trigger] y.remove(f(xx)).contains(b)) implies exists|a: A|
1253            x.difference(pre).contains(a) && f(a) == b by {
1254            let pre_wit = choose|a: A| x.contains(a) && f(a) == b;
1255            assert(x.difference(pre).contains(pre_wit));
1256        }
1257
1258        assert(x == x.difference(pre).union(pre));
1259        assert(y == y.remove(f(xx)).insert(f(xx)));
1260        assert(x.difference(pre).map(f) == y.remove(f(xx)));
1261        lemma_map_size_bound(x.difference(pre), y.remove(f(xx)), f);
1262    }
1263}
1264
1265// This verified lemma used to be an axiom in the Dafny prelude
1266/// Taking the union of sets `a` and `b` and then taking the union of the result with `b`
1267/// is the same as taking the union of `a` and `b` once.
1268pub broadcast proof fn lemma_set_union_again1<A>(a: Set<A>, b: Set<A>)
1269    ensures
1270        #[trigger] a.union(b).union(b) =~= a.union(b),
1271{
1272}
1273
1274// This verified lemma used to be an axiom in the Dafny prelude
1275/// Taking the union of sets `a` and `b` and then taking the union of the result with `a`
1276/// is the same as taking the union of `a` and `b` once.
1277pub broadcast proof fn lemma_set_union_again2<A>(a: Set<A>, b: Set<A>)
1278    ensures
1279        #[trigger] a.union(b).union(a) =~= a.union(b),
1280{
1281}
1282
1283// This verified lemma used to be an axiom in the Dafny prelude
1284/// Taking the intersection of sets `a` and `b` and then taking the intersection of the result with `b`
1285/// is the same as taking the intersection of `a` and `b` once.
1286pub broadcast proof fn lemma_set_intersect_again1<A>(a: Set<A>, b: Set<A>)
1287    ensures
1288        #![trigger (a.intersect(b)).intersect(b)]
1289        (a.intersect(b)).intersect(b) =~= a.intersect(b),
1290{
1291}
1292
1293// This verified lemma used to be an axiom in the Dafny prelude
1294/// Taking the intersection of sets `a` and `b` and then taking the intersection of the result with `a`
1295/// is the same as taking the intersection of `a` and `b` once.
1296pub broadcast proof fn lemma_set_intersect_again2<A>(a: Set<A>, b: Set<A>)
1297    ensures
1298        #![trigger (a.intersect(b)).intersect(a)]
1299        (a.intersect(b)).intersect(a) =~= a.intersect(b),
1300{
1301}
1302
1303// This verified lemma used to be an axiom in the Dafny prelude
1304/// If set `s2` contains element `a`, then the set difference of `s1` and `s2` does not contain `a`.
1305pub broadcast proof fn lemma_set_difference2<A>(s1: Set<A>, s2: Set<A>, a: A)
1306    ensures
1307        #![trigger s1.difference(s2).contains(a)]
1308        s2.contains(a) ==> !s1.difference(s2).contains(a),
1309{
1310}
1311
1312// This verified lemma used to be an axiom in the Dafny prelude
1313/// If sets `a` and `b` are disjoint, meaning they have no elements in common, then the set difference
1314/// of `a + b` and `b` is equal to `a` and the set difference of `a + b` and `a` is equal to `b`.
1315pub broadcast proof fn lemma_set_disjoint<A>(a: Set<A>, b: Set<A>)
1316    ensures
1317        #![trigger (a + b).difference(a)]  //TODO: this might be too free
1318        a.disjoint(b) ==> ((a + b).difference(a) =~= b && (a + b).difference(b) =~= a),
1319{
1320}
1321
1322// This verified lemma used to be an axiom in the Dafny prelude
1323// Dafny encodes the second clause with a single directional, although
1324// it should be fine with both directions?
1325// REVIEW: excluded from broadcast group if trigger is too free
1326//         also not that some proofs in seq_lib requires this lemma
1327/// Set `s` has length 0 if and only if it is equal to the empty set. If `s` has length greater than 0,
1328/// Then there must exist an element `x` such that `s` contains `x`.
1329pub broadcast proof fn lemma_set_empty_equivalency_len<A>(s: Set<A>)
1330    requires
1331        s.finite(),
1332    ensures
1333        #![trigger s.len()]
1334        (s.len() == 0 <==> s == Set::<A>::empty()) && (s.len() != 0 ==> exists|x: A| s.contains(x)),
1335{
1336    assert(s.len() == 0 ==> s =~= Set::empty()) by {
1337        if s.len() == 0 {
1338            assert(forall|a: A| !(Set::empty().contains(a)));
1339            assert(Set::<A>::empty().len() == 0);
1340            assert(Set::<A>::empty().len() == s.len());
1341            assert((exists|a: A| s.contains(a)) || (forall|a: A| !s.contains(a)));
1342            if exists|a: A| s.contains(a) {
1343                let a = s.choose();
1344                assert(s.remove(a).len() == s.len() - 1) by {
1345                    axiom_set_remove_len(s, a);
1346                }
1347            }
1348        }
1349    }
1350    assert(s.len() == 0 <== s =~= Set::empty());
1351}
1352
1353// This verified lemma used to be an axiom in the Dafny prelude
1354/// If sets `a` and `b` are disjoint, meaning they share no elements in common, then the length
1355/// of the union `a + b` is equal to the sum of the lengths of `a` and `b`.
1356pub broadcast proof fn lemma_set_disjoint_lens<A>(a: Set<A>, b: Set<A>)
1357    requires
1358        a.finite(),
1359        b.finite(),
1360    ensures
1361        a.disjoint(b) ==> #[trigger] (a + b).len() == a.len() + b.len(),
1362    decreases a.len(),
1363{
1364    if a.len() == 0 {
1365        lemma_set_empty_equivalency_len(a);
1366        assert(a + b =~= b);
1367    } else {
1368        if a.disjoint(b) {
1369            let x = a.choose();
1370            assert(a.remove(x) + b =~= (a + b).remove(x));
1371            lemma_set_disjoint_lens(a.remove(x), b);
1372        }
1373    }
1374}
1375
1376/// Two sets are disjoint iff their intersection is empty
1377pub proof fn lemma_disjoint_iff_empty_intersection<T>(a: Set<T>, b: Set<T>)
1378    ensures
1379        a.disjoint(b) <==> a.intersect(b).is_empty(),
1380{
1381    broadcast use group_set_properties;
1382
1383    if a.disjoint(b) {
1384        assert(b.disjoint(a));
1385        assert(forall|x: T| a.contains(x) ==> !(a.contains(x) && b.contains(x)));
1386        assert(forall|x: T| b.contains(x) ==> !(a.contains(x) && b.contains(x)));
1387        assert(forall|x: T| !a.intersect(b).contains(x));
1388    }
1389    if a.intersect(b).is_empty() {
1390        assert(forall|x: T| !a.intersect(b).contains(x));
1391        if !a.disjoint(b) {
1392            assert(exists|x: T| a.contains(x) && b.contains(x));
1393            let x = choose|x: T| a.contains(x) && b.contains(x);
1394            assert(a.intersect(b).contains(x));
1395            assert(!a.intersect(b).is_empty());
1396        }
1397    }
1398}
1399
1400// This verified lemma used to be an axiom in the Dafny prelude
1401/// The length of the union between two sets added to the length of the intersection between the
1402/// two sets is equal to the sum of the lengths of the two sets.
1403pub broadcast proof fn lemma_set_intersect_union_lens<A>(a: Set<A>, b: Set<A>)
1404    requires
1405        a.finite(),
1406        b.finite(),
1407    ensures
1408        #[trigger] (a + b).len() + #[trigger] a.intersect(b).len() == a.len() + b.len(),
1409    decreases a.len(),
1410{
1411    if a.len() == 0 {
1412        lemma_set_empty_equivalency_len(a);
1413        assert(a + b =~= b);
1414        assert(a.intersect(b) =~= Set::empty());
1415        assert(a.intersect(b).len() == 0);
1416    } else {
1417        let x = a.choose();
1418        lemma_set_intersect_union_lens(a.remove(x), b);
1419        if (b.contains(x)) {
1420            assert(a.remove(x) + b =~= (a + b));
1421            assert(a.intersect(b).remove(x) =~= a.remove(x).intersect(b));
1422        } else {
1423            assert(a.remove(x) + b =~= (a + b).remove(x));
1424            assert(a.remove(x).intersect(b) =~= a.intersect(b));
1425        }
1426    }
1427}
1428
1429// This verified lemma used to be an axiom in the Dafny prelude
1430/// The length of the set difference `A \ B` added to the length of the set difference `B \ A` added to
1431/// the length of the intersection `A ∩ B` is equal to the length of the union `A + B`.
1432///
1433/// The length of the set difference `A \ B` is equal to the length of `A` minus the length of the
1434/// intersection `A ∩ B`.
1435pub broadcast proof fn lemma_set_difference_len<A>(a: Set<A>, b: Set<A>)
1436    requires
1437        a.finite(),
1438        b.finite(),
1439    ensures
1440        (#[trigger] a.difference(b).len() + b.difference(a).len() + a.intersect(b).len() == (a
1441            + b).len()) && (a.difference(b).len() == a.len() - a.intersect(b).len()),
1442    decreases a.len(),
1443{
1444    if a.len() == 0 {
1445        lemma_set_empty_equivalency_len(a);
1446        assert(a.difference(b) =~= Set::empty());
1447        assert(b.difference(a) =~= b);
1448        assert(a.intersect(b) =~= Set::empty());
1449        assert(a + b =~= b);
1450    } else {
1451        let x = a.choose();
1452        lemma_set_difference_len(a.remove(x), b);
1453        if b.contains(x) {
1454            assert(a.intersect(b).remove(x) =~= a.remove(x).intersect(b));
1455            assert(a.remove(x).difference(b) =~= a.difference(b));
1456            assert(b.difference(a.remove(x)).remove(x) =~= b.difference(a));
1457            assert(a.remove(x) + b =~= a + b);
1458        } else {
1459            assert(a.remove(x) + b =~= (a + b).remove(x));
1460            assert(a.remove(x).difference(b) =~= a.difference(b).remove(x));
1461            assert(b.difference(a.remove(x)) =~= b.difference(a));
1462            assert(a.remove(x).intersect(b) =~= a.intersect(b));
1463        }
1464    }
1465}
1466
1467pub broadcast group group_set_properties {
1468    lemma_set_union_again1,
1469    lemma_set_union_again2,
1470    lemma_set_intersect_again1,
1471    lemma_set_intersect_again2,
1472    lemma_set_difference2,
1473    lemma_set_disjoint,
1474    lemma_set_disjoint_lens,
1475    lemma_set_intersect_union_lens,
1476    lemma_set_difference_len,
1477    // REVIEW: exclude from broadcast group if trigger is too free
1478    //         also note that some proofs in seq_lib requires this lemma
1479    lemma_set_empty_equivalency_len,
1480}
1481
1482pub broadcast proof fn axiom_is_empty<A>(s: Set<A>)
1483    requires
1484        !(#[trigger] s.is_empty()),
1485    ensures
1486        exists|a: A| s.contains(a),
1487{
1488    admit();  // REVIEW, should this be in `set`, or have a proof?
1489}
1490
1491pub broadcast proof fn axiom_is_empty_len0<A>(s: Set<A>)
1492    ensures
1493        #[trigger] s.is_empty() <==> (s.finite() && s.len() == 0),
1494{
1495}
1496
1497#[doc(hidden)]
1498#[verifier::inline]
1499pub open spec fn check_argument_is_set<A>(s: Set<A>) -> Set<A> {
1500    s
1501}
1502
1503/// Prove two sets equal by extensionality. Usage is:
1504///
1505/// ```rust
1506/// assert_sets_equal!(set1 == set2);
1507/// ```
1508///
1509/// or,
1510///
1511/// ```rust
1512/// assert_sets_equal!(set1 == set2, elem => {
1513///     // prove that set1.contains(elem) iff set2.contains(elem)
1514/// });
1515/// ```
1516#[macro_export]
1517macro_rules! assert_sets_equal {
1518    [$($tail:tt)*] => {
1519        $crate::vstd::prelude::verus_proof_macro_exprs!($crate::vstd::set_lib::assert_sets_equal_internal!($($tail)*))
1520    };
1521}
1522
1523#[macro_export]
1524#[doc(hidden)]
1525macro_rules! assert_sets_equal_internal {
1526    (::vstd::prelude::spec_eq($s1:expr, $s2:expr)) => {
1527        $crate::vstd::set_lib::assert_sets_equal_internal!($s1, $s2)
1528    };
1529    (::vstd::prelude::spec_eq($s1:expr, $s2:expr), $elem:ident $( : $t:ty )? => $bblock:block) => {
1530        $crate::vstd::set_lib::assert_sets_equal_internal!($s1, $s2, $elem $( : $t )? => $bblock)
1531    };
1532    (crate::prelude::spec_eq($s1:expr, $s2:expr)) => {
1533        $crate::vstd::set_lib::assert_sets_equal_internal!($s1, $s2)
1534    };
1535    (crate::prelude::spec_eq($s1:expr, $s2:expr), $elem:ident $( : $t:ty )? => $bblock:block) => {
1536        $crate::vstd::set_lib::assert_sets_equal_internal!($s1, $s2, $elem $( : $t )? => $bblock)
1537    };
1538    (crate::verus_builtin::spec_eq($s1:expr, $s2:expr)) => {
1539        $crate::vstd::set_lib::assert_sets_equal_internal!($s1, $s2)
1540    };
1541    (crate::verus_builtin::spec_eq($s1:expr, $s2:expr), $elem:ident $( : $t:ty )? => $bblock:block) => {
1542        $crate::vstd::set_lib::assert_sets_equal_internal!($s1, $s2, $elem $( : $t )? => $bblock)
1543    };
1544    ($s1:expr, $s2:expr $(,)?) => {
1545        $crate::vstd::set_lib::assert_sets_equal_internal!($s1, $s2, elem => { })
1546    };
1547    ($s1:expr, $s2:expr, $elem:ident $( : $t:ty )? => $bblock:block) => {
1548        #[verifier::spec] let s1 = $crate::vstd::set_lib::check_argument_is_set($s1);
1549        #[verifier::spec] let s2 = $crate::vstd::set_lib::check_argument_is_set($s2);
1550        $crate::vstd::prelude::assert_by($crate::vstd::prelude::equal(s1, s2), {
1551            $crate::vstd::prelude::assert_forall_by(|$elem $( : $t )?| {
1552                $crate::vstd::prelude::ensures(
1553                    $crate::vstd::prelude::imply(s1.contains($elem), s2.contains($elem))
1554                    &&
1555                    $crate::vstd::prelude::imply(s2.contains($elem), s1.contains($elem))
1556                );
1557                { $bblock }
1558            });
1559            $crate::vstd::prelude::assert_($crate::vstd::prelude::ext_equal(s1, s2));
1560        });
1561    }
1562}
1563
1564pub broadcast group group_set_lib_default {
1565    axiom_is_empty,
1566    axiom_is_empty_len0,
1567    lemma_set_subset_finite,
1568    Set::lemma_map_by_finite,
1569    Set::lemma_map_flatten_by_finite,
1570    range_set_properties,
1571    full_set_properties,
1572}
1573
1574pub use assert_sets_equal_internal;
1575pub use assert_sets_equal;
1576
1577} // verus!