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    /// Any sequence converted from set has no duplicates
660    pub broadcast proof fn lemma_to_seq_no_duplicates(self)
661        ensures
662            #[trigger] self.to_seq().no_duplicates(),
663        decreases self.len(),
664    {
665        broadcast use super::seq::group_seq_axioms;
666
667        if self.len() == 0 {
668        } else {
669            let x = choose|x: A| #[trigger]
670                self.contains(x) && self.to_seq() =~= seq![x] + self.remove(x).to_seq();
671            let seq = self.to_seq();
672            let seq2 = self.remove(x).to_seq();
673            assert(seq2.no_duplicates()) by { self.remove(x).lemma_to_seq_no_duplicates() }
674            assert(seq2.to_set() == self.remove(x)) by {
675                self.remove(x).lemma_to_seq_to_set_id();
676            }
677            assert(!seq2.contains(x)) by { seq2.to_set_ensures() }
678        }
679    }
680
681    /// Conversion from set to seq preserves the length
682    pub broadcast proof fn lemma_to_seq_len(self)
683        ensures
684            #[trigger] self.to_seq().len() == self.len(),
685        decreases self.len(),
686    {
687        broadcast use super::seq::group_seq_axioms;
688
689        if self.len() == 0 {
690        } else {
691            let x = choose|x: A| #[trigger]
692                self.contains(x) && self.to_seq() =~= seq![x] + self.remove(x).to_seq();
693            self.remove(x).lemma_to_seq_len();
694        }
695    }
696}
697
698impl<A> Set<Set<A>> {
699    /// This function creates a set from all the elements of all the elements
700    /// of `self`.
701    pub closed spec fn flatten(self) -> Set<A> {
702        Set::new(
703            |elem| exists|elem_s: Set<A>| #[trigger] self.contains(elem_s) && elem_s.contains(elem),
704        ).unwrap()
705    }
706
707    /// This helper lemma demonstrates that `Self::flatten` is finite,
708    /// so it produces a valid `Set`.
709    proof fn lemma_flatten_finite(self)
710        ensures
711            ISet::new(
712                |elem|
713                    exists|elem_s: Set<A>| #[trigger]
714                        self.contains(elem_s) && elem_s.contains(elem),
715            ).finite(),
716        decreases self.len(),
717    {
718        let flatten_f = |elem|
719            exists|elem_s: Set<A>| #[trigger] self.contains(elem_s) && elem_s.contains(elem);
720        if forall|s: Set<A>| !self.contains(s) {
721            assert(self =~= Set::<Set<A>>::empty());
722            assert(ISet::new(flatten_f) =~= ISet::<A>::empty());
723        } else {
724            let s = choose|s: Set<A>| self.contains(s);
725            self.remove(s).lemma_flatten_finite();
726            let flatten_remove_f = |elem|
727                exists|elem_s: Set<A>| #[trigger]
728                    self.remove(s).contains(elem_s) && elem_s.contains(elem);
729            assert(s.to_iset().finite());
730            assert(ISet::new(flatten_f) =~= ISet::new(flatten_remove_f).union(s.to_iset()));
731        }
732    }
733
734    /// Since `Self::flatten` is `closed`, this broadcast lemma is
735    /// needed to make its semantics visible to the verifier.
736    pub broadcast proof fn lemma_flatten_contains(self, elem: A)
737        ensures
738            #[trigger] self.flatten().contains(elem) <==> (exists|elem_s: Set<A>| #[trigger]
739                self.contains(elem_s) && elem_s.contains(elem)),
740    {
741        self.lemma_flatten_finite();
742    }
743
744    /// Flattening then unioning with another set is equivalent to
745    /// inserting that other set and then flattening.
746    pub broadcast proof fn flatten_insert_union_commute(self, other: Set<A>)
747        ensures
748            self.flatten().union(other) =~= #[trigger] self.insert(other).flatten(),
749    {
750        broadcast use Set::lemma_flatten_contains;
751        broadcast use Set::lemma_map_contains;
752
753        let lhs = self.flatten().union(other);
754        let rhs = self.insert(other).flatten();
755
756        assert forall|elem: A| lhs.contains(elem) implies rhs.contains(elem) by {
757            if self.flatten().contains(elem) {
758                self.lemma_flatten_contains(elem);
759                let s = choose|s: Set<A>| #[trigger] self.contains(s) && s.contains(elem);
760                assert(self.insert(other).contains(s));
761                assert(s.contains(elem));
762            } else {
763                assert(other.contains(elem));
764                assert(self.insert(other).contains(other));
765            }
766            self.insert(other).lemma_flatten_contains(elem);
767        }
768    }
769}
770
771pub trait FiniteRange: Sized {
772    spec fn in_range(i: Self, lo: Self, hi: Self) -> bool;
773
774    spec fn range_set(lo: Self, hi: Self) -> Set<Self>;
775
776    spec fn range_len(lo: Self, hi: Self) -> nat;
777
778    proof fn range_properties(lo: Self, hi: Self)
779        ensures
780            forall|i: Self| #[trigger]
781                Self::range_set(lo, hi).contains(i) <==> Self::in_range(i, lo, hi),
782            Self::range_set(lo, hi).len() == Self::range_len(lo, hi),
783    ;
784}
785
786/// This public broadcast lemma shows that when `A` has trait
787/// `FiniteRange`, `A::range_set(lo, hi)` has the expected properties.
788/// That is, it contains all values `a: A` such that `lo <= a < hi`,
789/// and its length is `hi - lo`.
790pub broadcast proof fn range_set_properties<A: FiniteRange>(lo: A, hi: A)
791    ensures
792        forall|i: A| #[trigger] A::range_set(lo, hi).contains(i) <==> A::in_range(i, lo, hi),
793        (#[trigger] A::range_set(lo, hi)).len() == A::range_len(lo, hi),
794{
795    A::range_properties(lo, hi);
796}
797
798pub trait FiniteFull: Sized {
799    proof fn full_properties()
800        ensures
801            Set::<Self>::full() is Some,
802    ;
803}
804
805/// This public broadcast lemma shows that when `A` has trait
806/// `FiniteRange`, `A::full()` has the expected propery of containing
807/// all values of type `A`.
808pub broadcast proof fn full_set_properties<A: FiniteFull>()
809    ensures
810        #![trigger Set::<A>::full()]
811        Set::<A>::full() is Some,
812{
813    A::full_properties();
814}
815
816impl<A: FiniteRange> Set<A> {
817    #[verifier::inline]
818    pub open spec fn range(lo: A, hi: A) -> Set<A> {
819        A::range_set(lo, hi)
820    }
821
822    #[verifier::inline]
823    pub open spec fn range_inclusive(lo: A, hi: A) -> Set<A> {
824        A::range_set(lo, hi).insert(hi)
825    }
826}
827
828impl<A: FiniteFull> Set<A> {
829    #[verifier::inline]
830    pub open spec fn from_finite_type(f: spec_fn(A) -> bool) -> Set<A> {
831        Set::<A>::full().unwrap().filter(f)
832    }
833}
834
835// Macro to implement the trait for every numeric type. We need a macro here
836// because 'as nat' can't be written as a type generic.
837macro_rules! range_impls {
838    ([$($t:ty)*]) => {
839        $(
840            verus! {
841                impl FiniteRange for $t {
842                    open spec fn in_range(i: Self, lo: Self, hi: Self) -> bool {
843                        lo <= i < hi
844                    }
845                    open spec fn range_set(lo: Self, hi: Self) -> Set<Self> {
846                        Set::new(|i: Self| Self::in_range(i, lo, hi)).unwrap()
847                    }
848                    open spec fn range_len(lo: Self, hi: Self) -> nat {
849                        if lo <= hi { (hi - lo) as nat } else { 0 }
850                    }
851                    proof fn range_properties(lo: Self, hi: Self)
852                        decreases hi - lo
853                    {
854                        proof fn range_properties_helper(lo: $t, hi: $t)
855                            ensures
856                                ISet::<$t>::new(|i: $t| $t::in_range(i, lo, hi)).finite(),
857                            decreases
858                                hi - lo,
859                        {
860                            if lo >= hi {
861                                assert(ISet::<$t>::new(|i: $t| $t::in_range(i, lo, hi)) =~= ISet::<$t>::empty());
862                            }
863                            else {
864                                let hi_minus_1: $t = (hi - 1) as $t;
865                                assert(hi_minus_1 == hi - 1);
866                                range_properties_helper(lo, hi_minus_1);
867                                assert(ISet::<$t>::new(|i: $t| $t::in_range(i, lo, hi)) =~=
868                                       ISet::<$t>::new(|i: $t| $t::in_range(i, lo, hi_minus_1)).insert(hi_minus_1));
869                            }
870                        }
871
872                        range_properties_helper(lo, hi);
873                        if hi <= lo {
874                            assert(Self::range_set(lo, hi) =~= Set::<Self>::empty());
875                        } else {
876                            let hi1 = (hi - 1) as $t;
877                            Self::range_properties(lo, hi1);
878                            assert(ISet::new(|i: Self| Self::in_range(i, lo, hi)) =~=
879                                   ISet::new(|i: Self| Self::in_range(i, lo, hi1)).insert(hi1));
880                            assert(Self::range_set(lo, hi) == Self::range_set(lo, hi1).insert(hi1));
881                        }
882                    }
883                }
884            } // verus!
885        )*
886    }
887}
888
889macro_rules! full_impls {
890    ([$($t:ty)*]) => {
891        $(
892            verus! {
893                impl FiniteFull for $t {
894                    proof fn full_properties() {
895                        proof fn full_properties_helper(lo: $t, hi: $t)
896                            requires
897                                lo <= hi,
898                            ensures
899                                ISet::<$t>::new(|a: $t| lo <= a && a <= hi).finite(),
900                            decreases
901                                hi - lo,
902                        {
903                            if lo == hi {
904                                assert(ISet::<$t>::new(|a: $t| lo <= a && a <= hi) =~= iset![lo]);
905                            }
906                            else {
907                                let hi_minus_1: $t = (hi - 1) as $t;
908                                assert(hi_minus_1 == hi - 1);
909                                full_properties_helper(lo, hi_minus_1);
910                                assert(ISet::<$t>::new(|a: $t| lo <= a && a <= hi) =~=
911                                       ISet::<$t>::new(|a: $t| lo <= a && a <= hi_minus_1).insert(hi));
912                            }
913                        }
914
915                        full_properties_helper($t::MIN, $t::MAX);
916                        assert(ISet::<$t>::new(|a: $t| true) =~=
917                               ISet::<$t>::new(|a: $t| $t::MIN <= a && a <= $t::MAX));
918                        assert(Set::<$t>::full() is Some);
919                        Self::range_properties($t::MIN, $t::MAX);
920                        assert(Set::<$t>::full().unwrap() == Set::range_inclusive($t::MIN, $t::MAX));
921                    }
922                }
923            } // verus!
924        )*
925    }
926}
927
928// Make Set::range available for all of the Verus numeric types
929range_impls!([
930    int nat
931    usize u8 u16 u32 u64 u128
932    isize i8 i16 i32 i64 i128
933]);
934
935// Make Set::full available for all of the Verus numeric types
936full_impls!([
937    usize u8 u16 u32 u64 u128
938    isize i8 i16 i32 i64 i128
939]);
940
941/// Two sets are equal iff mapping `f` results in equal sets, if `f` is injective.
942pub proof fn lemma_sets_eq_iff_injective_map_eq<T, S>(s1: Set<T>, s2: Set<T>, f: spec_fn(T) -> S)
943    requires
944        super::relations::injective(f),
945    ensures
946        (s1 == s2) <==> (s1.map(f) == s2.map(f)),
947{
948    broadcast use group_set_lemmas;
949    broadcast use Set::lemma_map_contains;
950
951    if (s1.map(f) == s2.map(f)) {
952        assert(s1.map(f).len() == s2.map(f).len());
953        if !s1.subset_of(s2) {
954            let x = choose|x: T| s1.contains(x) && !s2.contains(x);
955            assert(s1.map(f).contains(f(x)));
956        } else if !s2.subset_of(s1) {
957            let x = choose|x: T| s2.contains(x) && !s1.contains(x);
958            assert(s2.map(f).contains(f(x)));
959        }
960        assert(s1 =~= s2);
961    }
962}
963
964/// Two sets are equal iff applying an injective (in the union of the sets) function `f` to each set produces equal sets.
965pub proof fn lemma_sets_eq_iff_injective_map_on_eq<T, S>(s1: Set<T>, s2: Set<T>, f: spec_fn(T) -> S)
966    requires
967        (s1 + s2).injective_on(f),
968    ensures
969        (s1 == s2) <==> (s1.map(f) == s2.map(f)),
970{
971    broadcast use group_set_lemmas;
972    broadcast use Set::lemma_map_contains;
973
974    if (s1.map(f) == s2.map(f)) {
975        assert(s1.map(f).len() == s2.map(f).len());
976        if !s1.subset_of(s2) {
977            let x = choose|x: T| s1.contains(x) && !s2.contains(x);
978            assert(s1.map(f).contains(f(x)));
979        } else if !s2.subset_of(s1) {
980            let x = choose|x: T| s2.contains(x) && !s1.contains(x);
981            assert(s2.map(f).contains(f(x)));
982        }
983        assert(s1 =~= s2);
984    }
985}
986
987/// The size of a union of two sets is less than or equal to the size of
988/// both individual sets combined.
989pub proof fn lemma_len_union<A>(s1: Set<A>, s2: Set<A>)
990    ensures
991        s1.union(s2).len() <= s1.len() + s2.len(),
992    decreases s1.len(),
993{
994    if s1.is_empty() {
995        assert(s1.union(s2) =~= s2);
996    } else {
997        let a = s1.choose();
998        if s2.contains(a) {
999            assert(s1.union(s2) =~= s1.remove(a).union(s2));
1000        } else {
1001            assert(s1.union(s2).remove(a) =~= s1.remove(a).union(s2));
1002        }
1003        lemma_len_union::<A>(s1.remove(a), s2);
1004    }
1005}
1006
1007/// The size of a union of two sets is greater than or equal to the size of
1008/// both individual sets.
1009pub proof fn lemma_len_union_ind<A>(s1: Set<A>, s2: Set<A>)
1010    ensures
1011        s1.union(s2).len() >= s1.len(),
1012        s1.union(s2).len() >= s2.len(),
1013    decreases s2.len(),
1014{
1015    broadcast use group_set_properties;
1016
1017    if s2.len() == 0 {
1018    } else {
1019        let y = choose|y: A| s2.contains(y);
1020        if s1.contains(y) {
1021            assert(s1.remove(y).union(s2.remove(y)) =~= s1.union(s2).remove(y));
1022            lemma_len_union_ind(s1.remove(y), s2.remove(y))
1023        } else {
1024            assert(s1.union(s2.remove(y)) =~= s1.union(s2).remove(y));
1025            lemma_len_union_ind(s1, s2.remove(y))
1026        }
1027    }
1028}
1029
1030/// The size of the intersection of finite set `s1` and set `s2` is less than or equal to the size of `s1`.
1031pub proof fn lemma_len_intersect<A>(s1: Set<A>, s2: Set<A>)
1032    ensures
1033        s1.intersect(s2).len() <= s1.len(),
1034    decreases s1.len(),
1035{
1036    if s1.is_empty() {
1037        assert(s1.intersect(s2) =~= s1);
1038    } else {
1039        let a = s1.choose();
1040        assert(s1.intersect(s2).remove(a) =~= s1.remove(a).intersect(s2));
1041        lemma_len_intersect::<A>(s1.remove(a), s2);
1042    }
1043}
1044
1045/// If `s1` is a subset of finite set `s2`, then the size of `s1` is less than or equal to
1046/// the size of `s2` and `s1` must be finite.
1047pub proof fn lemma_len_subset<A>(s1: Set<A>, s2: Set<A>)
1048    requires
1049        s1.subset_of(s2),
1050    ensures
1051        s1.len() <= s2.len(),
1052{
1053    lemma_len_intersect::<A>(s2, s1);
1054    assert(s2.intersect(s1) =~= s1);
1055}
1056
1057/// The size of the difference of finite set `s1` and set `s2` is less than or equal to the size of `s1`.
1058pub proof fn lemma_len_difference<A>(s1: Set<A>, s2: Set<A>)
1059    ensures
1060        s1.difference(s2).len() <= s1.len(),
1061    decreases s1.len(),
1062{
1063    if s1.is_empty() {
1064        assert(s1.difference(s2) =~= s1);
1065    } else {
1066        let a = s1.choose();
1067        assert(s1.difference(s2).remove(a) =~= s1.remove(a).difference(s2));
1068        lemma_len_difference::<A>(s1.remove(a), s2);
1069    }
1070}
1071
1072/// Creates a finite set of integers in the range [lo, hi).
1073pub open spec fn set_int_range(lo: int, hi: int) -> Set<int> {
1074    Set::<int>::range(lo, hi)
1075}
1076
1077/// If a set solely contains integers in the range [a, b), then its size is
1078/// bounded by b - a.
1079pub proof fn lemma_int_range(lo: int, hi: int)
1080    requires
1081        lo <= hi,
1082    ensures
1083        forall|j: int| set_int_range(lo, hi).contains(j) <==> lo <= j < hi,
1084        set_int_range(lo, hi).len() == hi - lo,
1085    decreases hi - lo,
1086{
1087    broadcast use range_set_properties;
1088
1089}
1090
1091/// If x is a subset of y and the size of x is equal to the size of y, x is equal to y.
1092pub proof fn lemma_subset_equality<A>(x: Set<A>, y: Set<A>)
1093    requires
1094        x.subset_of(y),
1095        x.len() == y.len(),
1096    ensures
1097        x =~= y,
1098    decreases x.len(),
1099{
1100    broadcast use group_set_properties;
1101
1102    if x =~= Set::<A>::empty() {
1103    } else {
1104        let e = x.choose();
1105        lemma_subset_equality(x.remove(e), y.remove(e));
1106    }
1107}
1108
1109/// If an injective function is applied to each element of a set to construct
1110/// another set, the two sets have the same size.
1111pub proof fn lemma_map_size<A, B>(x: Set<A>, y: Set<B>, f: spec_fn(A) -> B)
1112    requires
1113        x.injective_on(f),
1114        x.map(f) == y,
1115    ensures
1116        x.len() == y.len(),
1117    decreases x.len(),
1118{
1119    broadcast use group_set_properties;
1120    broadcast use Set::lemma_map_contains;
1121
1122    if x.len() == 0 {
1123        if !y.is_empty() {
1124            let e = y.choose();
1125        }
1126    } else {
1127        let a = x.choose();
1128        assert(x.remove(a).map(f) == y.remove(f(a)));
1129        lemma_map_size(x.remove(a), y.remove(f(a)), f);
1130        assert(y == y.remove(f(a)).insert(f(a)));
1131    }
1132}
1133
1134/// If any function is applied to each element of a set to construct
1135/// another set, the constructed set's length is at most the original's
1136pub proof fn lemma_map_size_bound<A, B>(x: Set<A>, y: Set<B>, f: spec_fn(A) -> B)
1137    requires
1138        x.map(f) == y,
1139    ensures
1140        y.len() <= x.len(),
1141    decreases x.len(),
1142{
1143    broadcast use group_set_properties;
1144    broadcast use Set::lemma_map_contains;
1145
1146    if x.is_empty() {
1147        if !y.is_empty() {
1148            let e = y.choose();
1149        }
1150    } else {
1151        let xx = x.choose();
1152        let img = f(xx);
1153        let pre = x.filter(|a: A| f(a) == f(xx));
1154        x.lemma_len_filter(|a: A| f(a) == f(xx));
1155        let wit = choose|a: A| x.contains(a) && f(a) == f(xx);
1156        assert forall|b: B| (#[trigger] y.remove(f(xx)).contains(b)) implies exists|a: A|
1157            x.difference(pre).contains(a) && f(a) == b by {
1158            let pre_wit = choose|a: A| x.contains(a) && f(a) == b;
1159            assert(x.difference(pre).contains(pre_wit));
1160        }
1161
1162        assert(x == x.difference(pre).union(pre));
1163        assert(y == y.remove(f(xx)).insert(f(xx)));
1164        assert(x.difference(pre).map(f) == y.remove(f(xx)));
1165        lemma_map_size_bound(x.difference(pre), y.remove(f(xx)), f);
1166    }
1167}
1168
1169// This verified lemma used to be an axiom in the Dafny prelude
1170/// Taking the union of sets `a` and `b` and then taking the union of the result with `b`
1171/// is the same as taking the union of `a` and `b` once.
1172pub broadcast proof fn lemma_set_union_again1<A>(a: Set<A>, b: Set<A>)
1173    ensures
1174        #[trigger] a.union(b).union(b) =~= a.union(b),
1175{
1176}
1177
1178// This verified lemma used to be an axiom in the Dafny prelude
1179/// Taking the union of sets `a` and `b` and then taking the union of the result with `a`
1180/// is the same as taking the union of `a` and `b` once.
1181pub broadcast proof fn lemma_set_union_again2<A>(a: Set<A>, b: Set<A>)
1182    ensures
1183        #[trigger] a.union(b).union(a) =~= a.union(b),
1184{
1185}
1186
1187// This verified lemma used to be an axiom in the Dafny prelude
1188/// Taking the intersection of sets `a` and `b` and then taking the intersection of the result with `b`
1189/// is the same as taking the intersection of `a` and `b` once.
1190pub broadcast proof fn lemma_set_intersect_again1<A>(a: Set<A>, b: Set<A>)
1191    ensures
1192        #![trigger (a.intersect(b)).intersect(b)]
1193        (a.intersect(b)).intersect(b) =~= a.intersect(b),
1194{
1195}
1196
1197// This verified lemma used to be an axiom in the Dafny prelude
1198/// Taking the intersection of sets `a` and `b` and then taking the intersection of the result with `a`
1199/// is the same as taking the intersection of `a` and `b` once.
1200pub broadcast proof fn lemma_set_intersect_again2<A>(a: Set<A>, b: Set<A>)
1201    ensures
1202        #![trigger (a.intersect(b)).intersect(a)]
1203        (a.intersect(b)).intersect(a) =~= a.intersect(b),
1204{
1205}
1206
1207// This verified lemma used to be an axiom in the Dafny prelude
1208/// If set `s2` contains element `a`, then the set difference of `s1` and `s2` does not contain `a`.
1209pub broadcast proof fn lemma_set_difference2<A>(s1: Set<A>, s2: Set<A>, a: A)
1210    ensures
1211        #![trigger s1.difference(s2).contains(a)]
1212        s2.contains(a) ==> !s1.difference(s2).contains(a),
1213{
1214}
1215
1216// This verified lemma used to be an axiom in the Dafny prelude
1217/// If sets `a` and `b` are disjoint, meaning they have no elements in common, then the set difference
1218/// of `a + b` and `b` is equal to `a` and the set difference of `a + b` and `a` is equal to `b`.
1219pub broadcast proof fn lemma_set_disjoint<A>(a: Set<A>, b: Set<A>)
1220    ensures
1221        #![trigger (a + b).difference(a)]  //TODO: this might be too free
1222        a.disjoint(b) ==> ((a + b).difference(a) =~= b && (a + b).difference(b) =~= a),
1223{
1224}
1225
1226// This verified lemma used to be an axiom in the Dafny prelude
1227// Dafny encodes the second clause with a single directional, although
1228// it should be fine with both directions?
1229// REVIEW: excluded from broadcast group if trigger is too free
1230//         also not that some proofs in seq_lib requires this lemma
1231/// Set `s` has length 0 if and only if it is equal to the empty set. If `s` has length greater than 0,
1232/// Then there must exist an element `x` such that `s` contains `x`.
1233pub broadcast proof fn lemma_set_empty_equivalency_len<A>(s: Set<A>)
1234    ensures
1235        #![trigger s.len()]
1236        (s.len() == 0 <==> s == Set::<A>::empty()) && (s.len() != 0 ==> exists|x: A| s.contains(x)),
1237{
1238    assert(s.len() == 0 ==> s =~= Set::empty()) by {
1239        if s.len() == 0 {
1240            assert(forall|a: A| !(Set::empty().contains(a)));
1241            assert(Set::<A>::empty().len() == 0);
1242            assert(Set::<A>::empty().len() == s.len());
1243            assert((exists|a: A| s.contains(a)) || (forall|a: A| !s.contains(a)));
1244            if exists|a: A| s.contains(a) {
1245                let a = s.choose();
1246                assert(s.remove(a).len() == s.len() - 1) by {
1247                    lemma_set_remove_len(s, a);
1248                }
1249            }
1250        }
1251    }
1252    assert(s.len() == 0 <== s =~= Set::empty());
1253}
1254
1255// This verified lemma used to be an axiom in the Dafny prelude
1256/// If sets `a` and `b` are disjoint, meaning they share no elements in common, then the length
1257/// of the union `a + b` is equal to the sum of the lengths of `a` and `b`.
1258pub broadcast proof fn lemma_set_disjoint_lens<A>(a: Set<A>, b: Set<A>)
1259    ensures
1260        a.disjoint(b) ==> #[trigger] (a + b).len() == a.len() + b.len(),
1261    decreases a.len(),
1262{
1263    if a.len() == 0 {
1264        lemma_set_empty_equivalency_len(a);
1265        assert(a + b =~= b);
1266    } else {
1267        if a.disjoint(b) {
1268            let x = a.choose();
1269            assert(a.remove(x) + b =~= (a + b).remove(x));
1270            lemma_set_disjoint_lens(a.remove(x), b);
1271        }
1272    }
1273}
1274
1275/// Two sets are disjoint iff their intersection is empty
1276pub proof fn lemma_set_disjoint_iff_empty_intersection<T>(a: Set<T>, b: Set<T>)
1277    ensures
1278        a.disjoint(b) <==> a.intersect(b).is_empty(),
1279{
1280    broadcast use group_set_properties;
1281
1282    if a.disjoint(b) {
1283        assert(b.disjoint(a));
1284        assert(forall|x: T| a.contains(x) ==> !(a.contains(x) && b.contains(x)));
1285        assert(forall|x: T| b.contains(x) ==> !(a.contains(x) && b.contains(x)));
1286        assert(forall|x: T| !a.intersect(b).contains(x));
1287    }
1288    if a.intersect(b).is_empty() {
1289        assert(forall|x: T| !a.intersect(b).contains(x));
1290        if !a.disjoint(b) {
1291            assert(exists|x: T| a.contains(x) && b.contains(x));
1292            let x = choose|x: T| a.contains(x) && b.contains(x);
1293            assert(a.intersect(b).contains(x));
1294            assert(!a.intersect(b).is_empty());
1295        }
1296    }
1297}
1298
1299// This verified lemma used to be an axiom in the Dafny prelude
1300/// The length of the union between two sets added to the length of the intersection between the
1301/// two sets is equal to the sum of the lengths of the two sets.
1302pub broadcast proof fn lemma_set_intersect_union_lens<A>(a: Set<A>, b: Set<A>)
1303    ensures
1304        #[trigger] (a + b).len() + #[trigger] a.intersect(b).len() == a.len() + b.len(),
1305    decreases a.len(),
1306{
1307    if a.len() == 0 {
1308        lemma_set_empty_equivalency_len(a);
1309        assert(a + b =~= b);
1310        assert(a.intersect(b) =~= Set::empty());
1311        assert(a.intersect(b).len() == 0);
1312    } else {
1313        let x = a.choose();
1314        lemma_set_intersect_union_lens(a.remove(x), b);
1315        if (b.contains(x)) {
1316            assert(a.remove(x) + b =~= (a + b));
1317            assert(a.intersect(b).remove(x) =~= a.remove(x).intersect(b));
1318        } else {
1319            assert(a.remove(x) + b =~= (a + b).remove(x));
1320            assert(a.remove(x).intersect(b) =~= a.intersect(b));
1321        }
1322    }
1323}
1324
1325// This verified lemma used to be an axiom in the Dafny prelude
1326/// The length of the set difference `A \ B` added to the length of the set difference `B \ A` added to
1327/// the length of the intersection `A ∩ B` is equal to the length of the union `A + B`.
1328///
1329/// The length of the set difference `A \ B` is equal to the length of `A` minus the length of the
1330/// intersection `A ∩ B`.
1331pub broadcast proof fn lemma_set_difference_len<A>(a: Set<A>, b: Set<A>)
1332    ensures
1333        (#[trigger] a.difference(b).len() + b.difference(a).len() + a.intersect(b).len() == (a
1334            + b).len()) && (a.difference(b).len() == a.len() - a.intersect(b).len()),
1335    decreases a.len(),
1336{
1337    if a.len() == 0 {
1338        lemma_set_empty_equivalency_len(a);
1339        assert(a.difference(b) =~= Set::empty());
1340        assert(b.difference(a) =~= b);
1341        assert(a.intersect(b) =~= Set::empty());
1342        assert(a + b =~= b);
1343    } else {
1344        let x = a.choose();
1345        lemma_set_difference_len(a.remove(x), b);
1346        if b.contains(x) {
1347            assert(a.intersect(b).remove(x) =~= a.remove(x).intersect(b));
1348            assert(a.remove(x).difference(b) =~= a.difference(b));
1349            assert(b.difference(a.remove(x)).remove(x) =~= b.difference(a));
1350            assert(a.remove(x) + b =~= a + b);
1351        } else {
1352            assert(a.remove(x) + b =~= (a + b).remove(x));
1353            assert(a.remove(x).difference(b) =~= a.difference(b).remove(x));
1354            assert(b.difference(a.remove(x)) =~= b.difference(a));
1355            assert(a.remove(x).intersect(b) =~= a.intersect(b));
1356        }
1357    }
1358}
1359
1360pub broadcast group group_set_properties {
1361    lemma_set_union_again1,
1362    lemma_set_union_again2,
1363    lemma_set_intersect_again1,
1364    lemma_set_intersect_again2,
1365    lemma_set_difference2,
1366    lemma_set_disjoint,
1367    lemma_set_disjoint_lens,
1368    lemma_set_intersect_union_lens,
1369    lemma_set_difference_len,
1370    // REVIEW: exclude from broadcast group if trigger is too free
1371    //         also note that some proofs in seq_lib requires this lemma
1372    lemma_set_empty_equivalency_len,
1373}
1374
1375pub broadcast proof fn lemma_set_is_empty<A>(s: Set<A>)
1376    requires
1377        !(#[trigger] s.is_empty()),
1378    ensures
1379        exists|a: A| s.contains(a),
1380{
1381    super::iset_lib::axiom_iset_is_empty(s.to_iset());
1382}
1383
1384pub broadcast proof fn lemma_set_is_empty_len0<A>(s: Set<A>)
1385    ensures
1386        #[trigger] s.is_empty() <==> s.len() == 0,
1387{
1388}
1389
1390#[doc(hidden)]
1391#[verifier::inline]
1392pub open spec fn check_argument_is_set<A>(s: Set<A>) -> Set<A> {
1393    s
1394}
1395
1396/// Prove two sets equal by extensionality. Usage is:
1397///
1398/// ```rust
1399/// assert_sets_equal!(set1 == set2);
1400/// ```
1401///
1402/// or,
1403///
1404/// ```rust
1405/// assert_sets_equal!(set1 == set2, elem => {
1406///     // prove that set1.contains(elem) iff set2.contains(elem)
1407/// });
1408/// ```
1409#[macro_export]
1410macro_rules! assert_sets_equal {
1411    [$($tail:tt)*] => {
1412        $crate::vstd::prelude::verus_proof_macro_exprs!($crate::vstd::set_lib::assert_sets_equal_internal!($($tail)*))
1413    };
1414}
1415
1416#[macro_export]
1417#[doc(hidden)]
1418macro_rules! assert_sets_equal_internal {
1419    (::vstd::prelude::spec_eq($s1:expr, $s2:expr)) => {
1420        $crate::vstd::set_lib::assert_sets_equal_internal!($s1, $s2)
1421    };
1422    (::vstd::prelude::spec_eq($s1:expr, $s2:expr), $elem:ident $( : $t:ty )? => $bblock:block) => {
1423        $crate::vstd::set_lib::assert_sets_equal_internal!($s1, $s2, $elem $( : $t )? => $bblock)
1424    };
1425    (crate::prelude::spec_eq($s1:expr, $s2:expr)) => {
1426        $crate::vstd::set_lib::assert_sets_equal_internal!($s1, $s2)
1427    };
1428    (crate::prelude::spec_eq($s1:expr, $s2:expr), $elem:ident $( : $t:ty )? => $bblock:block) => {
1429        $crate::vstd::set_lib::assert_sets_equal_internal!($s1, $s2, $elem $( : $t )? => $bblock)
1430    };
1431    (crate::verus_builtin::spec_eq($s1:expr, $s2:expr)) => {
1432        $crate::vstd::set_lib::assert_sets_equal_internal!($s1, $s2)
1433    };
1434    (crate::verus_builtin::spec_eq($s1:expr, $s2:expr), $elem:ident $( : $t:ty )? => $bblock:block) => {
1435        $crate::vstd::set_lib::assert_sets_equal_internal!($s1, $s2, $elem $( : $t )? => $bblock)
1436    };
1437    ($s1:expr, $s2:expr $(,)?) => {
1438        $crate::vstd::set_lib::assert_sets_equal_internal!($s1, $s2, elem => { })
1439    };
1440    ($s1:expr, $s2:expr, $elem:ident $( : $t:ty )? => $bblock:block) => {
1441        #[verifier::spec] let s1 = $crate::vstd::set_lib::check_argument_is_set($s1);
1442        #[verifier::spec] let s2 = $crate::vstd::set_lib::check_argument_is_set($s2);
1443        $crate::vstd::prelude::assert_by($crate::vstd::prelude::equal(s1, s2), {
1444            $crate::vstd::prelude::assert_forall_by(|$elem $( : $t )?| {
1445                $crate::vstd::prelude::ensures(
1446                    $crate::vstd::prelude::imply(s1.contains($elem), s2.contains($elem))
1447                    &&
1448                    $crate::vstd::prelude::imply(s2.contains($elem), s1.contains($elem))
1449                );
1450                { $bblock }
1451            });
1452            $crate::vstd::prelude::assert_($crate::vstd::prelude::ext_equal(s1, s2));
1453        });
1454    }
1455}
1456
1457pub broadcast group group_set_lib_default {
1458    lemma_set_is_empty,
1459    lemma_set_is_empty_len0,
1460    Set::lemma_flatten_contains,
1461    Set::lemma_map_contains,
1462    Set::lemma_map_by_contains,
1463    Set::lemma_map_flatten_by_contains,
1464    range_set_properties,
1465    full_set_properties,
1466}
1467
1468pub use assert_sets_equal_internal;
1469pub use assert_sets_equal;
1470
1471} // verus!