1#[allow(unused_imports)]
2use super::map::*;
3#[allow(unused_imports)]
4use super::pervasive::*;
5#[allow(unused_imports)]
6use super::prelude::*;
7
8verus! {
9
10#[verifier::ext_equal]
30#[verifier::reject_recursive_types(A)]
31#[cfg_attr(verus_keep_ghost, rustc_diagnostic_item = "verus::vstd::iset::ISet")]
32pub struct ISet<A> {
33 set: spec_fn(A) -> bool,
34}
35
36impl<A> ISet<A> {
37 #[rustc_diagnostic_item = "verus::vstd::iset::ISet::empty"]
54 pub closed spec fn empty() -> ISet<A> {
55 ISet { set: |a| false }
56 }
57
58 pub closed spec fn new(f: spec_fn(A) -> bool) -> ISet<A> {
67 ISet { set: f }
68 }
69
70 #[rustc_diagnostic_item = "verus::vstd::iset::ISet::full"]
72 pub open spec fn full() -> ISet<A> {
73 ISet::empty().complement()
74 }
75
76 #[rustc_diagnostic_item = "verus::vstd::iset::ISet::contains"]
78 pub closed spec fn contains(self, a: A) -> bool {
79 (self.set)(a)
80 }
81
82 #[verifier::inline]
84 pub open spec fn spec_has(self, a: A) -> bool {
85 self.contains(a)
86 }
87
88 #[rustc_diagnostic_item = "verus::vstd::iset::ISet::subset_of"]
90 pub open spec fn subset_of(self, s2: ISet<A>) -> bool {
91 forall|a: A| self.contains(a) ==> s2.contains(a)
92 }
93
94 #[verifier::inline]
95 pub open spec fn spec_le(self, s2: ISet<A>) -> bool {
96 self.subset_of(s2)
97 }
98
99 #[rustc_diagnostic_item = "verus::vstd::iset::ISet::insert"]
102 pub closed spec fn insert(self, a: A) -> ISet<A> {
103 ISet {
104 set: |a2|
105 if a2 == a {
106 true
107 } else {
108 (self.set)(a2)
109 },
110 }
111 }
112
113 #[rustc_diagnostic_item = "verus::vstd::iset::ISet::remove"]
116 pub closed spec fn remove(self, a: A) -> ISet<A> {
117 ISet {
118 set: |a2|
119 if a2 == a {
120 false
121 } else {
122 (self.set)(a2)
123 },
124 }
125 }
126
127 pub closed spec fn union(self, s2: ISet<A>) -> ISet<A> {
129 ISet { set: |a| (self.set)(a) || (s2.set)(a) }
130 }
131
132 #[verifier::inline]
134 pub open spec fn spec_add(self, s2: ISet<A>) -> ISet<A> {
135 self.union(s2)
136 }
137
138 pub closed spec fn intersect(self, s2: ISet<A>) -> ISet<A> {
140 ISet { set: |a| (self.set)(a) && (s2.set)(a) }
141 }
142
143 #[verifier::inline]
145 pub open spec fn spec_mul(self, s2: ISet<A>) -> ISet<A> {
146 self.intersect(s2)
147 }
148
149 pub closed spec fn difference(self, s2: ISet<A>) -> ISet<A> {
151 ISet { set: |a| (self.set)(a) && !(s2.set)(a) }
152 }
153
154 #[verifier::inline]
156 pub open spec fn spec_sub(self, s2: ISet<A>) -> ISet<A> {
157 self.difference(s2)
158 }
159
160 pub closed spec fn complement(self) -> ISet<A> {
162 ISet { set: |a| !(self.set)(a) }
163 }
164
165 pub open spec fn filter(self, f: spec_fn(A) -> bool) -> ISet<A> {
167 self.intersect(Self::new(f))
168 }
169
170 pub closed spec fn finite(self) -> bool {
172 exists|f: spec_fn(A) -> nat, ub: nat|
173 {
174 &&& #[trigger] trigger_finite(f, ub)
175 &&& surj_on(f, self)
176 &&& forall|a| self.contains(a) ==> f(a) < ub
177 }
178 }
179
180 pub open spec fn to_set(self) -> Option<Set<A>>
181 recommends
182 self.finite(),
183 {
184 Set::<A>::new_from_iset(self)
185 }
186
187 pub closed spec fn len(self) -> nat {
189 self.fold(0, |acc: nat, a| acc + 1)
190 }
191
192 pub open spec fn choose(self) -> A {
199 choose|a: A| self.contains(a)
200 }
201
202 pub uninterp spec fn mk_map<V>(self, f: spec_fn(A) -> V) -> IMap<A, V>;
205
206 pub open spec fn disjoint(self, s2: Self) -> bool {
209 forall|a: A| self.contains(a) ==> !s2.contains(a)
210 }
211
212 pub open spec fn congruent(self, s2: Set<A>) -> bool {
215 forall|a: A| #![all_triggers] self.contains(a) <==> s2.contains(a)
216 }
217}
218
219spec fn trigger_finite<A>(f: spec_fn(A) -> nat, ub: nat) -> bool {
221 true
222}
223
224spec fn surj_on<A, B>(f: spec_fn(A) -> B, s: ISet<A>) -> bool {
225 forall|a1, a2| #![all_triggers] s.contains(a1) && s.contains(a2) && a1 != a2 ==> f(a1) != f(a2)
226}
227
228pub mod fold {
229 use super::*;
254
255 broadcast group group_iset_lemmas_early {
256 lemma_iset_empty,
257 lemma_iset_new,
258 lemma_iset_insert_same,
259 lemma_iset_insert_different,
260 lemma_iset_remove_same,
261 lemma_iset_remove_insert,
262 lemma_iset_remove_different,
263 lemma_iset_union,
264 lemma_iset_intersect,
265 lemma_iset_difference,
266 lemma_iset_complement,
267 lemma_iset_ext_equal,
268 lemma_iset_ext_equal_deep,
269 lemma_iset_empty_finite,
270 lemma_iset_insert_finite,
271 lemma_iset_remove_finite,
272 }
273
274 pub open spec fn is_fun_commutative<A, B>(f: spec_fn(B, A) -> B) -> bool {
275 forall|a1, a2, b| #[trigger] f(f(b, a2), a1) == f(f(b, a1), a2)
276 }
277
278 #[verifier(opaque)]
281 spec fn fold_graph<A, B>(z: B, f: spec_fn(B, A) -> B, s: ISet<A>, y: B, d: nat) -> bool
282 decreases d,
283 {
284 if s === ISet::empty() {
285 &&& z == y
286 &&& d == 0
287 } else {
288 exists|yr, a|
289 {
290 &&& #[trigger] trigger_fold_graph(yr, a)
291 &&& d > 0
292 &&& s.remove(a).finite()
293 &&& s.contains(a)
294 &&& fold_graph(z, f, s.remove(a), yr, sub(d, 1))
295 &&& y == f(yr, a)
296 }
297 }
298 }
299
300 spec fn trigger_fold_graph<A, B>(yr: B, a: A) -> bool {
301 true
302 }
303
304 proof fn lemma_fold_graph_empty_intro<A, B>(z: B, f: spec_fn(B, A) -> B)
306 ensures
307 fold_graph(z, f, ISet::empty(), z, 0),
308 {
309 reveal(fold_graph);
310 }
311
312 proof fn lemma_fold_graph_insert_intro<A, B>(
313 z: B,
314 f: spec_fn(B, A) -> B,
315 s: ISet<A>,
316 y: B,
317 d: nat,
318 a: A,
319 )
320 requires
321 fold_graph(z, f, s, y, d),
322 !s.contains(a),
323 ensures
324 fold_graph(z, f, s.insert(a), f(y, a), d + 1),
325 {
326 broadcast use group_iset_lemmas_early;
327
328 reveal(fold_graph);
329 let _ = trigger_fold_graph(y, a);
330 assert(s == s.insert(a).remove(a));
331 }
332
333 proof fn lemma_fold_graph_empty_elim<A, B>(z: B, f: spec_fn(B, A) -> B, y: B, d: nat)
335 requires
336 fold_graph(z, f, ISet::empty(), y, d),
337 ensures
338 z == y,
339 d == 0,
340 {
341 reveal(fold_graph);
342 }
343
344 proof fn lemma_fold_graph_insert_elim<A, B>(
345 z: B,
346 f: spec_fn(B, A) -> B,
347 s: ISet<A>,
348 y: B,
349 d: nat,
350 a: A,
351 )
352 requires
353 is_fun_commutative(f),
354 fold_graph(z, f, s.insert(a), y, d),
355 !s.contains(a),
356 ensures
357 d > 0,
358 exists|yp| y == f(yp, a) && #[trigger] fold_graph(z, f, s, yp, sub(d, 1)),
359 {
360 reveal(fold_graph);
361 lemma_fold_graph_insert_elim_aux(z, f, s.insert(a), y, d, a);
362 assert(s.insert(a).remove(a) =~= s);
363 let yp = choose|yp| y == f(yp, a) && #[trigger] fold_graph(z, f, s, yp, sub(d, 1));
364 }
365
366 proof fn lemma_fold_graph_insert_elim_aux<A, B>(
367 z: B,
368 f: spec_fn(B, A) -> B,
369 s: ISet<A>,
370 y: B,
371 d: nat,
372 a: A,
373 )
374 requires
375 is_fun_commutative(f),
376 fold_graph(z, f, s, y, d),
377 s.contains(a),
378 ensures
379 exists|yp| y == f(yp, a) && #[trigger] fold_graph(z, f, s.remove(a), yp, sub(d, 1)),
380 decreases d,
381 {
382 broadcast use group_iset_lemmas_early;
383
384 reveal(fold_graph);
385 let (yr, aa): (B, A) = choose|yr, aa|
386 #![all_triggers]
387 {
388 &&& trigger_fold_graph(yr, a)
389 &&& d > 0
390 &&& s.remove(aa).finite()
391 &&& s.contains(aa)
392 &&& fold_graph(z, f, s.remove(aa), yr, sub(d, 1))
393 &&& y == f(yr, aa)
394 };
395 assert(trigger_fold_graph(yr, a));
396 if s.remove(aa) === ISet::empty() {
397 } else {
398 if a == aa {
399 } else {
400 lemma_fold_graph_insert_elim_aux(z, f, s.remove(aa), yr, sub(d, 1), a);
401 let yrp = choose|yrp|
402 yr == f(yrp, a) && #[trigger] fold_graph(
403 z,
404 f,
405 s.remove(aa).remove(a),
406 yrp,
407 sub(d, 2),
408 );
409 assert(fold_graph(z, f, s.remove(aa).insert(aa).remove(a), f(yrp, aa), sub(d, 1)))
410 by {
411 assert(s.remove(aa).remove(a) == s.remove(aa).insert(aa).remove(a).remove(aa));
412 assert(trigger_fold_graph(yrp, aa));
413 };
414 }
415 }
416 }
417
418 proof fn lemma_fold_graph_induct<A, B>(
420 z: B,
421 f: spec_fn(B, A) -> B,
422 s: ISet<A>,
423 y: B,
424 d: nat,
425 pred: spec_fn(ISet<A>, B, nat) -> bool,
426 )
427 requires
428 is_fun_commutative(f),
429 fold_graph(z, f, s, y, d),
430 pred(ISet::empty(), z, 0),
431 forall|a, s, y, d|
432 pred(s, y, d) && !s.contains(a) && #[trigger] fold_graph(z, f, s, y, d) ==> pred(
433 #[trigger] s.insert(a),
434 f(y, a),
435 d + 1,
436 ),
437 ensures
438 pred(s, y, d),
439 decreases d,
440 {
441 broadcast use group_iset_lemmas_early;
442
443 reveal(fold_graph);
444 if s === ISet::empty() {
445 lemma_fold_graph_empty_elim(z, f, y, d);
446 } else {
447 let a = s.choose();
448 lemma_fold_graph_insert_elim(z, f, s.remove(a), y, d, a);
449 let yp = choose|yp|
450 y == f(yp, a) && #[trigger] fold_graph(z, f, s.remove(a), yp, sub(d, 1));
451 lemma_fold_graph_induct(z, f, s.remove(a), yp, sub(d, 1), pred);
452 }
453 }
454
455 impl<A> ISet<A> {
456 pub closed spec fn fold<B>(self, z: B, f: spec_fn(B, A) -> B) -> B
462 recommends
463 self.finite(),
464 is_fun_commutative(f),
465 {
466 let (y, d): (B, nat) = choose|y, d| fold_graph(z, f, self, y, d);
467 y
468 }
469 }
470
471 proof fn lemma_fold_graph_finite<A, B>(z: B, f: spec_fn(B, A) -> B, s: ISet<A>, y: B, d: nat)
472 requires
473 is_fun_commutative(f),
474 fold_graph(z, f, s, y, d),
475 ensures
476 s.finite(),
477 {
478 broadcast use group_iset_lemmas_early;
479
480 let pred = |s: ISet<A>, y, d| s.finite();
481 lemma_fold_graph_induct(z, f, s, y, d, pred);
482 }
483
484 proof fn lemma_fold_graph_deterministic<A, B>(
485 z: B,
486 f: spec_fn(B, A) -> B,
487 s: ISet<A>,
488 y1: B,
489 y2: B,
490 d1: nat,
491 d2: nat,
492 )
493 requires
494 is_fun_commutative(f),
495 fold_graph(z, f, s, y1, d1),
496 fold_graph(z, f, s, y2, d2),
497 ensures
498 y1 == y2,
499 d1 == d2,
500 {
501 let pred = |s: ISet<A>, y1: B, d1: nat|
502 forall|y2, d2| fold_graph(z, f, s, y2, d2) ==> y1 == y2 && d2 == d1;
503 assert(pred(ISet::empty(), z, 0)) by {
505 assert forall|y2, d2| fold_graph(z, f, ISet::empty(), y2, d2) implies z == y2 && d2
506 == 0 by {
507 lemma_fold_graph_empty_elim(z, f, y2, d2);
508 };
509 };
510 assert forall|a, s, y1, d1|
512 pred(s, y1, d1) && !s.contains(a) && #[trigger] fold_graph(
513 z,
514 f,
515 s,
516 y1,
517 d1,
518 ) implies pred(#[trigger] s.insert(a), f(y1, a), d1 + 1) by {
519 assert forall|y2, d2| fold_graph(z, f, s.insert(a), y2, d2) implies f(y1, a) == y2 && d2
520 == d1 + 1 by {
521 lemma_fold_graph_insert_elim(z, f, s, y2, d2, a);
522 };
523 };
524 lemma_fold_graph_induct(z, f, s, y2, d2, pred);
525 }
526
527 proof fn lemma_fold_is_fold_graph<A, B>(z: B, f: spec_fn(B, A) -> B, s: ISet<A>, y: B, d: nat)
528 requires
529 is_fun_commutative(f),
530 fold_graph(z, f, s, y, d),
531 ensures
532 s.fold(z, f) == y,
533 {
534 lemma_fold_graph_finite(z, f, s, y, d);
535 if s.fold(z, f) != y {
536 let (y2, d2) = choose|y2, d2| fold_graph(z, f, s, y2, d2) && y2 != y;
537 lemma_fold_graph_deterministic(z, f, s, y2, y, d2, d);
538 assert(false);
539 }
540 }
541
542 pub proof fn lemma_finite_set_induct<A>(s: ISet<A>, pred: spec_fn(ISet<A>) -> bool)
547 requires
548 s.finite(),
549 pred(ISet::empty()),
550 forall|s, a| pred(s) && s.finite() && !s.contains(a) ==> #[trigger] pred(s.insert(a)),
551 ensures
552 pred(s),
553 {
554 let (f, ub) = choose|f: spec_fn(A) -> nat, ub: nat| #[trigger]
555 trigger_finite(f, ub) && surj_on(f, s) && (forall|a| s.contains(a) ==> f(a) < ub);
556 lemma_finite_set_induct_aux(s, f, ub, pred);
557 }
558
559 proof fn lemma_finite_set_induct_aux<A>(
560 s: ISet<A>,
561 f: spec_fn(A) -> nat,
562 ub: nat,
563 pred: spec_fn(ISet<A>) -> bool,
564 )
565 requires
566 surj_on(f, s),
567 s.finite(),
568 forall|a| s.contains(a) ==> f(a) < ub,
569 pred(ISet::empty()),
570 forall|s, a| pred(s) && s.finite() && !s.contains(a) ==> #[trigger] pred(s.insert(a)),
571 ensures
572 pred(s),
573 decreases ub,
574 {
575 broadcast use group_iset_lemmas_early;
576
577 if s =~= ISet::empty() {
578 } else {
579 let a = s.choose();
580 let fp = |aa|
582 if f(aa) == ub - 1 {
583 f(a)
584 } else {
585 f(aa)
586 };
587 lemma_finite_set_induct_aux(s.remove(a), fp, sub(ub, 1), pred);
588 }
589 }
590
591 proof fn lemma_fold_graph_exists<A, B>(z: B, f: spec_fn(B, A) -> B, s: ISet<A>)
592 requires
593 s.finite(),
594 is_fun_commutative(f),
595 ensures
596 exists|y, d| fold_graph(z, f, s, y, d),
597 {
598 let pred = |s| exists|y, d| fold_graph(z, f, s, y, d);
599 assert(fold_graph(z, f, ISet::empty(), z, 0)) by {
601 lemma_fold_graph_empty_intro(z, f);
602 };
603 assert forall|s, a| pred(s) && s.finite() && !s.contains(a) implies #[trigger] pred(
605 s.insert(a),
606 ) by {
607 let (y, d): (B, nat) = choose|y, d| fold_graph(z, f, s, y, d);
608 lemma_fold_graph_insert_intro(z, f, s, y, d, a);
609 };
610 lemma_finite_set_induct(s, pred);
611 }
612
613 pub broadcast proof fn lemma_fold_insert<A, B>(s: ISet<A>, z: B, f: spec_fn(B, A) -> B, a: A)
614 requires
615 s.finite(),
616 !s.contains(a),
617 is_fun_commutative(f),
618 ensures
619 #[trigger] s.insert(a).fold(z, f) == f(s.fold(z, f), a),
620 {
621 lemma_fold_graph_exists(z, f, s);
622 let (y, d): (B, nat) = choose|y, d| fold_graph(z, f, s, y, d);
623 lemma_fold_graph_insert_intro(z, f, s, s.fold(z, f), d, a);
624 lemma_fold_is_fold_graph(z, f, s.insert(a), f(s.fold(z, f), a), d + 1);
625 }
626
627 pub broadcast proof fn lemma_fold_empty<A, B>(z: B, f: spec_fn(B, A) -> B)
628 ensures
629 #[trigger] ISet::empty().fold(z, f) == z,
630 {
631 let (y, d): (B, nat) = choose|y, d| fold_graph(z, f, ISet::empty(), y, d);
632 lemma_fold_graph_empty_intro(z, f);
633 lemma_fold_graph_empty_elim(z, f, y, d);
634 }
635
636}
637
638pub broadcast proof fn lemma_iset_empty<A>(a: A)
641 ensures
642 !(#[trigger] ISet::empty().contains(a)),
643{
644}
645
646pub broadcast proof fn lemma_iset_new<A>(f: spec_fn(A) -> bool, a: A)
648 ensures
649 #[trigger] ISet::new(f).contains(a) == f(a),
650{
651}
652
653pub broadcast proof fn lemma_iset_insert_same<A>(s: ISet<A>, a: A)
655 ensures
656 #[trigger] s.insert(a).contains(a),
657{
658}
659
660pub broadcast proof fn lemma_iset_insert_different<A>(s: ISet<A>, a1: A, a2: A)
663 requires
664 a1 != a2,
665 ensures
666 #[trigger] s.insert(a2).contains(a1) == s.contains(a1),
667{
668}
669
670pub broadcast proof fn lemma_iset_remove_same<A>(s: ISet<A>, a: A)
672 ensures
673 !(#[trigger] s.remove(a).contains(a)),
674{
675}
676
677pub broadcast proof fn lemma_iset_remove_insert<A>(s: ISet<A>, a: A)
680 requires
681 s.contains(a),
682 ensures
683 (#[trigger] s.remove(a)).insert(a) == s,
684{
685 assert forall|aa| #![all_triggers] s.remove(a).insert(a).contains(aa) implies s.contains(
686 aa,
687 ) by {
688 if a == aa {
689 } else {
690 lemma_iset_remove_different(s, aa, a);
691 lemma_iset_insert_different(s.remove(a), aa, a);
692 }
693 };
694 assert forall|aa| #![all_triggers] s.contains(aa) implies s.remove(a).insert(a).contains(
695 aa,
696 ) by {
697 if a == aa {
698 lemma_iset_insert_same(s.remove(a), a);
699 } else {
700 lemma_iset_remove_different(s, aa, a);
701 lemma_iset_insert_different(s.remove(a), aa, a);
702 }
703 };
704 lemma_iset_ext_equal(s.remove(a).insert(a), s);
705}
706
707pub broadcast proof fn lemma_iset_remove_different<A>(s: ISet<A>, a1: A, a2: A)
710 requires
711 a1 != a2,
712 ensures
713 #[trigger] s.remove(a2).contains(a1) == s.contains(a1),
714{
715}
716
717pub broadcast proof fn lemma_iset_union<A>(s1: ISet<A>, s2: ISet<A>, a: A)
720 ensures
721 #[trigger] s1.union(s2).contains(a) == (s1.contains(a) || s2.contains(a)),
722{
723}
724
725pub broadcast proof fn lemma_iset_intersect<A>(s1: ISet<A>, s2: ISet<A>, a: A)
728 ensures
729 #[trigger] s1.intersect(s2).contains(a) == (s1.contains(a) && s2.contains(a)),
730{
731}
732
733pub broadcast proof fn lemma_iset_difference<A>(s1: ISet<A>, s2: ISet<A>, a: A)
736 ensures
737 #[trigger] s1.difference(s2).contains(a) == (s1.contains(a) && !s2.contains(a)),
738{
739}
740
741pub broadcast proof fn lemma_iset_complement<A>(s: ISet<A>, a: A)
743 ensures
744 #[trigger] s.complement().contains(a) == !s.contains(a),
745{
746}
747
748pub broadcast proof fn lemma_iset_ext_equal<A>(s1: ISet<A>, s2: ISet<A>)
750 ensures
751 #[trigger] (s1 =~= s2) <==> (forall|a: A| s1.contains(a) == s2.contains(a)),
752{
753 if s1 =~= s2 {
754 assert(forall|a: A| s1.contains(a) == s2.contains(a));
755 }
756 if forall|a: A| s1.contains(a) == s2.contains(a) {
757 if !(forall|a: A| #[trigger] (s1.set)(a) <==> (s2.set)(a)) {
758 assert(exists|a: A| #[trigger] (s1.set)(a) != (s2.set)(a));
759 let a = choose|a: A| #[trigger] (s1.set)(a) != (s2.set)(a);
760 assert(s1.contains(a));
761 assert(false);
762 }
763 assert(s1 =~= s2);
764 }
765}
766
767pub broadcast proof fn lemma_iset_ext_equal_deep<A>(s1: ISet<A>, s2: ISet<A>)
768 ensures
769 #[trigger] (s1 =~~= s2) <==> s1 =~= s2,
770{
771}
772
773pub broadcast axiom fn lemma_iset_mk_map_domain<K, V>(s: ISet<K>, f: spec_fn(K) -> V)
774 ensures
775 #[trigger] s.mk_map(f).dom() == s,
776;
777
778pub broadcast axiom fn lemma_iset_mk_map_index<K, V>(s: ISet<K>, f: spec_fn(K) -> V, key: K)
779 requires
780 s.contains(key),
781 ensures
782 #[trigger] s.mk_map(f)[key] == f(key),
783;
784
785pub broadcast proof fn lemma_iset_empty_finite<A>()
788 ensures
789 #[trigger] ISet::<A>::empty().finite(),
790{
791 let f = |a: A| 0;
792 let ub = 0;
793 let _ = trigger_finite(f, ub);
794}
795
796pub broadcast proof fn lemma_iset_insert_finite<A>(s: ISet<A>, a: A)
798 requires
799 s.finite(),
800 ensures
801 #[trigger] s.insert(a).finite(),
802{
803 let (f, ub) = choose|f: spec_fn(A) -> nat, ub: nat| #[trigger]
804 trigger_finite(f, ub) && surj_on(f, s) && (forall|a| s.contains(a) ==> f(a) < ub);
805 let f2 = |a2: A|
806 if a2 == a {
807 ub
808 } else {
809 f(a2)
810 };
811 let ub2 = ub + 1;
812 let _ = trigger_finite(f2, ub2);
813 assert forall|a1, a2|
814 #![all_triggers]
815 s.insert(a).contains(a1) && s.insert(a).contains(a2) && a1 != a2 implies f2(a1) != f2(
816 a2,
817 ) by {
818 if a != a1 {
819 assert(s.contains(a1));
820 }
821 if a != a2 {
822 assert(s.contains(a2));
823 }
824 };
825 assert forall|a2| s.insert(a).contains(a2) implies #[trigger] f2(a2) < ub2 by {
826 if a == a2 {
827 } else {
828 assert(s.contains(a2));
829 }
830 };
831}
832
833pub broadcast proof fn lemma_iset_remove_finite<A>(s: ISet<A>, a: A)
835 requires
836 s.finite(),
837 ensures
838 #[trigger] s.remove(a).finite(),
839{
840 let (f, ub) = choose|f: spec_fn(A) -> nat, ub: nat| #[trigger]
841 trigger_finite(f, ub) && surj_on(f, s) && (forall|a| s.contains(a) ==> f(a) < ub);
842 assert forall|a1, a2|
843 #![all_triggers]
844 s.remove(a).contains(a1) && s.remove(a).contains(a2) && a1 != a2 implies f(a1) != f(a2) by {
845 if a != a1 {
846 assert(s.contains(a1));
847 }
848 if a != a2 {
849 assert(s.contains(a2));
850 }
851 };
852 assert(surj_on(f, s.remove(a)));
853 assert forall|a2| s.remove(a).contains(a2) implies #[trigger] f(a2) < ub by {
854 if a == a2 {
855 } else {
856 assert(s.contains(a2));
857 }
858 };
859}
860
861pub broadcast proof fn lemma_iset_union_finite<A>(s1: ISet<A>, s2: ISet<A>)
863 requires
864 s1.finite(),
865 s2.finite(),
866 ensures
867 #[trigger] s1.union(s2).finite(),
868{
869 let (f1, ub1) = choose|f: spec_fn(A) -> nat, ub: nat| #[trigger]
870 trigger_finite(f, ub) && surj_on(f, s1) && (forall|a| s1.contains(a) ==> f(a) < ub);
871 let (f2, ub2) = choose|f: spec_fn(A) -> nat, ub: nat| #[trigger]
872 trigger_finite(f, ub) && surj_on(f, s2) && (forall|a| s2.contains(a) ==> f(a) < ub);
873 let f3 = |a|
874 if s1.contains(a) {
875 f1(a)
876 } else {
877 ub1 + f2(a)
878 };
879 let ub3 = ub1 + ub2;
880 assert(trigger_finite(f3, ub3));
881 assert(forall|a|
882 #![all_triggers]
883 s1.union(s2).contains(a) ==> s1.contains(a) || s2.contains(a));
884}
885
886pub broadcast proof fn lemma_iset_intersect_finite<A>(s1: ISet<A>, s2: ISet<A>)
888 requires
889 s1.finite() || s2.finite(),
890 ensures
891 #[trigger] s1.intersect(s2).finite(),
892{
893 assert(forall|a|
894 #![all_triggers]
895 s1.intersect(s2).contains(a) ==> s1.contains(a) && s2.contains(a));
896}
897
898pub broadcast proof fn lemma_iset_difference_finite<A>(s1: ISet<A>, s2: ISet<A>)
900 requires
901 s1.finite(),
902 ensures
903 #[trigger] s1.difference(s2).finite(),
904{
905 assert(forall|a|
906 #![all_triggers]
907 s1.difference(s2).contains(a) ==> s1.contains(a) && !s2.contains(a));
908}
909
910pub broadcast proof fn lemma_iset_choose_infinite<A>(s: ISet<A>)
912 requires
913 !s.finite(),
914 ensures
915 #[trigger] s.contains(s.choose()),
916{
917 let f = |a: A| 0;
918 let ub = 0;
919 let _ = trigger_finite(f, ub);
920}
921
922pub broadcast proof fn lemma_iset_empty_len<A>()
927 ensures
928 #[trigger] ISet::<A>::empty().len() == 0,
929{
930 fold::lemma_fold_empty(0, |b: nat, a: A| b + 1);
931}
932
933pub broadcast proof fn lemma_iset_insert_len<A>(s: ISet<A>, a: A)
936 requires
937 s.finite(),
938 ensures
939 #[trigger] s.insert(a).len() == s.len() + (if s.contains(a) {
940 0int
941 } else {
942 1
943 }),
944{
945 if s.contains(a) {
946 assert(s =~= s.insert(a));
947 } else {
948 fold::lemma_fold_insert(s, 0, |b: nat, a: A| b + 1, a);
949 }
950}
951
952pub broadcast proof fn lemma_iset_remove_len<A>(s: ISet<A>, a: A)
955 requires
956 s.finite(),
957 ensures
958 s.len() == #[trigger] s.remove(a).len() + (if s.contains(a) {
959 1int
960 } else {
961 0
962 }),
963{
964 lemma_iset_remove_finite(s, a);
965 lemma_iset_insert_len(s.remove(a), a);
966 if s.contains(a) {
967 assert(s =~= s.remove(a).insert(a));
968 } else {
969 assert(s =~= s.remove(a));
970 }
971}
972
973pub broadcast proof fn lemma_iset_contains_len<A>(s: ISet<A>, a: A)
975 requires
976 s.finite(),
977 #[trigger] s.contains(a),
978 ensures
979 #[trigger] s.len() != 0,
980{
981 let a = s.choose();
982 assert(s.remove(a).insert(a) =~= s);
983 lemma_iset_remove_finite(s, a);
984 lemma_iset_insert_finite(s.remove(a), a);
985 lemma_iset_insert_len(s.remove(a), a);
986}
987
988pub broadcast proof fn lemma_iset_choose_len<A>(s: ISet<A>)
990 requires
991 s.finite(),
992 #[trigger] s.len() != 0,
993 ensures
994 #[trigger] s.contains(s.choose()),
995{
996 broadcast use lemma_iset_contains_len;
998 broadcast use lemma_iset_empty_len;
999 broadcast use lemma_iset_ext_equal;
1000 broadcast use lemma_iset_insert_finite;
1001
1002 let pred = |s: ISet<A>| s.finite() ==> s.len() == 0 <==> s =~= ISet::empty();
1003 fold::lemma_finite_set_induct(s, pred);
1004}
1005
1006pub proof fn lemma_iset_finite_if_subset_of_seq<A>(i: ISet<A>, s: Seq<A>)
1007 requires
1008 forall|a| i.contains(a) ==> s.contains(a),
1009 ensures
1010 i.finite(),
1011{
1012 let f = |a: A| (s.index_of(a) as nat);
1013 let ub = s.len();
1014 assert(surj_on(f, i)) by {
1015 assert forall|a1, a2|
1016 #![all_triggers]
1017 i.contains(a1) && i.contains(a2) && a1 != a2 implies f(a1) != f(a2) by {
1018 assert(s.contains(a1));
1019 assert(s.contains(a2));
1020 assert(0 <= f(a1) < s.len() && s[f(a1) as int] == a1);
1021 assert(0 <= f(a2) < s.len() && s[f(a2) as int] == a2);
1022 }
1023 }
1024 assert forall|a| i.contains(a) implies f(a) < ub by {
1025 assert(s.contains(a));
1026 assert(0 <= f(a) < s.len() && s[f(a) as int] == a);
1027 }
1028 assert(trigger_finite(f, ub));
1029}
1030
1031pub broadcast group group_iset_lemmas {
1032 lemma_iset_empty,
1033 lemma_iset_new,
1034 lemma_iset_insert_same,
1035 lemma_iset_insert_different,
1036 lemma_iset_remove_same,
1037 lemma_iset_remove_insert,
1038 lemma_iset_remove_different,
1039 lemma_iset_union,
1040 lemma_iset_intersect,
1041 lemma_iset_difference,
1042 lemma_iset_complement,
1043 lemma_iset_ext_equal,
1044 lemma_iset_ext_equal_deep,
1045 lemma_iset_mk_map_domain,
1046 lemma_iset_mk_map_index,
1047 lemma_iset_empty_finite,
1048 lemma_iset_insert_finite,
1049 lemma_iset_remove_finite,
1050 lemma_iset_union_finite,
1051 lemma_iset_intersect_finite,
1052 lemma_iset_difference_finite,
1053 lemma_iset_choose_infinite,
1054 lemma_iset_empty_len,
1055 lemma_iset_insert_len,
1056 lemma_iset_remove_len,
1057 lemma_iset_contains_len,
1058 lemma_iset_choose_len,
1059}
1060
1061#[doc(hidden)]
1063#[macro_export]
1064macro_rules! iset_internal {
1065 [$($elem:expr),* $(,)?] => {
1066 $crate::vstd::iset::ISet::empty()
1067 $(.insert($elem))*
1068 };
1069}
1070
1071#[macro_export]
1072macro_rules! iset {
1073 [$($tail:tt)*] => {
1074 $crate::vstd::prelude::verus_proof_macro_exprs!($crate::vstd::iset::iset_internal!($($tail)*))
1075 };
1076}
1077
1078pub use iset_internal;
1079pub use iset;
1080
1081}