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