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 pub open spec fn is_empty(self) -> (b: bool) {
22 self =~= Set::<A>::empty()
23 }
24
25 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 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 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 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 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 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 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 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 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 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 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 pub open spec fn injective_on<B>(self, r: spec_fn(A) -> B) -> bool {
189 self.to_iset().injective_on(r)
190 }
191
192 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 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 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 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 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 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 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 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 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 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 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 assert(self.remove(self.choose()).len() + 1 == 0);
294 }
295 assert(self =~= Set::empty());
296 }
297
298 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 pub open spec fn all(&self, pred: spec_fn(A) -> bool) -> bool {
497 forall|x: A| self.contains(x) ==> pred(x)
498 }
499
500 pub open spec fn any(&self, pred: spec_fn(A) -> bool) -> bool {
502 exists|x: A| self.contains(x) && pred(x)
503 }
504
505 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 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 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 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 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 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 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 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 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 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 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 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
786pub 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
805pub 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
835macro_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 } )*
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 } )*
925 }
926}
927
928range_impls!([
930 int nat
931 usize u8 u16 u32 u64 u128
932 isize i8 i16 i32 i64 i128
933]);
934
935full_impls!([
937 usize u8 u16 u32 u64 u128
938 isize i8 i16 i32 i64 i128
939]);
940
941pub 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
964pub 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
987pub 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
1007pub 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
1030pub 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
1045pub 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
1057pub 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
1072pub open spec fn set_int_range(lo: int, hi: int) -> Set<int> {
1074 Set::<int>::range(lo, hi)
1075}
1076
1077pub 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
1091pub 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
1109pub 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
1134pub 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
1169pub 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
1178pub 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
1187pub 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
1197pub 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
1207pub 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
1216pub broadcast proof fn lemma_set_disjoint<A>(a: Set<A>, b: Set<A>)
1220 ensures
1221 #![trigger (a + b).difference(a)] a.disjoint(b) ==> ((a + b).difference(a) =~= b && (a + b).difference(b) =~= a),
1223{
1224}
1225
1226pub 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
1255pub 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
1275pub 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
1299pub 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
1325pub 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 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#[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}