1#[macro_use]
2use super::imap::{IMap, assert_imaps_equal, assert_imaps_equal_internal};
3#[cfg(verus_keep_ghost)]
4use super::iset::*;
5#[cfg(verus_keep_ghost)]
6use super::iset_lib::*;
7#[allow(unused_imports)]
8use super::pervasive::*;
9#[allow(unused_imports)]
10use super::prelude::*;
11#[allow(unused_imports)]
12use super::relations::*;
13
14verus! {
15
16broadcast use {super::imap::group_imap_lemmas, super::iset::group_iset_lemmas};
17
18impl<K, V> IMap<K, V> {
19 #[verifier::inline]
21 pub open spec fn is_full(self) -> bool {
22 self.dom().is_full()
23 }
24
25 #[verifier::inline]
27 pub open spec fn is_empty(self) -> (b: bool) {
28 self.dom().is_empty()
29 }
30
31 #[verifier::inline]
33 pub open spec fn contains_key(self, k: K) -> bool {
34 self.dom().contains(k)
35 }
36
37 pub open spec fn contains_value(self, v: V) -> bool {
39 exists|i: K| #[trigger] self.dom().contains(i) && self[i] == v
40 }
41
42 pub open spec fn index_opt(self, k: K) -> Option<V> {
45 if self.contains_key(k) {
46 Some(self[k])
47 } else {
48 None
49 }
50 }
51
52 pub open spec fn values(self) -> ISet<V> {
66 ISet::<V>::new(|v: V| self.contains_value(v))
67 }
68
69 pub open spec fn kv_pairs(self) -> ISet<(K, V)> {
83 ISet::<(K, V)>::new(|kv: (K, V)| self.dom().contains(kv.0) && self[kv.0] == kv.1)
84 }
85
86 pub open spec fn contains_pair(self, k: K, v: V) -> bool {
88 &&& self.dom().contains(k)
92 &&& self.dom().contains(k) ==> self[k] == v
93 }
94
95 pub open spec fn submap_of(self, m2: Self) -> bool {
106 forall|k: K| #[trigger]
107 self.dom().contains(k) ==> #[trigger] m2.dom().contains(k) && self[k] == m2[k]
108 }
109
110 #[verifier::inline]
111 pub open spec fn spec_le(self, m2: Self) -> bool {
112 self.submap_of(m2)
113 }
114
115 pub open spec fn union_prefer_right(self, m2: Self) -> Self {
129 Self::new(
130 |k: K| self.dom().contains(k) || m2.dom().contains(k),
131 |k: K|
132 if m2.dom().contains(k) {
133 m2[k]
134 } else {
135 self[k]
136 },
137 )
138 }
139
140 pub open spec fn remove_keys(self, keys: ISet<K>) -> Self {
152 Self::new(|k: K| self.dom().contains(k) && !keys.contains(k), |k: K| self[k])
153 }
154
155 pub open spec fn restrict(self, keys: ISet<K>) -> Self {
167 Self::new(|k: K| self.dom().contains(k) && keys.contains(k), |k: K| self[k])
168 }
169
170 pub open spec fn is_equal_on_key(self, m2: Self, key: K) -> bool {
172 ||| (!self.dom().contains(key) && !m2.dom().contains(key))
173 ||| (self.dom().contains(key) && m2.dom().contains(key) && self[key] == m2[key])
174 }
175
176 pub open spec fn agrees(self, m2: Self) -> bool {
178 forall|k| #![auto] self.dom().contains(k) && m2.dom().contains(k) ==> self[k] == m2[k]
179 }
180
181 pub open spec fn map_entries<W>(self, f: spec_fn(K, V) -> W) -> IMap<K, W> {
183 IMap::new(|k: K| self.contains_key(k), |k: K| f(k, self[k]))
184 }
185
186 pub open spec fn map_values<W>(self, f: spec_fn(V) -> W) -> IMap<K, W> {
188 IMap::new(|k: K| self.contains_key(k), |k: K| f(self[k]))
189 }
190
191 pub open spec fn is_injective(self) -> bool {
193 forall|x: K, y: K|
194 x != y && self.dom().contains(x) && self.dom().contains(y) ==> #[trigger] self[x]
195 != #[trigger] self[y]
196 }
197
198 pub open spec fn invert(self) -> IMap<V, K> {
201 IMap::<V, K>::new(
202 |v: V| self.contains_value(v),
203 |v: V| choose|k: K| self.contains_pair(k, v),
204 )
205 }
206
207 pub proof fn lemma_remove_key_len(self, key: K)
211 requires
212 self.dom().contains(key),
213 self.dom().finite(),
214 ensures
215 self.dom().len() == 1 + self.remove(key).dom().len(),
216 {
217 }
218
219 pub proof fn lemma_remove_equivalency(self, key: K)
222 ensures
223 self.remove(key).dom() == self.dom().remove(key),
224 {
225 }
226
227 pub proof fn lemma_remove_keys_len(self, keys: ISet<K>)
230 requires
231 forall|k: K| #[trigger] keys.contains(k) ==> self.contains_key(k),
232 keys.finite(),
233 self.dom().finite(),
234 ensures
235 self.remove_keys(keys).dom().len() == self.dom().len() - keys.len(),
236 decreases keys.len(),
237 {
238 broadcast use group_iset_properties;
239
240 if keys.len() > 0 {
241 let key = keys.choose();
242 let val = self[key];
243 self.remove(key).lemma_remove_keys_len(keys.remove(key));
244 assert(self.remove(key).remove_keys(keys.remove(key)) =~= self.remove_keys(keys));
245 } else {
246 assert(self.remove_keys(keys) =~= self);
247 }
248 }
249
250 pub proof fn lemma_invert_is_injective(self)
252 ensures
253 self.invert().is_injective(),
254 {
255 assert forall|x: V, y: V|
256 x != y && self.invert().dom().contains(x) && self.invert().dom().contains(
257 y,
258 ) implies #[trigger] self.invert()[x] != #[trigger] self.invert()[y] by {
259 let i = choose|i: K| #[trigger] self.dom().contains(i) && self[i] == x;
260 assert(self.contains_pair(i, x));
261 let j = choose|j: K| self.contains_pair(j, x) && self.invert()[x] == j;
262 let k = choose|k: K| #[trigger] self.dom().contains(k) && self[k] == y;
263 assert(self.contains_pair(k, y));
264 let l = choose|l: K| self.contains_pair(l, y) && self.invert()[y] == l && l != j;
265 }
266 }
267
268 pub open spec fn filter_keys(self, p: spec_fn(K) -> bool) -> Self {
279 self.restrict(self.dom().filter(p))
280 }
281
282 pub open spec fn get(self, k: K) -> Option<V> {
298 if self.dom().contains(k) {
299 Some(self[k])
300 } else {
301 None
302 }
303 }
304
305 pub proof fn get_dom_value_any(self, p: spec_fn(V) -> bool)
317 ensures
318 self.dom().any(|k: K| p(self[k])) <==> self.values().any(p),
319 {
320 broadcast use group_imap_properties;
321
322 if self.dom().any(|k: K| p(self[k])) {
323 let k = choose|k: K| self.dom().contains(k) && #[trigger] p(self[k]);
324 assert(self.values().contains(self[k]));
325 assert(self.values().any(p));
326 }
327 }
328
329 pub proof fn lemma_submap_eq_iff(self, m: Self)
343 ensures
344 (self == m) <==> (self.submap_of(m) && m.submap_of(self)),
345 {
346 broadcast use group_imap_properties;
347
348 if self.submap_of(m) && m.submap_of(self) {
349 assert(self.dom() == m.dom());
350 assert(self == m);
351 }
352 }
353
354 pub broadcast proof fn lemma_imap_remove_keys_insert(self, r: ISet<K>, k: K, v: V)
373 ensures
374 #[trigger] self.insert(k, v).remove_keys(r) == if r.contains(k) {
375 self.remove_keys(r)
376 } else {
377 self.remove_keys(r).insert(k, v)
378 },
379 {
380 broadcast use group_imap_properties;
381
382 let lhs = self.insert(k, v).remove_keys(r);
383 let rhs = if r.contains(k) {
384 self.remove_keys(r)
385 } else {
386 self.remove_keys(r).insert(k, v)
387 };
388 assert(lhs == rhs);
389 }
390
391 pub broadcast proof fn lemma_filter_keys_insert(self, p: spec_fn(K) -> bool, k: K, v: V)
406 ensures
407 #[trigger] self.insert(k, v).filter_keys(p) == (if p(k) {
408 self.filter_keys(p).insert(k, v)
409 } else {
410 self.filter_keys(p)
411 }),
412 {
413 broadcast use group_imap_properties;
414
415 let lhs = self.insert(k, v).filter_keys(p);
416 let rhs = if p(k) {
417 self.filter_keys(p).insert(k, v)
418 } else {
419 self.filter_keys(p)
420 };
421 assert(lhs == rhs);
422 }
423
424 pub broadcast proof fn lemma_insert_contains_value(self, k: K, v: V)
434 ensures
435 #[trigger] self.insert(k, v).contains_value(v),
436 {
437 assert(self.insert(k, v).contains_key(k));
438 }
439
440 pub broadcast proof fn lemma_insert_invariant_contains(self, old_v: V, k: K, v: V)
452 requires
453 self.contains_key(k) ==> self[k] != old_v,
454 old_v != v,
455 ensures
456 #[trigger] self.insert(k, v).contains_value(old_v) == self.contains_value(old_v),
457 {
458 if self.contains_value(old_v) {
459 let old_k = choose|key: K| #[trigger] self.dom().contains(key) && self[key] == old_v;
460 assert(self.insert(k, v).contains_key(old_k));
461 }
462 }
463
464 pub proof fn lemma_injective_values_len(self)
465 requires
466 self.dom().finite(),
467 self.is_injective(),
468 ensures
469 self.values().finite(),
470 self.values().len() == self.dom().len(),
471 {
472 let f = |k: K|
473 if self.contains_key(k) {
474 self[k]
475 } else {
476 ISet::<V>::full().difference(self.values()).choose()
477 };
478 assert(forall|a1: K, a2: K|
479 self.dom().contains(a1) && self.dom().contains(a2) && #[trigger] f(a1) == #[trigger] f(
480 a2,
481 ) ==> a1 == a2);
482 assert(self.dom().map(f) == self.values());
483 super::iset_lib::lemma_map_size(self.dom(), self.values(), f);
484 }
485
486 pub proof fn lemma_values_len(self)
487 requires
488 self.dom().finite(),
489 ensures
490 self.values().finite(),
491 self.values().len() <= self.dom().len(),
492 {
493 let f = |k: K|
494 if self.contains_key(k) {
495 self[k]
496 } else {
497 ISet::<V>::full().difference(self.values()).choose()
498 };
499 assert(self.dom().map(f) == self.values());
500 super::iset_lib::lemma_map_size_bound(self.dom(), self.values(), f);
501 }
502}
503
504impl<K, V> IMap<Seq<K>, V> {
505 pub open spec fn prefixed_entries(self, prefix: Seq<K>) -> Self {
524 IMap::new(|k: Seq<K>| self.contains_key(prefix + k), |k: Seq<K>| self[prefix + k])
525 }
526
527 pub broadcast proof fn lemma_prefixed_entries_get(self, prefix: Seq<K>, k: Seq<K>)
542 requires
543 self.prefixed_entries(prefix).contains_key(k),
544 ensures
545 self.prefixed_entries(prefix)[k] == #[trigger] self[prefix + k],
546 {
547 broadcast use group_imap_properties;
548
549 }
550
551 pub broadcast proof fn lemma_prefixed_entries_contains(self, prefix: Seq<K>, k: Seq<K>)
570 ensures
571 #[trigger] self.prefixed_entries(prefix).contains_key(k) <==> self.contains_key(
572 prefix + k,
573 ),
574 {
575 broadcast use group_imap_properties;
576
577 let lhs = self.prefixed_entries(prefix);
578 let rhs = self;
579 }
580
581 pub broadcast proof fn lemma_prefixed_entries_insert(self, prefix: Seq<K>, k: Seq<K>, v: V)
597 ensures
598 #[trigger] self.insert(prefix + k, v).prefixed_entries(prefix) == self.prefixed_entries(
599 prefix,
600 ).insert(k, v),
601 {
602 broadcast use group_imap_properties;
603 broadcast use super::seq::group_seq_axioms;
604 broadcast use super::seq_lib::group_seq_properties, super::seq_lib::lemma_seq_skip_of_skip;
605 broadcast use Map::lemma_prefixed_entries_contains, Map::lemma_prefixed_entries_get;
606
607 let lhs = self.insert(prefix + k, v).prefixed_entries(prefix);
608 let rhs = self.prefixed_entries(prefix).insert(k, v);
609 assert(lhs =~= rhs) by {
610 assert(forall|key| key != k ==> prefix.is_prefix_of(#[trigger] (prefix + key)));
611 }
612 }
613
614 pub broadcast proof fn lemma_prefixed_entries_union(self, m: Self, prefix: Seq<K>)
632 ensures
633 #[trigger] self.union_prefer_right(m).prefixed_entries(prefix) == self.prefixed_entries(
634 prefix,
635 ).union_prefer_right(m.prefixed_entries(prefix)),
636 {
637 broadcast use group_imap_properties;
638 broadcast use
639 IMap::lemma_prefixed_entries_contains,
640 IMap::lemma_prefixed_entries_get,
641 IMap::lemma_prefixed_entries_insert,
642 ;
643
644 let lhs = self.union_prefer_right(m).prefixed_entries(prefix);
645 let rhs = self.prefixed_entries(prefix).union_prefer_right(m.prefixed_entries(prefix));
646 assert(lhs == rhs);
647 }
648}
649
650impl IMap<int, int> {
651 pub open spec fn is_monotonic(self) -> bool {
654 forall|x: int, y: int|
655 self.dom().contains(x) && self.dom().contains(y) && x <= y ==> #[trigger] self[x]
656 <= #[trigger] self[y]
657 }
658
659 pub open spec fn is_monotonic_from(self, start: int) -> bool {
662 forall|x: int, y: int|
663 self.dom().contains(x) && self.dom().contains(y) && start <= x <= y
664 ==> #[trigger] self[x] <= #[trigger] self[y]
665 }
666}
667
668pub broadcast proof fn lemma_union_insert_left<K, V>(m1: IMap<K, V>, m2: IMap<K, V>, k: K, v: V)
670 requires
671 !m2.contains_key(k),
672 ensures
673 #[trigger] m1.insert(k, v).union_prefer_right(m2) == m1.union_prefer_right(m2).insert(k, v),
674{
675 assert(m1.insert(k, v).union_prefer_right(m2) =~= m1.union_prefer_right(m2).insert(k, v));
676}
677
678pub broadcast proof fn lemma_union_insert_right<K, V>(m1: IMap<K, V>, m2: IMap<K, V>, k: K, v: V)
679 ensures
680 #[trigger] m1.union_prefer_right(m2.insert(k, v)) == m1.union_prefer_right(m2).insert(k, v),
681{
682 assert(m1.union_prefer_right(m2.insert(k, v)) =~= m1.union_prefer_right(m2).insert(k, v));
683}
684
685pub broadcast proof fn lemma_union_remove_left<K, V>(m1: IMap<K, V>, m2: IMap<K, V>, k: K)
686 requires
687 m1.contains_key(k),
688 !m2.contains_key(k),
689 ensures
690 #[trigger] m1.union_prefer_right(m2).remove(k) == m1.remove(k).union_prefer_right(m2),
691{
692 assert(m1.remove(k).union_prefer_right(m2) =~= m1.union_prefer_right(m2).remove(k));
693}
694
695pub broadcast proof fn lemma_union_remove_right<K, V>(m1: IMap<K, V>, m2: IMap<K, V>, k: K)
696 requires
697 !m1.contains_key(k),
698 m2.contains_key(k),
699 ensures
700 #[trigger] m1.union_prefer_right(m2).remove(k) == m1.union_prefer_right(m2.remove(k)),
701{
702 assert(m1.union_prefer_right(m2.remove(k)) =~= m1.union_prefer_right(m2).remove(k));
703}
704
705pub broadcast proof fn lemma_union_dom<K, V>(m1: IMap<K, V>, m2: IMap<K, V>)
706 ensures
707 #[trigger] m1.union_prefer_right(m2).dom() == m1.dom().union(m2.dom()),
708{
709 assert(m1.dom().union(m2.dom()) =~= m1.union_prefer_right(m2).dom());
710}
711
712pub broadcast proof fn lemma_disjoint_union_size<K, V>(m1: IMap<K, V>, m2: IMap<K, V>)
714 requires
715 m1.dom().disjoint(m2.dom()),
716 m1.dom().finite(),
717 m2.dom().finite(),
718 ensures
719 #[trigger] m1.union_prefer_right(m2).dom().len() == m1.dom().len() + m2.dom().len(),
720{
721 let u = m1.union_prefer_right(m2);
722 assert(u.dom() =~= m1.dom() + m2.dom()); assert(u.remove_keys(m1.dom()).dom() =~= m2.dom());
724 assert(u.remove_keys(m1.dom()).dom().len() == u.dom().len() - m1.dom().len()) by {
725 u.lemma_remove_keys_len(m1.dom());
726 }
727}
728
729pub broadcast group group_imap_union {
730 lemma_union_dom,
731 lemma_union_remove_left,
732 lemma_union_remove_right,
733 lemma_union_insert_left,
734 lemma_union_insert_right,
735 lemma_disjoint_union_size,
736}
737
738pub broadcast proof fn lemma_submap_of_trans<K, V>(m1: IMap<K, V>, m2: IMap<K, V>, m3: IMap<K, V>)
740 requires
741 #[trigger] m1.submap_of(m2),
742 #[trigger] m2.submap_of(m3),
743 ensures
744 m1.submap_of(m3),
745{
746 assert forall|k| m1.dom().contains(k) implies #[trigger] m3.dom().contains(k) && m1[k]
747 == m3[k] by {
748 assert(m2.dom().contains(k));
749 }
750}
751
752pub broadcast proof fn lemma_imap_new_domain<K, V>(fk: spec_fn(K) -> bool, fv: spec_fn(K) -> V)
755 ensures
756 #[trigger] IMap::<K, V>::new(fk, fv).dom() == ISet::<K>::new(|k: K| fk(k)),
757{
758 assert(ISet::new(fk) =~= ISet::<K>::new(|k: K| fk(k)));
759}
760
761pub broadcast proof fn lemma_imap_new_values<K, V>(fk: spec_fn(K) -> bool, fv: spec_fn(K) -> V)
766 ensures
767 #[trigger] IMap::<K, V>::new(fk, fv).values() == ISet::<V>::new(
768 |v: V| (exists|k: K| #[trigger] fk(k) && #[trigger] fv(k) == v),
769 ),
770{
771 let keys = ISet::<K>::new(fk);
772 let values = IMap::<K, V>::new(fk, fv).values();
773 let map = IMap::<K, V>::new(fk, fv);
774 assert(map.dom() =~= keys);
775 assert(forall|k: K| #[trigger] fk(k) ==> keys.contains(k));
776 assert(values =~= ISet::<V>::new(
777 |v: V| (exists|k: K| #[trigger] fk(k) && #[trigger] fv(k) == v),
778 ));
779}
780
781pub broadcast group group_imap_properties {
782 lemma_imap_new_domain,
783 lemma_imap_new_values,
784}
785
786pub broadcast group group_imap_extra {
787 IMap::lemma_imap_remove_keys_insert,
788 IMap::lemma_filter_keys_insert,
789 IMap::lemma_insert_contains_value,
790 IMap::lemma_insert_invariant_contains,
791 IMap::lemma_prefixed_entries_get,
792 IMap::lemma_prefixed_entries_contains,
793 IMap::lemma_prefixed_entries_insert,
794 IMap::lemma_prefixed_entries_union,
795}
796
797pub proof fn lemma_values_finite<K, V>(m: IMap<K, V>)
798 requires
799 m.dom().finite(),
800 ensures
801 m.values().finite(),
802 decreases m.len(),
803{
804 if m.len() > 0 {
805 let k = m.dom().choose();
806 let v = m[k];
807 let m1 = m.remove(k);
808 assert(m.contains_key(k));
809 assert(m.contains_value(v));
810 let mv = m.values();
811 let m1v = m1.values();
812 assert_isets_equal!(mv == m1v.insert(v), v0 => {
813 if m.contains_value(v0) {
814 if v0 != v {
815 let k0 = choose|k0| #![auto] m.contains_key(k0) && m[k0] == v0;
816 assert(k0 != k);
817 assert(m1.contains_key(k0));
818 assert(mv.contains(v0) ==> m1v.insert(v).contains(v0));
819 assert(mv.contains(v0) <== m1v.insert(v).contains(v0));
820 }
821 }
822 });
823 assert(m1.len() < m.len());
824 lemma_values_finite(m1);
825 lemma_iset_insert_finite(m1.values(), v);
826 } else {
827 assert(m.values() =~= ISet::<V>::empty());
828 }
829}
830
831}