1use vstd::prelude::*;
3use vstd::{map::*, set::*};
4
5verus! {
6
7pub proof fn lemma_map_insert_len<K, V>(m: Map<K, V>, k: K, v: V)
11 ensures
12 #[trigger] m.insert(k, v).len() == m.len() + (if m.contains_key(k) {
13 0int
14 } else {
15 1
16 }),
17{
18 lemma_map_insert_domain(m, k, v)
19}
20
21pub proof fn lemma_map_remove_len<K, V>(m: Map<K, V>, k: K)
25 ensures
26 m.len() == #[trigger] m.remove(k).len() + (if m.contains_key(k) {
27 1
28 } else {
29 0int
30 }),
31{
32 lemma_map_remove_domain(m, k)
33}
34
35pub open spec fn value_filter<K, V>(m: Map<K, V>, f: spec_fn(V) -> bool) -> Map<K, V> {
37 m.restrict(m.dom().filter(|s| f(m[s])))
38}
39
40pub open spec fn value_filter_choose<K, V>(m: Map<K, V>, f: spec_fn(V) -> bool) -> K {
41 choose|k: K| value_filter(m, f).contains_key(k)
42}
43
44pub broadcast group group_value_filter_lemmas {
45 lemma_value_filter_choose,
46 lemma_insert_value_filter_same_len,
47 lemma_insert_value_filter_different_len_contains,
48 lemma_insert_value_filter_different_len_not_contains,
49}
50
51pub proof fn lemma_value_filter_contains<K, V>(m: Map<K, V>, f: spec_fn(V) -> bool, k: K)
55 requires
56 m.contains_key(k),
57 ensures
58 if f(m[k]) {
59 value_filter(m, f).contains_key(k)
60 } else {
61 !value_filter(m, f).contains_key(k)
62 },
63{
64}
65
66pub proof fn lemma_value_filter_all_true<K, V>(m: Map<K, V>, f: spec_fn(V) -> bool)
69 requires
70 forall|k: K| m.contains_key(k) ==> #[trigger] f(m[k]),
71 ensures
72 value_filter(m, f) == m,
73{
74}
75
76pub proof fn lemma_value_filter_all_false<K, V>(m: Map<K, V>, f: spec_fn(V) -> bool)
79 ensures
80 value_filter(m, f).is_empty() <==> forall|k: K| m.contains_key(k) ==> !#[trigger] f(m[k]),
81{
82 if value_filter(m, f).is_empty() {
83 assert forall|k: K| m.contains_key(k) implies !#[trigger] f(m[k]) by {
84 if f(m[k]) {
85 assert(value_filter(m, f).contains_key(k));
86 }
87 }
88 }
89}
90
91pub proof fn lemma_remove_value_filter_true<K, V>(m: Map<K, V>, f: spec_fn(V) -> bool, k: K)
95 requires
96 f(m[k]),
97 ensures
98 value_filter(m.remove(k), f) == value_filter(m, f).remove(k),
99{
100}
101
102pub proof fn lemma_remove_value_filter_false<K, V>(m: Map<K, V>, f: spec_fn(V) -> bool, k: K)
106 requires
107 !f(m[k]),
108 ensures
109 value_filter(m.remove(k), f) == value_filter(m, f),
110{
111}
112
113pub proof fn lemma_insert_value_filter_true<K, V>(m: Map<K, V>, f: spec_fn(V) -> bool, k: K, v: V)
118 requires
119 f(v),
120 ensures
121 value_filter(m.insert(k, v), f) == value_filter(m, f).insert(k, v),
122{
123}
124
125pub proof fn lemma_insert_value_filter_false<K, V>(m: Map<K, V>, f: spec_fn(V) -> bool, k: K, v: V)
131 requires
132 !f(v),
133 ensures
134 value_filter(m.insert(k, v), f) == if m.contains_key(k) {
135 value_filter(m, f).remove(k)
136 } else {
137 value_filter(m, f)
138 },
139{
140}
141
142pub broadcast proof fn lemma_insert_value_filter_same_len<K, V>(
147 m: Map<K, V>,
148 f: spec_fn(V) -> bool,
149 k: K,
150 v: V,
151)
152 requires
153 m.contains_key(k) && f(m[k]) == f(v) || !m.contains_key(k) && !f(v),
154 ensures
155 #[trigger] value_filter(m.insert(k, v), f).len() == value_filter(m, f).len(),
156{
157 if f(v) {
158 lemma_insert_value_filter_true(m, f, k, v);
159 lemma_map_insert_len(value_filter(m, f), k, v);
160 } else {
161 lemma_insert_value_filter_false(m, f, k, v);
162 lemma_map_remove_len(value_filter(m, f), k);
163 }
164}
165
166pub broadcast proof fn lemma_insert_value_filter_different_len_contains<K, V>(
171 m: Map<K, V>,
172 f: spec_fn(V) -> bool,
173 k: K,
174 v: V,
175)
176 requires
177 m.contains_key(k),
178 f(m[k]) != f(v),
179 ensures
180 #[trigger] value_filter(m.insert(k, v), f).len() == value_filter(m, f).len() + if f(v) {
181 1
182 } else {
183 -1
184 },
185{
186 if f(v) {
187 lemma_insert_value_filter_true(m, f, k, v);
188 lemma_map_insert_len(m, k, v);
189 } else {
190 lemma_insert_value_filter_false(m, f, k, v);
191 lemma_map_remove_len(value_filter(m, f), k);
192 }
193}
194
195pub broadcast proof fn lemma_insert_value_filter_different_len_not_contains<K, V>(
199 m: Map<K, V>,
200 f: spec_fn(V) -> bool,
201 k: K,
202 v: V,
203)
204 requires
205 !m.contains_key(k),
206 f(v),
207 ensures
208 #[trigger] value_filter(m.insert(k, v), f).len() == value_filter(m, f).len() + 1,
209{
210 lemma_insert_value_filter_true(m, f, k, v);
211 lemma_map_insert_len(m, k, v);
212}
213
214pub proof fn lemma_value_filter_contains_key<K, V>(m: Map<K, V>, f: spec_fn(V) -> bool, k: K)
215 requires
216 value_filter(m, f).contains_key(k),
217 ensures
218 m.contains_key(k),
219{
220}
221
222pub broadcast proof fn lemma_value_filter_choose<K, V>(m: Map<K, V>, f: spec_fn(V) -> bool)
223 requires
224 value_filter(m, f).len() != 0,
225 ensures
226 value_filter(m, f).contains_key(#[trigger] value_filter_choose(m, f)),
227 f(m[value_filter_choose(m, f)]),
228{
229 lemma_set_choose_len(value_filter(m, f).dom());
230}
231
232} verus! {
234
235pub open spec fn forall_map<K, V>(map: Map<K, V>, f: spec_fn(K, V) -> bool) -> bool {
237 forall|k| #[trigger] map.contains_key(k) ==> f(k, map[k])
238}
239
240pub open spec fn forall_map_values<K, V>(map: Map<K, V>, f: spec_fn(V) -> bool) -> bool {
242 forall|k| #[trigger] map.contains_key(k) ==> f(map[k])
243}
244
245pub broadcast group group_forall_map_lemmas {
246 lemma_forall_map_insert,
247 lemma_forall_map_values_insert,
248 lemma_forall_map_remove,
249 lemma_forall_map_values_remove,
250}
251
252pub proof fn lemma_forall_map_entry<K, V>(m: Map<K, V>, f: spec_fn(K, V) -> bool, k: K)
254 requires
255 forall_map(m, f),
256 m.contains_key(k),
257 ensures
258 f(k, m[k]),
259{
260}
261
262pub proof fn lemma_forall_map_values_entry<K, V>(m: Map<K, V>, f: spec_fn(V) -> bool, k: K)
264 requires
265 forall_map_values(m, f),
266 m.contains_key(k),
267 ensures
268 f(m[k]),
269{
270}
271
272pub broadcast proof fn lemma_forall_map_insert<K, V>(
275 m: Map<K, V>,
276 f: spec_fn(K, V) -> bool,
277 k: K,
278 v: V,
279)
280 ensures
281 #[trigger] forall_map(m.insert(k, v), f) ==> f(k, v) && if m.contains_key(k) {
282 forall_map(m.remove(k), f)
283 } else {
284 forall_map(m, f)
285 },
286{
287 assert(m.insert(k, v).contains_key(k));
288 if m.contains_key(k) {
289 assert(m.insert(k, v) == m.remove(k).insert(k, v));
290 }
291 if forall_map(m.insert(k, v), f) {
292 if !m.contains_key(k) {
293 assert(forall|k0| #[trigger] m.contains_key(k0) ==> m.insert(k, v).contains_key(k0));
294 }
295 }
296}
297
298pub broadcast proof fn lemma_forall_map_values_insert<K, V>(
301 m: Map<K, V>,
302 f: spec_fn(V) -> bool,
303 k: K,
304 v: V,
305)
306 ensures
307 #[trigger] forall_map_values(m.insert(k, v), f) ==> f(v) && if m.contains_key(k) {
308 forall_map_values(m.remove(k), f)
309 } else {
310 forall_map_values(m, f)
311 },
312{
313 assert(m.insert(k, v).contains_key(k));
314 if m.contains_key(k) {
315 assert(m.insert(k, v) == m.remove(k).insert(k, v));
316 }
317 if forall_map_values(m.insert(k, v), f) {
318 if !m.contains_key(k) {
319 assert(forall|k0| #[trigger] m.contains_key(k0) ==> m.insert(k, v).contains_key(k0));
320 }
321 }
322}
323
324pub broadcast proof fn lemma_forall_map_remove<K, V>(m: Map<K, V>, f: spec_fn(K, V) -> bool, k: K)
327 ensures
328 forall_map(m, f) <==> #[trigger] forall_map(m.remove(k), f) && (m.contains_key(k) ==> f(
329 k,
330 m[k],
331 )),
332{
333 if m.contains_key(k) {
334 assert(m == m.remove(k).insert(k, m[k]));
335 } else {
336 assert(m == m.remove(k));
337 }
338}
339
340pub broadcast proof fn lemma_forall_map_values_remove<K, V>(
343 m: Map<K, V>,
344 f: spec_fn(V) -> bool,
345 k: K,
346)
347 ensures
348 forall_map_values(m, f) <==> #[trigger] forall_map_values(m.remove(k), f) && (
349 m.contains_key(k) ==> f(m[k])),
350{
351 if m.contains_key(k) {
352 assert(m == m.remove(k).insert(k, m[k]));
353 } else {
354 assert(m == m.remove(k));
355 }
356}
357
358pub open spec fn project_first_key<K1, K2, V>(m: Map<(K1, K2), V>, k1: K1) -> Map<K2, V> {
361 Map::new(m.dom().filter(|p: (K1, K2)| p.0 == k1).map(|p: (K1, K2)| p.1), |k2: K2| m[(k1, k2)])
362}
363
364pub open spec fn project_second_key<K1, K2, V>(m: Map<(K1, K2), V>, k2: K2) -> Map<K1, V> {
367 Map::new(m.dom().filter(|p: (K1, K2)| p.1 == k2).map(|p: (K1, K2)| p.0), |k1: K1| m[(k1, k2)])
368}
369
370pub proof fn lemma_project_first_key_sound<K1, K2, V>(m: Map<(K1, K2), V>, k1: K1)
373 ensures
374 forall|k2: K2|
375 {
376 &&& #[trigger] project_first_key(m, k1).contains_key(k2) <==> m.contains_key(
377 (k1, k2),
378 )
379 &&& project_first_key(m, k1).contains_key(k2) ==> project_first_key(m, k1)[k2]
380 == m[(k1, k2)]
381 },
382{
383 assert forall|k2: K2|
384 {
385 &&& #[trigger] project_first_key(m, k1).contains_key(k2) <==> m.contains_key((k1, k2))
386 &&& project_first_key(m, k1).contains_key(k2) ==> project_first_key(m, k1)[k2] == m[(
387 k1,
388 k2,
389 )]
390 } by {
391 if m.contains_key((k1, k2)) {
392 assert(m.dom().filter(|p: (K1, K2)| p.0 == k1).contains((k1, k2)));
393 }
394 if project_first_key(m, k1).contains_key(k2) {
395 assert(m.contains_key((k1, k2)));
396 }
397 }
398}
399
400pub proof fn lemma_project_first_key_value_filter_non_empty<K1, K2, V>(
403 m: Map<(K1, K2), V>,
404 k1: K1,
405 f: spec_fn(V) -> bool,
406)
407 requires
408 value_filter(project_first_key(m, k1), f).len() != 0,
409 ensures
410 exists|k2: K2| #[trigger]
411 project_first_key(m, k1).contains_key(k2) && f(project_first_key(m, k1)[k2]),
412{
413 lemma_value_filter_choose(project_first_key(m, k1), f);
414 let k2 = value_filter_choose(project_first_key(m, k1), f);
415 assert(project_first_key(m, k1).contains_key(k2) && f(m[(k1, k2)]));
416}
417
418pub proof fn lemma_project_first_key_value_filter_empty<K1, K2, V>(
419 m: Map<(K1, K2), V>,
420 k1: K1,
421 f: spec_fn(V) -> bool,
422)
423 requires
424 value_filter(project_first_key(m, k1), f).len() == 0,
425 ensures
426 forall|k2: K2| #[trigger]
427 project_first_key(m, k1).contains_key(k2) ==> !f(project_first_key(m, k1)[k2]),
428{
429 assert forall|k2: K2| #[trigger] project_first_key(m, k1).contains_key(k2) implies !f(
430 project_first_key(m, k1)[k2],
431 ) by {
432 if f(project_first_key(m, k1)[k2]) {
433 assert(value_filter(project_first_key(m, k1), f).dom().contains(k2));
434 Set::lemma_len0_is_empty(value_filter(project_first_key(m, k1), f).dom());
435 assert(false);
436 }
437 }
438}
439
440}