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;
18
19impl<A> ISet<A> {
20 pub open spec fn is_full(self) -> bool {
22 self == ISet::<A>::full()
23 }
24
25 pub open spec fn is_empty(self) -> (b: bool) {
27 self =~= ISet::<A>::empty()
28 }
29
30 pub open spec fn map<B>(self, f: spec_fn(A) -> B) -> ISet<B> {
32 ISet::new(|a: B| exists|x: A| self.contains(x) && a == f(x))
33 }
34
35 pub open spec fn map_by<B>(self, fwd: spec_fn(A) -> B, rev: spec_fn(B) -> A) -> ISet<B>
48 recommends
49 forall|a: A| self.contains(a) ==> rev(fwd(a)) == a,
50 {
51 ISet::new(|b: B| self.contains(rev(b)) && b == fwd(rev(b)))
52 }
53
54 pub open spec fn map_flatten_by<B>(
60 self,
61 fwd: spec_fn(A) -> ISet<B>,
62 rev: spec_fn(B) -> A,
63 ) -> ISet<B>
64 recommends
65 forall|a: A, b: B| #[trigger]
66 self.contains(a) && fwd(a).contains(b) ==> #[trigger] rev(b) == a,
67 {
68 ISet::new(|b: B| self.contains(rev(b)) && fwd(rev(b)).contains(b))
69 }
70
71 pub proof fn map_flatten_by_is_map_flatten<B>(
74 self,
75 fwd: spec_fn(A) -> ISet<B>,
76 rev: spec_fn(B) -> A,
77 )
78 requires
79 forall|a: A, b: B| #[trigger]
80 self.contains(a) && fwd(a).contains(b) ==> #[trigger] rev(b) == a,
81 ensures
82 self.map_flatten_by(fwd, rev) == self.map(fwd).flatten(),
83 {
84 assert forall|b: B| self.map_flatten_by(fwd, rev).contains(b) implies #[trigger] self.map(
85 fwd,
86 ).flatten().contains(b) by {
87 let bs = choose|bs: ISet<B>|
88 (exists|a: A| self.contains(a) && bs == fwd(a)) && bs.contains(b);
89 assert(self.map(fwd).contains(bs) <==> (exists|a: A| self.contains(a) && bs == fwd(a)));
90 }
91 }
92
93 pub open spec fn to_seq(self) -> Seq<A>
95 recommends
96 self.finite(),
97 decreases self.len(),
98 when self.finite()
99 {
100 if self.len() == 0 {
101 Seq::<A>::empty()
102 } else {
103 let x = self.choose();
104 Seq::<A>::empty().push(x) + self.remove(x).to_seq()
105 }
106 }
107
108 pub open spec fn to_sorted_seq(self, leq: spec_fn(A, A) -> bool) -> Seq<A> {
110 self.to_seq().sort_by(leq)
111 }
112
113 pub open spec fn is_singleton(self) -> bool {
115 &&& self.len() > 0
116 &&& (forall|x: A, y: A| self.contains(x) && self.contains(y) ==> x == y)
117 }
118
119 pub open spec fn injective_on<B>(self, r: spec_fn(A) -> B) -> bool {
123 forall|x1: A, x2: A|
124 self.contains(x1) && self.contains(x2) && #[trigger] r(x1) == #[trigger] r(x2) ==> x1
125 == x2
126 }
127
128 pub open spec fn has_least(self, leq: spec_fn(A, A) -> bool, min: A) -> bool {
131 self.contains(min) && forall|x: A| self.contains(x) ==> #[trigger] leq(min, x)
132 }
133
134 pub open spec fn has_minimum(self, leq: spec_fn(A, A) -> bool, min: A) -> bool {
136 self.contains(min) && forall|x: A|
137 self.contains(x) && #[trigger] leq(x, min) ==> #[trigger] leq(min, x)
138 }
139
140 pub open spec fn has_greatest(self, leq: spec_fn(A, A) -> bool, max: A) -> bool {
143 self.contains(max) && forall|x: A| self.contains(x) ==> #[trigger] leq(x, max)
144 }
145
146 pub open spec fn has_maximum(self, leq: spec_fn(A, A) -> bool, max: A) -> bool {
148 self.contains(max) && forall|x: A|
149 self.contains(x) && #[trigger] leq(max, x) ==> #[trigger] leq(x, max)
150 }
151
152 pub proof fn lemma_injective_on_subset<B>(self, r: spec_fn(A) -> B, other: Self)
154 requires
155 other <= self,
156 self.injective_on(r),
157 ensures
158 other.injective_on(r),
159 {
160 assert forall|a1: A, a2: A|
161 other.contains(a1) && other.contains(a2) && #[trigger] r(a1) == #[trigger] r(
162 a2,
163 ) implies a1 == a2 by {
164 assert(self.contains(a1));
165 assert(self.contains(a2));
166 assert(r(a1) == r(a2));
167 }
168 }
169
170 pub closed spec fn find_unique_minimal(self, r: spec_fn(A, A) -> bool) -> A
173 recommends
174 total_ordering(r),
175 self.len() > 0,
176 self.finite(),
177 decreases self.len(),
178 when self.finite()
179 {
180 proof {
181 broadcast use group_iset_properties;
182
183 }
184 if self.len() <= 1 {
185 self.choose()
186 } else {
187 let x = choose|x: A| self.contains(x);
188 let min = self.remove(x).find_unique_minimal(r);
189 if r(min, x) {
190 min
191 } else {
192 x
193 }
194 }
195 }
196
197 pub proof fn find_unique_minimal_ensures(self, r: spec_fn(A, A) -> bool)
199 requires
200 self.finite(),
201 self.len() > 0,
202 total_ordering(r),
203 ensures
204 self.has_minimum(r, self.find_unique_minimal(r)) && (forall|min: A|
205 self.has_minimum(r, min) ==> self.find_unique_minimal(r) == min),
206 decreases self.len(),
207 {
208 broadcast use group_iset_properties;
209
210 if self.len() == 1 {
211 let x = choose|x: A| self.contains(x);
212 assert(self.remove(x).insert(x) =~= self);
213 assert(self.has_minimum(r, self.find_unique_minimal(r)));
214 } else {
215 let x = choose|x: A| self.contains(x);
216 self.remove(x).find_unique_minimal_ensures(r);
217 assert(self.remove(x).has_minimum(r, self.remove(x).find_unique_minimal(r)));
218 let y = self.remove(x).find_unique_minimal(r);
219 let min_updated = self.find_unique_minimal(r);
220 assert(!r(y, x) ==> min_updated == x);
221 assert(forall|elt: A|
222 self.remove(x).contains(elt) && #[trigger] r(elt, y) ==> #[trigger] r(y, elt));
223 assert forall|elt: A|
224 self.contains(elt) && #[trigger] r(elt, min_updated) implies #[trigger] r(
225 min_updated,
226 elt,
227 ) by {
228 assert(r(min_updated, x) || r(min_updated, y));
229 if min_updated == y { assert(self.has_minimum(r, self.find_unique_minimal(r)));
231 } else { assert(self.remove(x).contains(elt) || elt == x);
233 assert(min_updated == x);
234 assert(r(x, y) || r(y, x));
235 assert(!r(x, y) || !r(y, x));
236 assert(!(min_updated == y) ==> !r(y, x));
237 assert(r(x, y));
238 if (self.remove(x).contains(elt)) {
239 assert(r(elt, y) && r(y, elt) ==> elt == y);
240 } else {
241 }
242 }
243 }
244 assert forall|min_poss: A|
245 self.has_minimum(r, min_poss) implies self.find_unique_minimal(r) == min_poss by {
246 assert(self.remove(x).has_minimum(r, min_poss) || x == min_poss);
247 if self.remove(x).has_minimum(r, min_poss) {
248 assert(r(x, min_poss) ==> r(min_poss, x));
249 assert(r(min_poss, self.find_unique_minimal(r)));
250 } else {
251 assert(x == min_poss);
252 assert(r(x, y));
253 }
254 }
255 }
256 }
257
258 pub closed spec fn find_unique_maximal(self, r: spec_fn(A, A) -> bool) -> A
261 recommends
262 total_ordering(r),
263 self.len() > 0,
264 decreases self.len(),
265 when self.finite()
266 {
267 proof {
268 broadcast use group_iset_properties;
269
270 }
271 if self.len() <= 1 {
272 self.choose()
273 } else {
274 let x = choose|x: A| self.contains(x);
275 let max = self.remove(x).find_unique_maximal(r);
276 if r(x, max) {
277 max
278 } else {
279 x
280 }
281 }
282 }
283
284 pub proof fn find_unique_maximal_ensures(self, r: spec_fn(A, A) -> bool)
286 requires
287 self.finite(),
288 self.len() > 0,
289 total_ordering(r),
290 ensures
291 self.has_maximum(r, self.find_unique_maximal(r)) && (forall|max: A|
292 self.has_maximum(r, max) ==> self.find_unique_maximal(r) == max),
293 decreases self.len(),
294 {
295 broadcast use group_iset_properties;
296
297 if self.len() == 1 {
298 let x = choose|x: A| self.contains(x);
299 assert(self.remove(x) =~= ISet::<A>::empty());
300 assert(self.contains(self.find_unique_maximal(r)));
301 } else {
302 let x = choose|x: A| self.contains(x);
303 self.remove(x).find_unique_maximal_ensures(r);
304 assert(self.remove(x).has_maximum(r, self.remove(x).find_unique_maximal(r)));
305 assert(self.remove(x).insert(x) =~= self);
306 let y = self.remove(x).find_unique_maximal(r);
307 let max_updated = self.find_unique_maximal(r);
308 assert(max_updated == x || max_updated == y);
309 assert(!r(x, y) ==> max_updated == x);
310 assert forall|elt: A|
311 self.contains(elt) && #[trigger] r(max_updated, elt) implies #[trigger] r(
312 elt,
313 max_updated,
314 ) by {
315 assert(r(x, max_updated) || r(y, max_updated));
316 if max_updated == y { assert(r(elt, max_updated));
318 assert(r(x, max_updated));
319 assert(self.has_maximum(r, self.find_unique_maximal(r)));
320 } else { assert(self.remove(x).contains(elt) || elt == x);
322 assert(max_updated == x);
323 assert(r(x, y) || r(y, x));
324 assert(!r(x, y) || !r(y, x));
325 assert(!(max_updated == y) ==> !r(x, y));
326 assert(r(y, x));
327 if (self.remove(x).contains(elt)) {
328 assert(r(y, elt) ==> r(elt, y));
329 assert(r(y, elt) && r(elt, y) ==> elt == y);
330 assert(r(elt, x));
331 assert(r(elt, max_updated))
332 } else {
333 }
334 }
335 }
336 assert forall|max_poss: A|
337 self.has_maximum(r, max_poss) implies self.find_unique_maximal(r) == max_poss by {
338 assert(self.remove(x).has_maximum(r, max_poss) || x == max_poss);
339 assert(r(max_poss, self.find_unique_maximal(r)));
340 assert(r(self.find_unique_maximal(r), max_poss));
341 }
342 }
343 }
344
345 pub open spec fn to_multiset(self) -> Multiset<A>
348 decreases self.len(),
349 when self.finite()
350 {
351 if self.len() == 0 {
352 Multiset::<A>::empty()
353 } else {
354 Multiset::<A>::empty().insert(self.choose()).add(
355 self.remove(self.choose()).to_multiset(),
356 )
357 }
358 }
359
360 pub proof fn lemma_len0_is_empty(self)
362 requires
363 self.finite(),
364 self.len() == 0,
365 ensures
366 self == ISet::<A>::empty(),
367 {
368 if exists|a: A| self.contains(a) {
369 assert(self.remove(self.choose()).len() + 1 == 0);
371 }
372 assert(self =~= ISet::empty());
373 }
374
375 pub proof fn lemma_singleton_size(self)
377 requires
378 self.is_singleton(),
379 ensures
380 self.len() == 1,
381 {
382 broadcast use group_iset_properties;
383
384 assert(self.remove(self.choose()) =~= ISet::empty());
385 }
386
387 pub proof fn lemma_is_singleton(s: ISet<A>)
389 requires
390 s.finite(),
391 ensures
392 s.is_singleton() == (s.len() == 1),
393 {
394 if s.is_singleton() {
395 s.lemma_singleton_size();
396 }
397 if s.len() == 1 {
398 assert forall|x: A, y: A| s.contains(x) && s.contains(y) implies x == y by {
399 let x = choose|x: A| s.contains(x);
400 broadcast use group_iset_properties;
401
402 assert(s.remove(x).len() == 0);
403 assert(s.insert(x) =~= s);
404 }
405 }
406 }
407
408 pub proof fn lemma_len_filter(self, f: spec_fn(A) -> bool)
410 requires
411 self.finite(),
412 ensures
413 self.filter(f).finite(),
414 self.filter(f).len() <= self.len(),
415 decreases self.len(),
416 {
417 lemma_len_intersect::<A>(self, ISet::new(f));
418 }
419
420 pub proof fn lemma_greatest_implies_maximal(self, r: spec_fn(A, A) -> bool, max: A)
422 requires
423 pre_ordering(r),
424 ensures
425 self.has_greatest(r, max) ==> self.has_maximum(r, max),
426 {
427 }
428
429 pub proof fn lemma_least_implies_minimal(self, r: spec_fn(A, A) -> bool, min: A)
431 requires
432 pre_ordering(r),
433 ensures
434 self.has_least(r, min) ==> self.has_minimum(r, min),
435 {
436 }
437
438 pub proof fn lemma_maximal_equivalent_greatest(self, r: spec_fn(A, A) -> bool, max: A)
440 requires
441 total_ordering(r),
442 ensures
443 self.has_greatest(r, max) <==> self.has_maximum(r, max),
444 {
445 assert(self.has_maximum(r, max) ==> forall|x: A|
446 !self.contains(x) || !r(max, x) || r(x, max));
447 }
448
449 pub proof fn lemma_minimal_equivalent_least(self, r: spec_fn(A, A) -> bool, min: A)
451 requires
452 total_ordering(r),
453 ensures
454 self.has_least(r, min) <==> self.has_minimum(r, min),
455 {
456 assert(self.has_minimum(r, min) ==> forall|x: A|
457 !self.contains(x) || !r(x, min) || r(min, x));
458 }
459
460 pub proof fn lemma_least_is_unique(self, r: spec_fn(A, A) -> bool)
462 requires
463 partial_ordering(r),
464 ensures
465 forall|min: A, min_prime: A|
466 self.has_least(r, min) && self.has_least(r, min_prime) ==> min == min_prime,
467 {
468 assert forall|min: A, min_prime: A|
469 self.has_least(r, min) && self.has_least(r, min_prime) implies min == min_prime by {
470 assert(r(min, min_prime));
471 assert(r(min_prime, min));
472 }
473 }
474
475 pub proof fn lemma_greatest_is_unique(self, r: spec_fn(A, A) -> bool)
477 requires
478 partial_ordering(r),
479 ensures
480 forall|max: A, max_prime: A|
481 self.has_greatest(r, max) && self.has_greatest(r, max_prime) ==> max == max_prime,
482 {
483 assert forall|max: A, max_prime: A|
484 self.has_greatest(r, max) && self.has_greatest(r, max_prime) implies max
485 == max_prime by {
486 assert(r(max_prime, max));
487 assert(r(max, max_prime));
488 }
489 }
490
491 pub proof fn lemma_minimal_is_unique(self, r: spec_fn(A, A) -> bool)
493 requires
494 total_ordering(r),
495 ensures
496 forall|min: A, min_prime: A|
497 self.has_minimum(r, min) && self.has_minimum(r, min_prime) ==> min == min_prime,
498 {
499 assert forall|min: A, min_prime: A|
500 self.has_minimum(r, min) && self.has_minimum(r, min_prime) implies min == min_prime by {
501 self.lemma_minimal_equivalent_least(r, min);
502 self.lemma_minimal_equivalent_least(r, min_prime);
503 self.lemma_least_is_unique(r);
504 }
505 }
506
507 pub proof fn lemma_maximal_is_unique(self, r: spec_fn(A, A) -> bool)
509 requires
510 self.finite(),
511 total_ordering(r),
512 ensures
513 forall|max: A, max_prime: A|
514 self.has_maximum(r, max) && self.has_maximum(r, max_prime) ==> max == max_prime,
515 {
516 assert forall|max: A, max_prime: A|
517 self.has_maximum(r, max) && self.has_maximum(r, max_prime) implies max == max_prime by {
518 self.lemma_maximal_equivalent_greatest(r, max);
519 self.lemma_maximal_equivalent_greatest(r, max_prime);
520 self.lemma_greatest_is_unique(r);
521 }
522 }
523
524 pub broadcast proof fn lemma_iset_insert_diff_decreases(self, s: ISet<A>, elt: A)
528 requires
529 self.contains(elt),
530 !s.contains(elt),
531 self.finite(),
532 ensures
533 #[trigger] self.difference(s.insert(elt)).len() < self.difference(s).len(),
534 {
535 self.difference(s.insert(elt)).lemma_subset_not_in_lt(self.difference(s), elt);
536 }
537
538 pub proof fn lemma_subset_not_in_lt(self: ISet<A>, s2: ISet<A>, elt: A)
540 requires
541 self.subset_of(s2),
542 s2.finite(),
543 !self.contains(elt),
544 s2.contains(elt),
545 ensures
546 self.len() < s2.len(),
547 {
548 let s2_no_elt = s2.remove(elt);
549 assert(self.len() <= s2_no_elt.len()) by {
550 lemma_len_subset(self, s2_no_elt);
551 }
552 }
553
554 pub broadcast proof fn lemma_iset_map_insert_commute<B>(self, elt: A, f: spec_fn(A) -> B)
556 ensures
557 #[trigger] self.insert(elt).map(f) =~= self.map(f).insert(f(elt)),
558 {
559 assert forall|x: B| self.map(f).insert(f(elt)).contains(x) implies self.insert(elt).map(
560 f,
561 ).contains(x) by {
562 if x == f(elt) {
563 assert(self.insert(elt).contains(elt));
564 } else {
565 let y = choose|y: A| self.contains(y) && f(y) == x;
566 assert(self.insert(elt).contains(y));
567 }
568 }
569 }
570
571 pub proof fn lemma_map_union_commute<B>(self, t: ISet<A>, f: spec_fn(A) -> B)
573 ensures
574 (self.union(t)).map(f) =~= self.map(f).union(t.map(f)),
575 {
576 broadcast use group_iset_lemmas;
577
578 let lhs = self.union(t).map(f);
579 let rhs = self.map(f).union(t.map(f));
580
581 assert forall|elem: B| rhs.contains(elem) implies lhs.contains(elem) by {
582 if self.map(f).contains(elem) {
583 let preimage = choose|preimage: A| self.contains(preimage) && f(preimage) == elem;
584 assert(self.union(t).contains(preimage));
585 } else {
586 assert(t.map(f).contains(elem));
587 let preimage = choose|preimage: A| t.contains(preimage) && f(preimage) == elem;
588 assert(self.union(t).contains(preimage));
589 }
590 }
591 }
592
593 pub open spec fn all(&self, pred: spec_fn(A) -> bool) -> bool {
595 forall|x: A| self.contains(x) ==> pred(x)
596 }
597
598 pub open spec fn any(&self, pred: spec_fn(A) -> bool) -> bool {
600 exists|x: A| self.contains(x) && pred(x)
601 }
602
603 pub broadcast proof fn lemma_any_map_preserved_pred<B>(
605 self,
606 p: spec_fn(A) -> bool,
607 q: spec_fn(B) -> bool,
608 f: spec_fn(A) -> B,
609 )
610 requires
611 #[trigger] self.any(p),
612 forall|x: A| #[trigger] p(x) ==> q(f(x)),
613 ensures
614 #[trigger] self.map(f).any(q),
615 {
616 let x = choose|x: A| self.contains(x) && p(x);
617 assert(self.map(f).contains(f(x)));
618 }
619
620 pub open spec fn filter_map<B>(self, f: spec_fn(A) -> Option<B>) -> ISet<B> {
622 self.map(
623 |elem: A|
624 match f(elem) {
625 Option::Some(r) => iset!{r},
626 Option::None => iset!{},
627 },
628 ).flatten()
629 }
630
631 pub broadcast proof fn lemma_filter_map_insert<B>(
633 s: ISet<A>,
634 f: spec_fn(A) -> Option<B>,
635 elem: A,
636 )
637 ensures
638 #[trigger] s.insert(elem).filter_map(f) == (match f(elem) {
639 Some(res) => s.filter_map(f).insert(res),
640 None => s.filter_map(f),
641 }),
642 {
643 broadcast use group_iset_lemmas;
644 broadcast use ISet::lemma_iset_map_insert_commute;
645
646 let lhs = s.insert(elem).filter_map(f);
647 let rhs = match f(elem) {
648 Some(res) => s.filter_map(f).insert(res),
649 None => s.filter_map(f),
650 };
651 let to_set = |elem: A|
652 match f(elem) {
653 Option::Some(r) => iset!{r},
654 Option::None => iset!{},
655 };
656 assert forall|r: B| #[trigger] lhs.contains(r) implies rhs.contains(r) by {
657 if f(elem) != Some(r) {
658 let orig = choose|orig: A| #[trigger]
659 s.contains(orig) && f(orig) == Option::Some(r);
660 assert(to_set(orig) == iset!{r});
661 assert(s.map(to_set).contains(to_set(orig)));
662 }
663 }
664 assert forall|r: B| #[trigger] rhs.contains(r) implies lhs.contains(r) by {
665 if Some(r) == f(elem) {
666 assert(s.insert(elem).map(to_set).contains(to_set(elem)));
667 } else {
668 let orig = choose|orig: A| #[trigger]
669 s.contains(orig) && f(orig) == Option::Some(r);
670 assert(s.insert(elem).map(to_set).contains(to_set(orig)));
671 }
672 }
673 assert(lhs =~= rhs);
674 }
675
676 pub broadcast proof fn lemma_filter_map_union<B>(self, f: spec_fn(A) -> Option<B>, t: ISet<A>)
678 ensures
679 #[trigger] self.union(t).filter_map(f) == self.filter_map(f).union(t.filter_map(f)),
680 {
681 broadcast use group_iset_lemmas;
682
683 let lhs = self.union(t).filter_map(f);
684 let rhs = self.filter_map(f).union(t.filter_map(f));
685 let to_set = |elem: A|
686 match f(elem) {
687 Option::Some(r) => iset!{r},
688 Option::None => iset!{},
689 };
690
691 assert forall|elem: B| rhs.contains(elem) implies lhs.contains(elem) by {
692 if self.filter_map(f).contains(elem) {
693 let x = choose|x: A| self.contains(x) && f(x) == Option::Some(elem);
694 assert(self.union(t).contains(x));
695 assert(self.union(t).map(to_set).contains(to_set(x)));
696 }
697 if t.filter_map(f).contains(elem) {
698 let x = choose|x: A| t.contains(x) && f(x) == Option::Some(elem);
699 assert(self.union(t).contains(x));
700 assert(self.union(t).map(to_set).contains(to_set(x)));
701 }
702 }
703 assert forall|elem: B| lhs.contains(elem) implies rhs.contains(elem) by {
704 let x = choose|x: A| self.union(t).contains(x) && f(x) == Option::Some(elem);
705 if self.contains(x) {
706 assert(self.map(to_set).contains(to_set(x)));
707 assert(self.filter_map(f).contains(elem));
708 } else {
709 assert(t.contains(x));
710 assert(t.map(to_set).contains(to_set(x)));
711 assert(t.filter_map(f).contains(elem));
712 }
713 }
714 assert(lhs =~= rhs);
715 }
716
717 pub proof fn lemma_map_finite<B>(self, f: spec_fn(A) -> B)
719 requires
720 self.finite(),
721 ensures
722 self.map(f).finite(),
723 self.map(f).len() <= self.len(),
724 decreases self.len(),
725 {
726 broadcast use group_iset_lemmas;
727 broadcast use lemma_iset_empty_equivalency_len;
728
729 if self.len() == 0 {
730 assert(forall|elem: A| !(#[trigger] self.contains(elem)));
731 assert forall|res: B| #[trigger] self.map(f).contains(res) implies false by {
732 let x = choose|x: A| self.contains(x) && f(x) == res;
733 }
734 assert(self.map(f) =~= ISet::<B>::empty());
735 } else {
736 let x = choose|x: A| self.contains(x);
737 assert(self.map(f).contains(f(x)));
738 self.remove(x).lemma_map_finite(f);
739 assert(self.remove(x).insert(x) == self);
740 assert(self.map(f) == self.remove(x).map(f).insert(f(x)));
741 }
742 }
743
744 pub broadcast proof fn lemma_map_by_finite<B>(self, fwd: spec_fn(A) -> B, rev: spec_fn(B) -> A)
746 requires
747 self.finite(),
748 ensures
749 #[trigger] self.map_by(fwd, rev).finite(),
750 {
751 broadcast use lemma_iset_subset_finite;
752
753 assert(self.map_by(fwd, rev).subset_of(self.map(fwd)));
754 self.lemma_map_finite(fwd);
755 }
756
757 pub broadcast proof fn lemma_map_flatten_by_finite<B>(
759 self,
760 fwd: spec_fn(A) -> ISet<B>,
761 rev: spec_fn(B) -> A,
762 )
763 requires
764 self.finite(),
765 forall|a: A| self.contains(a) ==> fwd(a).finite(),
766 ensures
767 #[trigger] self.map_flatten_by(fwd, rev).finite(),
768 {
769 broadcast use lemma_iset_subset_finite;
770
771 let s1 = self.map_flatten_by(fwd, rev);
772 let s2 = self.map(fwd).flatten();
773 assert forall|b: B| s1.contains(b) implies s2.contains(b) by {
774 assert(self.map(fwd).contains(fwd(rev(b))));
775 }
776 assert(s1.subset_of(s2));
777 self.lemma_map_finite(fwd);
778 self.map(fwd).lemma_flatten_finite();
779 }
780
781 pub broadcast proof fn lemma_iset_all_subset(self, s2: ISet<A>, p: spec_fn(A) -> bool)
785 requires
786 #[trigger] self.subset_of(s2),
787 s2.all(p),
788 ensures
789 #[trigger] self.all(p),
790 {
791 broadcast use group_iset_lemmas;
792
793 }
794
795 pub broadcast proof fn lemma_filter_map_finite<B>(self, f: spec_fn(A) -> Option<B>)
797 requires
798 self.finite(),
799 ensures
800 #[trigger] self.filter_map(f).finite(),
801 decreases self.len(),
802 {
803 broadcast use group_iset_lemmas;
804 broadcast use ISet::lemma_filter_map_insert;
805
806 let mapped = self.filter_map(f);
807 if self.len() == 0 {
808 assert(self.filter_map(f) =~= ISet::<B>::empty());
809 } else {
810 let elem = self.choose();
811 self.remove(elem).lemma_filter_map_finite(f);
812 assert(self =~= self.remove(elem).insert(elem));
813 }
814 }
815
816 pub broadcast proof fn lemma_to_seq_to_set_id(self)
818 requires
819 self.finite(),
820 ensures
821 #[trigger] self.to_seq().to_set().to_iset() =~= self,
822 decreases self.len(),
823 {
824 broadcast use group_set_lemmas;
825 broadcast use group_iset_lemmas;
826 broadcast use lemma_iset_empty_equivalency_len;
827 broadcast use super::seq_lib::group_seq_lib_default;
828 broadcast use super::seq_lib::group_seq_properties;
829
830 if self.len() == 0 {
831 assert(self.to_seq().to_set().to_iset() =~= ISet::<A>::empty());
832 } else {
833 let elem = self.choose();
834 self.remove(elem).lemma_to_seq_to_set_id();
835 assert(self =~= self.remove(elem).insert(elem));
836 assert(self.to_seq().to_set() =~= self.remove(elem).to_seq().to_set().insert(elem));
837 }
838 }
839
840 pub broadcast proof fn lemma_to_seq_no_duplicates(self)
842 requires
843 self.finite(),
844 ensures
845 #[trigger] self.to_seq().no_duplicates(),
846 decreases self.len(),
847 {
848 broadcast use super::seq::group_seq_axioms;
849
850 if self.len() == 0 {
851 } else {
852 let x = choose|x: A| #[trigger]
853 self.contains(x) && self.to_seq() =~= seq![x] + self.remove(x).to_seq();
854 let seq = self.to_seq();
855 let seq2 = self.remove(x).to_seq();
856 assert(seq2.no_duplicates()) by { self.remove(x).lemma_to_seq_no_duplicates() }
857 assert(seq2.to_set().to_iset() == self.remove(x)) by {
858 self.remove(x).lemma_to_seq_to_set_id();
859 }
860 assert(!seq2.contains(x)) by { seq2.to_set_ensures() }
861 }
862 }
863
864 pub broadcast proof fn lemma_to_seq_len(self)
866 requires
867 self.finite(),
868 ensures
869 #[trigger] self.to_seq().len() == self.len(),
870 decreases self.len(),
871 {
872 broadcast use super::seq::group_seq_axioms;
873
874 if self.len() == 0 {
875 } else {
876 let x = choose|x: A| #[trigger]
877 self.contains(x) && self.to_seq() =~= seq![x] + self.remove(x).to_seq();
878 self.remove(x).lemma_to_seq_len();
879 }
880 }
881}
882
883impl<A> ISet<ISet<A>> {
884 pub open spec fn flatten(self) -> ISet<A> {
887 ISet::new(
888 |elem|
889 exists|elem_s: ISet<A>| #[trigger] self.contains(elem_s) && elem_s.contains(elem),
890 )
891 }
892
893 pub broadcast proof fn flatten_insert_union_commute(self, other: ISet<A>)
896 ensures
897 self.flatten().union(other) =~= #[trigger] self.insert(other).flatten(),
898 {
899 broadcast use group_iset_lemmas;
900
901 let lhs = self.flatten().union(other);
902 let rhs = self.insert(other).flatten();
903
904 assert forall|elem: A| lhs.contains(elem) implies rhs.contains(elem) by {
905 if exists|s: ISet<A>| self.contains(s) && s.contains(elem) {
906 let s = choose|s: ISet<A>| self.contains(s) && s.contains(elem);
907 assert(self.insert(other).contains(s));
908 assert(s.contains(elem));
909 } else {
910 assert(self.insert(other).contains(other));
911 }
912 }
913 }
914
915 pub proof fn lemma_flatten_finite(self)
918 requires
919 self.finite(),
920 forall|s: ISet<A>| self.contains(s) ==> #[trigger] s.finite(),
921 ensures
922 self.flatten().finite(),
923 decreases self.len(),
924 {
925 broadcast use group_iset_lemmas;
926
927 if self.len() == 0 {
928 assert(self.flatten() =~= ISet::<A>::empty());
929 } else {
930 let s = self.choose();
931 let self2 = self.remove(s);
932 self2.lemma_flatten_finite();
933 self2.flatten_insert_union_commute(s);
934 }
935 }
936}
937
938pub proof fn lemma_isets_eq_iff_injective_map_eq<T, S>(s1: ISet<T>, s2: ISet<T>, f: spec_fn(T) -> S)
940 requires
941 super::relations::injective(f),
942 ensures
943 (s1 == s2) <==> (s1.map(f) == s2.map(f)),
944{
945 broadcast use group_iset_lemmas;
946
947 if (s1.map(f) == s2.map(f)) {
948 assert(s1.map(f).len() == s2.map(f).len());
949 if !s1.subset_of(s2) {
950 let x = choose|x: T| s1.contains(x) && !s2.contains(x);
951 assert(s1.map(f).contains(f(x)));
952 } else if !s2.subset_of(s1) {
953 let x = choose|x: T| s2.contains(x) && !s1.contains(x);
954 assert(s2.map(f).contains(f(x)));
955 }
956 assert(s1 =~= s2);
957 }
958}
959
960pub proof fn lemma_isets_eq_iff_injective_map_on_eq<T, S>(
962 s1: ISet<T>,
963 s2: ISet<T>,
964 f: spec_fn(T) -> S,
965)
966 requires
967 (s1 + s2).injective_on(f),
968 ensures
969 (s1 == s2) <==> (s1.map(f) == s2.map(f)),
970{
971 broadcast use group_iset_lemmas;
972
973 if (s1.map(f) == s2.map(f)) {
974 assert(s1.map(f).len() == s2.map(f).len());
975 if !s1.subset_of(s2) {
976 let x = choose|x: T| s1.contains(x) && !s2.contains(x);
977 assert(s1.map(f).contains(f(x)));
978 } else if !s2.subset_of(s1) {
979 let x = choose|x: T| s2.contains(x) && !s1.contains(x);
980 assert(s2.map(f).contains(f(x)));
981 }
982 assert(s1 =~= s2);
983 }
984}
985
986pub broadcast proof fn lemma_iset_insert_finite_iff<A>(s: ISet<A>, a: A)
988 ensures
989 #[trigger] s.insert(a).finite() <==> s.finite(),
990{
991 if s.insert(a).finite() {
992 if s.contains(a) {
993 assert(s == s.insert(a));
994 } else {
995 assert(s == s.insert(a).remove(a));
996 }
997 }
998 assert(s.insert(a).finite() ==> s.finite());
999}
1000
1001pub broadcast proof fn lemma_iset_remove_finite_iff<A>(s: ISet<A>, a: A)
1003 ensures
1004 #[trigger] s.remove(a).finite() <==> s.finite(),
1005{
1006 if s.remove(a).finite() {
1007 if s.contains(a) {
1008 assert(s == s.remove(a).insert(a));
1009 } else {
1010 assert(s == s.remove(a));
1011 }
1012 }
1013}
1014
1015pub broadcast proof fn lemma_iset_union_finite_iff<A>(s1: ISet<A>, s2: ISet<A>)
1017 ensures
1018 #[trigger] s1.union(s2).finite() <==> s1.finite() && s2.finite(),
1019{
1020 if s1.union(s2).finite() {
1021 lemma_iset_union_finite_implies_sets_finite(s1, s2);
1022 }
1023}
1024
1025pub proof fn lemma_iset_union_finite_implies_sets_finite<A>(s1: ISet<A>, s2: ISet<A>)
1028 requires
1029 s1.union(s2).finite(),
1030 ensures
1031 s1.finite(),
1032 s2.finite(),
1033 decreases s1.union(s2).len(),
1034{
1035 if s1.union(s2) =~= ISet::<A>::empty() {
1036 assert(s1 =~= ISet::<A>::empty());
1037 assert(s2 =~= ISet::<A>::empty());
1038 } else {
1039 let a = s1.union(s2).choose();
1040 assert(s1.remove(a).union(s2.remove(a)) == s1.union(s2).remove(a));
1041 lemma_iset_remove_len(s1.union(s2), a);
1042 lemma_iset_union_finite_implies_sets_finite(s1.remove(a), s2.remove(a));
1043 assert(forall|s: ISet<A>|
1044 #![auto]
1045 s.remove(a).insert(a) == if s.contains(a) {
1046 s
1047 } else {
1048 s.insert(a)
1049 });
1050 lemma_iset_insert_finite_iff(s1, a);
1051 lemma_iset_insert_finite_iff(s2, a);
1052 }
1053}
1054
1055pub proof fn lemma_len_union<A>(s1: ISet<A>, s2: ISet<A>)
1058 requires
1059 s1.finite(),
1060 s2.finite(),
1061 ensures
1062 s1.union(s2).len() <= s1.len() + s2.len(),
1063 decreases s1.len(),
1064{
1065 if s1.is_empty() {
1066 assert(s1.union(s2) =~= s2);
1067 } else {
1068 let a = s1.choose();
1069 if s2.contains(a) {
1070 assert(s1.union(s2) =~= s1.remove(a).union(s2));
1071 } else {
1072 assert(s1.union(s2).remove(a) =~= s1.remove(a).union(s2));
1073 }
1074 lemma_len_union::<A>(s1.remove(a), s2);
1075 }
1076}
1077
1078pub proof fn lemma_len_union_ind<A>(s1: ISet<A>, s2: ISet<A>)
1081 requires
1082 s1.finite(),
1083 s2.finite(),
1084 ensures
1085 s1.union(s2).len() >= s1.len(),
1086 s1.union(s2).len() >= s2.len(),
1087 decreases s2.len(),
1088{
1089 broadcast use group_iset_properties;
1090
1091 if s2.len() == 0 {
1092 } else {
1093 let y = choose|y: A| s2.contains(y);
1094 if s1.contains(y) {
1095 assert(s1.remove(y).union(s2.remove(y)) =~= s1.union(s2).remove(y));
1096 lemma_len_union_ind(s1.remove(y), s2.remove(y))
1097 } else {
1098 assert(s1.union(s2.remove(y)) =~= s1.union(s2).remove(y));
1099 lemma_len_union_ind(s1, s2.remove(y))
1100 }
1101 }
1102}
1103
1104pub proof fn lemma_len_intersect<A>(s1: ISet<A>, s2: ISet<A>)
1106 requires
1107 s1.finite(),
1108 ensures
1109 s1.intersect(s2).len() <= s1.len(),
1110 decreases s1.len(),
1111{
1112 if s1.is_empty() {
1113 assert(s1.intersect(s2) =~= s1);
1114 } else {
1115 let a = s1.choose();
1116 assert(s1.intersect(s2).remove(a) =~= s1.remove(a).intersect(s2));
1117 lemma_len_intersect::<A>(s1.remove(a), s2);
1118 }
1119}
1120
1121pub proof fn lemma_len_subset<A>(s1: ISet<A>, s2: ISet<A>)
1124 requires
1125 s2.finite(),
1126 s1.subset_of(s2),
1127 ensures
1128 s1.len() <= s2.len(),
1129 s1.finite(),
1130{
1131 lemma_len_intersect::<A>(s2, s1);
1132 assert(s2.intersect(s1) =~= s1);
1133}
1134
1135pub broadcast proof fn lemma_iset_subset_finite<A>(s: ISet<A>, sub: ISet<A>)
1137 requires
1138 s.finite(),
1139 sub.subset_of(s),
1140 ensures
1141 #![trigger sub.subset_of(s)]
1142 sub.finite(),
1143{
1144 let complement = s.difference(sub);
1145 assert(sub =~= s.difference(complement));
1146}
1147
1148pub proof fn lemma_len_difference<A>(s1: ISet<A>, s2: ISet<A>)
1150 requires
1151 s1.finite(),
1152 ensures
1153 s1.difference(s2).len() <= s1.len(),
1154 decreases s1.len(),
1155{
1156 if s1.is_empty() {
1157 assert(s1.difference(s2) =~= s1);
1158 } else {
1159 let a = s1.choose();
1160 assert(s1.difference(s2).remove(a) =~= s1.remove(a).difference(s2));
1161 lemma_len_difference::<A>(s1.remove(a), s2);
1162 }
1163}
1164
1165pub open spec fn set_int_range(lo: int, hi: int) -> ISet<int> {
1167 ISet::new(|i: int| lo <= i && i < hi)
1168}
1169
1170pub proof fn lemma_int_range(lo: int, hi: int)
1173 requires
1174 lo <= hi,
1175 ensures
1176 set_int_range(lo, hi).finite(),
1177 set_int_range(lo, hi).len() == hi - lo,
1178 decreases hi - lo,
1179{
1180 if lo == hi {
1181 assert(set_int_range(lo, hi) =~= ISet::empty());
1182 } else {
1183 lemma_int_range(lo, hi - 1);
1184 assert(set_int_range(lo, hi - 1).insert(hi - 1) =~= set_int_range(lo, hi));
1185 }
1186}
1187
1188pub proof fn lemma_subset_equality<A>(x: ISet<A>, y: ISet<A>)
1190 requires
1191 x.subset_of(y),
1192 x.finite(),
1193 y.finite(),
1194 x.len() == y.len(),
1195 ensures
1196 x =~= y,
1197 decreases x.len(),
1198{
1199 broadcast use group_iset_properties;
1200
1201 if x =~= ISet::<A>::empty() {
1202 } else {
1203 let e = x.choose();
1204 lemma_subset_equality(x.remove(e), y.remove(e));
1205 }
1206}
1207
1208pub proof fn lemma_map_size<A, B>(x: ISet<A>, y: ISet<B>, f: spec_fn(A) -> B)
1211 requires
1212 x.finite(),
1213 x.injective_on(f),
1214 x.map(f) == y,
1215 ensures
1216 y.finite(),
1217 x.len() == y.len(),
1218 decreases x.len(),
1219{
1220 broadcast use group_iset_properties;
1221
1222 if x.len() == 0 {
1223 if !y.is_empty() {
1224 let e = y.choose();
1225 }
1226 } else {
1227 let a = x.choose();
1228 assert(x.remove(a).map(f) == y.remove(f(a)));
1229 lemma_map_size(x.remove(a), y.remove(f(a)), f);
1230 assert(y == y.remove(f(a)).insert(f(a)));
1231 }
1232}
1233
1234pub proof fn lemma_map_size_bound<A, B>(x: ISet<A>, y: ISet<B>, f: spec_fn(A) -> B)
1237 requires
1238 x.finite(),
1239 x.map(f) == y,
1240 ensures
1241 y.finite(),
1242 y.len() <= x.len(),
1243 decreases x.len(),
1244{
1245 broadcast use group_iset_properties;
1246
1247 if x.is_empty() {
1248 if !y.is_empty() {
1249 let e = y.choose();
1250 }
1251 } else {
1252 let xx = x.choose();
1253 let img = f(xx);
1254 let pre = x.filter(|a: A| f(a) == f(xx));
1255 x.lemma_len_filter(|a: A| f(a) == f(xx));
1256 let wit = choose|a: A| x.contains(a) && f(a) == f(xx);
1257 assert forall|b: B| (#[trigger] y.remove(f(xx)).contains(b)) implies exists|a: A|
1258 x.difference(pre).contains(a) && f(a) == b by {
1259 let pre_wit = choose|a: A| x.contains(a) && f(a) == b;
1260 assert(x.difference(pre).contains(pre_wit));
1261 }
1262
1263 assert(x == x.difference(pre).union(pre));
1264 assert(y == y.remove(f(xx)).insert(f(xx)));
1265 assert(x.difference(pre).map(f) == y.remove(f(xx)));
1266 lemma_map_size_bound(x.difference(pre), y.remove(f(xx)), f);
1267 }
1268}
1269
1270pub broadcast proof fn lemma_iset_union_again1<A>(a: ISet<A>, b: ISet<A>)
1274 ensures
1275 #[trigger] a.union(b).union(b) =~= a.union(b),
1276{
1277}
1278
1279pub broadcast proof fn lemma_iset_union_again2<A>(a: ISet<A>, b: ISet<A>)
1283 ensures
1284 #[trigger] a.union(b).union(a) =~= a.union(b),
1285{
1286}
1287
1288pub broadcast proof fn lemma_iset_intersect_again1<A>(a: ISet<A>, b: ISet<A>)
1292 ensures
1293 #![trigger (a.intersect(b)).intersect(b)]
1294 (a.intersect(b)).intersect(b) =~= a.intersect(b),
1295{
1296}
1297
1298pub broadcast proof fn lemma_iset_intersect_again2<A>(a: ISet<A>, b: ISet<A>)
1302 ensures
1303 #![trigger (a.intersect(b)).intersect(a)]
1304 (a.intersect(b)).intersect(a) =~= a.intersect(b),
1305{
1306}
1307
1308pub broadcast proof fn lemma_iset_difference2<A>(s1: ISet<A>, s2: ISet<A>, a: A)
1311 ensures
1312 #![trigger s1.difference(s2).contains(a)]
1313 s2.contains(a) ==> !s1.difference(s2).contains(a),
1314{
1315}
1316
1317pub broadcast proof fn lemma_iset_disjoint<A>(a: ISet<A>, b: ISet<A>)
1321 ensures
1322 #![trigger (a + b).difference(a)] a.disjoint(b) ==> ((a + b).difference(a) =~= b && (a + b).difference(b) =~= a),
1324{
1325}
1326
1327pub broadcast proof fn lemma_iset_empty_equivalency_len<A>(s: ISet<A>)
1335 requires
1336 s.finite(),
1337 ensures
1338 #![trigger s.len()]
1339 (s.len() == 0 <==> s == ISet::<A>::empty()) && (s.len() != 0 ==> exists|x: A|
1340 s.contains(x)),
1341{
1342 assert(s.len() == 0 ==> s =~= ISet::empty()) by {
1343 if s.len() == 0 {
1344 assert(forall|a: A| !(ISet::empty().contains(a)));
1345 assert(ISet::<A>::empty().len() == 0);
1346 assert(ISet::<A>::empty().len() == s.len());
1347 assert((exists|a: A| s.contains(a)) || (forall|a: A| !s.contains(a)));
1348 if exists|a: A| s.contains(a) {
1349 let a = s.choose();
1350 assert(s.remove(a).len() == s.len() - 1) by {
1351 lemma_iset_remove_len(s, a);
1352 }
1353 }
1354 }
1355 }
1356 assert(s.len() == 0 <== s =~= ISet::empty());
1357}
1358
1359pub broadcast proof fn lemma_iset_disjoint_lens<A>(a: ISet<A>, b: ISet<A>)
1363 requires
1364 a.finite(),
1365 b.finite(),
1366 ensures
1367 a.disjoint(b) ==> #[trigger] (a + b).len() == a.len() + b.len(),
1368 decreases a.len(),
1369{
1370 if a.len() == 0 {
1371 lemma_iset_empty_equivalency_len(a);
1372 assert(a + b =~= b);
1373 } else {
1374 if a.disjoint(b) {
1375 let x = a.choose();
1376 assert(a.remove(x) + b =~= (a + b).remove(x));
1377 lemma_iset_disjoint_lens(a.remove(x), b);
1378 }
1379 }
1380}
1381
1382pub proof fn lemma_iset_disjoint_iff_empty_intersection<T>(a: ISet<T>, b: ISet<T>)
1384 ensures
1385 a.disjoint(b) <==> a.intersect(b).is_empty(),
1386{
1387 broadcast use group_iset_properties;
1388
1389 if a.disjoint(b) {
1390 assert(b.disjoint(a));
1391 assert(forall|x: T| a.contains(x) ==> !(a.contains(x) && b.contains(x)));
1392 assert(forall|x: T| b.contains(x) ==> !(a.contains(x) && b.contains(x)));
1393 assert(forall|x: T| !a.intersect(b).contains(x));
1394 }
1395 if a.intersect(b).is_empty() {
1396 assert(forall|x: T| !a.intersect(b).contains(x));
1397 if !a.disjoint(b) {
1398 assert(exists|x: T| a.contains(x) && b.contains(x));
1399 let x = choose|x: T| a.contains(x) && b.contains(x);
1400 assert(a.intersect(b).contains(x));
1401 assert(!a.intersect(b).is_empty());
1402 }
1403 }
1404}
1405
1406pub broadcast proof fn lemma_iset_intersect_union_lens<A>(a: ISet<A>, b: ISet<A>)
1410 requires
1411 a.finite(),
1412 b.finite(),
1413 ensures
1414 #[trigger] (a + b).len() + #[trigger] a.intersect(b).len() == a.len() + b.len(),
1415 decreases a.len(),
1416{
1417 if a.len() == 0 {
1418 lemma_iset_empty_equivalency_len(a);
1419 assert(a + b =~= b);
1420 assert(a.intersect(b) =~= ISet::empty());
1421 assert(a.intersect(b).len() == 0);
1422 } else {
1423 let x = a.choose();
1424 lemma_iset_intersect_union_lens(a.remove(x), b);
1425 if (b.contains(x)) {
1426 assert(a.remove(x) + b =~= (a + b));
1427 assert(a.intersect(b).remove(x) =~= a.remove(x).intersect(b));
1428 } else {
1429 assert(a.remove(x) + b =~= (a + b).remove(x));
1430 assert(a.remove(x).intersect(b) =~= a.intersect(b));
1431 }
1432 }
1433}
1434
1435pub broadcast proof fn lemma_iset_difference_len<A>(a: ISet<A>, b: ISet<A>)
1442 requires
1443 a.finite(),
1444 b.finite(),
1445 ensures
1446 (#[trigger] a.difference(b).len() + b.difference(a).len() + a.intersect(b).len() == (a
1447 + b).len()) && (a.difference(b).len() == a.len() - a.intersect(b).len()),
1448 decreases a.len(),
1449{
1450 if a.len() == 0 {
1451 lemma_iset_empty_equivalency_len(a);
1452 assert(a.difference(b) =~= ISet::empty());
1453 assert(b.difference(a) =~= b);
1454 assert(a.intersect(b) =~= ISet::empty());
1455 assert(a + b =~= b);
1456 } else {
1457 let x = a.choose();
1458 lemma_iset_difference_len(a.remove(x), b);
1459 if b.contains(x) {
1460 assert(a.intersect(b).remove(x) =~= a.remove(x).intersect(b));
1461 assert(a.remove(x).difference(b) =~= a.difference(b));
1462 assert(b.difference(a.remove(x)).remove(x) =~= b.difference(a));
1463 assert(a.remove(x) + b =~= a + b);
1464 } else {
1465 assert(a.remove(x) + b =~= (a + b).remove(x));
1466 assert(a.remove(x).difference(b) =~= a.difference(b).remove(x));
1467 assert(b.difference(a.remove(x)) =~= b.difference(a));
1468 assert(a.remove(x).intersect(b) =~= a.intersect(b));
1469 }
1470 }
1471}
1472
1473pub broadcast group group_iset_properties {
1474 lemma_iset_union_again1,
1475 lemma_iset_union_again2,
1476 lemma_iset_intersect_again1,
1477 lemma_iset_intersect_again2,
1478 lemma_iset_difference2,
1479 lemma_iset_disjoint,
1480 lemma_iset_disjoint_lens,
1481 lemma_iset_intersect_union_lens,
1482 lemma_iset_difference_len,
1483 lemma_iset_empty_equivalency_len,
1486}
1487
1488pub broadcast axiom fn axiom_iset_is_empty<A>(s: ISet<A>)
1489 requires
1490 !(#[trigger] s.is_empty()),
1491 ensures
1492 exists|a: A|
1493 s.contains(
1494 a,
1495 ),
1496;
1499
1500pub broadcast proof fn lemma_iset_is_empty_len0<A>(s: ISet<A>)
1501 ensures
1502 #[trigger] s.is_empty() <==> (s.finite() && s.len() == 0),
1503{
1504}
1505
1506#[doc(hidden)]
1507#[verifier::inline]
1508pub open spec fn check_argument_is_set<A>(s: ISet<A>) -> ISet<A> {
1509 s
1510}
1511
1512#[macro_export]
1526macro_rules! assert_isets_equal {
1527 [$($tail:tt)*] => {
1528 $crate::vstd::prelude::verus_proof_macro_exprs!($crate::vstd::iset_lib::assert_isets_equal_internal!($($tail)*))
1529 };
1530}
1531
1532#[macro_export]
1533#[doc(hidden)]
1534macro_rules! assert_isets_equal_internal {
1535 (::vstd::prelude::spec_eq($s1:expr, $s2:expr)) => {
1536 $crate::vstd::iset_lib::assert_isets_equal_internal!($s1, $s2)
1537 };
1538 (::vstd::prelude::spec_eq($s1:expr, $s2:expr), $elem:ident $( : $t:ty )? => $bblock:block) => {
1539 $crate::vstd::iset_lib::assert_isets_equal_internal!($s1, $s2, $elem $( : $t )? => $bblock)
1540 };
1541 (crate::prelude::spec_eq($s1:expr, $s2:expr)) => {
1542 $crate::vstd::iset_lib::assert_isets_equal_internal!($s1, $s2)
1543 };
1544 (crate::prelude::spec_eq($s1:expr, $s2:expr), $elem:ident $( : $t:ty )? => $bblock:block) => {
1545 $crate::vstd::iset_lib::assert_isets_equal_internal!($s1, $s2, $elem $( : $t )? => $bblock)
1546 };
1547 (crate::verus_builtin::spec_eq($s1:expr, $s2:expr)) => {
1548 $crate::vstd::iset_lib::assert_isets_equal_internal!($s1, $s2)
1549 };
1550 (crate::verus_builtin::spec_eq($s1:expr, $s2:expr), $elem:ident $( : $t:ty )? => $bblock:block) => {
1551 $crate::vstd::iset_lib::assert_isets_equal_internal!($s1, $s2, $elem $( : $t )? => $bblock)
1552 };
1553 ($s1:expr, $s2:expr $(,)?) => {
1554 $crate::vstd::iset_lib::assert_isets_equal_internal!($s1, $s2, elem => { })
1555 };
1556 ($s1:expr, $s2:expr, $elem:ident $( : $t:ty )? => $bblock:block) => {
1557 #[verifier::spec] let s1 = $crate::vstd::iset_lib::check_argument_is_set($s1);
1558 #[verifier::spec] let s2 = $crate::vstd::iset_lib::check_argument_is_set($s2);
1559 $crate::vstd::prelude::assert_by($crate::vstd::prelude::equal(s1, s2), {
1560 $crate::vstd::prelude::assert_forall_by(|$elem $( : $t )?| {
1561 $crate::vstd::prelude::ensures(
1562 $crate::vstd::prelude::imply(s1.contains($elem), s2.contains($elem))
1563 &&
1564 $crate::vstd::prelude::imply(s2.contains($elem), s1.contains($elem))
1565 );
1566 { $bblock }
1567 });
1568 $crate::vstd::prelude::assert_($crate::vstd::prelude::ext_equal(s1, s2));
1569 });
1570 }
1571}
1572
1573pub broadcast group group_iset_lib_default {
1574 axiom_iset_is_empty,
1575 lemma_iset_is_empty_len0,
1576 lemma_iset_subset_finite,
1577 ISet::lemma_map_by_finite,
1578 ISet::lemma_map_flatten_by_finite,
1579}
1580
1581pub use assert_isets_equal_internal;
1582pub use assert_isets_equal;
1583
1584}