Skip to main content

vstd/
set_lib.rs

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