1use core::marker;
2
3#[allow(unused_imports)]
4use super::map::*;
5#[cfg(verus_keep_ghost)]
6use super::math::clip;
7#[cfg(verus_keep_ghost)]
8use super::math::min;
9#[allow(unused_imports)]
10use super::pervasive::*;
11#[allow(unused_imports)]
12use super::prelude::*;
13#[allow(unused_imports)]
14use super::set::*;
15
16verus! {
17
18#[verifier::external_body]
44#[verifier::ext_equal]
45#[verifier::accept_recursive_types(V)]
46pub struct Multiset<V> {
47 dummy: marker::PhantomData<V>,
48}
49
50impl<V> Multiset<V> {
51 pub uninterp spec fn count(self, value: V) -> nat;
53
54 pub uninterp spec fn len(self) -> nat;
56
57 pub uninterp spec fn empty() -> Self;
59
60 pub uninterp spec fn from_map(m: Map<V, nat>) -> Self;
64
65 pub open spec fn from_set(m: Set<V>) -> Self {
66 Self::from_map(Map::new(|k| m.contains(k), |v| 1))
67 }
68
69 pub uninterp spec fn singleton(v: V) -> Self;
71
72 pub uninterp spec fn add(self, m2: Self) -> Self;
75
76 pub uninterp spec fn sub(self, m2: Self) -> Self;
84
85 pub open spec fn insert(self, v: V) -> Self {
89 self.add(Self::singleton(v))
90 }
91
92 pub open spec fn remove(self, v: V) -> Self {
96 self.sub(Self::singleton(v))
97 }
98
99 pub open spec fn update(self, v: V, mult: nat) -> Self {
101 let map = Map::new(
102 |key: V| (self.contains(key) || key == v),
103 |key: V|
104 if key == v {
105 mult
106 } else {
107 self.count(key)
108 },
109 );
110 Self::from_map(map)
111 }
112
113 pub open spec fn subset_of(self, m2: Self) -> bool {
117 forall|v: V| self.count(v) <= m2.count(v)
118 }
119
120 #[verifier::inline]
121 pub open spec fn spec_le(self, m2: Self) -> bool {
122 self.subset_of(m2)
123 }
124
125 pub uninterp spec fn filter(self, f: impl Fn(V) -> bool) -> Self;
127
128 pub open spec fn choose(self) -> V {
135 choose|v: V| self.count(v) > 0
136 }
137
138 pub open spec fn contains(self, v: V) -> bool {
140 self.count(v) > 0
141 }
142
143 #[verifier::inline]
145 pub open spec fn spec_has(self, v: V) -> bool {
146 self.contains(v)
147 }
148
149 pub open spec fn intersection_with(self, other: Self) -> Self {
153 let m = Map::<V, nat>::new(
154 |v: V| self.contains(v),
155 |v: V| min(self.count(v) as int, other.count(v) as int) as nat,
156 );
157 Self::from_map(m)
158 }
159
160 pub open spec fn difference_with(self, other: Self) -> Self {
163 let m = Map::<V, nat>::new(
164 |v: V| self.contains(v),
165 |v: V| clip(self.count(v) - other.count(v)),
166 );
167 Self::from_map(m)
168 }
169
170 pub open spec fn is_disjoint_from(self, other: Self) -> bool {
174 forall|x: V| self.count(x) == 0 || other.count(x) == 0
175 }
176
177 pub open spec fn dom(self) -> Set<V> {
179 Set::new(|v: V| self.count(v) > 0)
180 }
181}
182
183pub broadcast axiom fn axiom_multiset_empty<V>(v: V)
186 ensures
187 #[trigger] Multiset::empty().count(v) == 0,
188;
189
190pub broadcast proof fn lemma_multiset_empty_len<V>(m: Multiset<V>)
195 ensures
196 #[trigger] m.len() == 0 <==> m =~= Multiset::empty(),
197 #[trigger] m.len() > 0 ==> exists|v: V| 0 < m.count(v),
198{
199 broadcast use group_multiset_axioms;
200
201 assert(m.len() == 0 <==> m =~= Multiset::empty());
202}
203
204pub broadcast axiom fn axiom_multiset_contained<V>(m: Map<V, nat>, v: V)
208 requires
209 m.dom().finite(),
210 m.dom().contains(v),
211 ensures
212 #[trigger] Multiset::from_map(m).count(v) == m[v],
213;
214
215pub broadcast axiom fn axiom_multiset_new_not_contained<V>(m: Map<V, nat>, v: V)
218 requires
219 m.dom().finite(),
220 !m.dom().contains(v),
221 ensures
222 #[trigger] Multiset::from_map(m).count(v) == 0,
223;
224
225pub broadcast axiom fn axiom_multiset_singleton<V>(v: V)
229 ensures
230 (#[trigger] Multiset::singleton(v)).count(v) == 1,
231;
232
233pub broadcast axiom fn axiom_multiset_singleton_different<V>(v: V, w: V)
236 ensures
237 v != w ==> #[trigger] Multiset::singleton(v).count(w) == 0,
238;
239
240pub broadcast axiom fn axiom_multiset_add<V>(m1: Multiset<V>, m2: Multiset<V>, v: V)
244 ensures
245 #[trigger] m1.add(m2).count(v) == m1.count(v) + m2.count(v),
246;
247
248pub broadcast axiom fn axiom_multiset_sub<V>(m1: Multiset<V>, m2: Multiset<V>, v: V)
253 ensures
254 #[trigger] m1.sub(m2).count(v) == if m1.count(v) >= m2.count(v) {
255 m1.count(v) - m2.count(v)
256 } else {
257 0
258 },
259;
260
261pub broadcast axiom fn axiom_multiset_ext_equal<V>(m1: Multiset<V>, m2: Multiset<V>)
264 ensures
265 #[trigger] (m1 =~= m2) <==> (forall|v: V| m1.count(v) == m2.count(v)),
266;
267
268pub broadcast axiom fn axiom_multiset_ext_equal_deep<V>(m1: Multiset<V>, m2: Multiset<V>)
269 ensures
270 #[trigger] (m1 =~~= m2) <==> m1 =~= m2,
271;
272
273pub broadcast axiom fn axiom_len_empty<V>()
276 ensures
277 (#[trigger] Multiset::<V>::empty().len()) == 0,
278;
279
280pub broadcast axiom fn axiom_len_singleton<V>(v: V)
282 ensures
283 (#[trigger] Multiset::<V>::singleton(v).len()) == 1,
284;
285
286pub broadcast axiom fn axiom_len_add<V>(m1: Multiset<V>, m2: Multiset<V>)
288 ensures
289 (#[trigger] m1.add(m2).len()) == m1.len() + m2.len(),
290;
291
292pub broadcast axiom fn axiom_len_sub<V>(m1: Multiset<V>, m2: Multiset<V>)
295 requires
296 m2.subset_of(m1),
297 ensures
298 (#[trigger] m1.sub(m2).len()) == m1.len() - m2.len(),
299;
300
301pub broadcast axiom fn axiom_count_le_len<V>(m: Multiset<V>, v: V)
303 ensures
304 #[trigger] m.count(v) <= #[trigger] m.len(),
305;
306
307pub broadcast axiom fn axiom_filter_count<V>(m: Multiset<V>, f: spec_fn(V) -> bool, v: V)
311 ensures
312 (#[trigger] m.filter(f).count(v)) == if f(v) {
313 m.count(v)
314 } else {
315 0
316 },
317;
318
319pub broadcast axiom fn axiom_choose_count<V>(m: Multiset<V>)
323 requires
324 #[trigger] m.len() != 0,
325 ensures
326 #[trigger] m.count(m.choose()) > 0,
327;
328
329pub broadcast axiom fn axiom_multiset_always_finite<V>(m: Multiset<V>)
334 ensures
335 #[trigger] m.dom().finite(),
336;
337
338pub broadcast group group_multiset_axioms {
339 axiom_multiset_empty,
340 axiom_multiset_contained,
341 axiom_multiset_new_not_contained,
342 axiom_multiset_singleton,
343 axiom_multiset_singleton_different,
344 axiom_multiset_add,
345 axiom_multiset_sub,
346 axiom_multiset_ext_equal,
347 axiom_multiset_ext_equal_deep,
348 axiom_len_empty,
349 axiom_len_singleton,
350 axiom_len_add,
351 axiom_len_sub,
352 axiom_count_le_len,
353 axiom_filter_count,
354 axiom_choose_count,
355 axiom_multiset_always_finite,
356}
357
358pub broadcast proof fn lemma_update_same<V>(m: Multiset<V>, v: V, mult: nat)
362 ensures
363 #[trigger] m.update(v, mult).count(v) == mult,
364{
365 broadcast use {group_set_axioms, group_map_axioms, group_multiset_axioms};
366
367 let map = Map::new(
368 |key: V| (m.contains(key) || key == v),
369 |key: V|
370 if key == v {
371 mult
372 } else {
373 m.count(key)
374 },
375 );
376 assert(map.dom() =~= m.dom().insert(v));
377}
378
379pub broadcast proof fn lemma_update_different<V>(m: Multiset<V>, v1: V, mult: nat, v2: V)
382 requires
383 v1 != v2,
384 ensures
385 #[trigger] m.update(v1, mult).count(v2) == m.count(v2),
386{
387 broadcast use {group_set_axioms, group_map_axioms, group_multiset_axioms};
388
389 let map = Map::new(
390 |key: V| (m.contains(key) || key == v1),
391 |key: V|
392 if key == v1 {
393 mult
394 } else {
395 m.count(key)
396 },
397 );
398 assert(map.dom() =~= m.dom().insert(v1));
399}
400
401pub broadcast proof fn lemma_insert_containment<V>(m: Multiset<V>, x: V, y: V)
407 ensures
408 0 < #[trigger] m.insert(x).count(y) <==> x == y || 0 < m.count(y),
409{
410 broadcast use group_multiset_axioms;
411
412}
413
414pub broadcast proof fn lemma_insert_increases_count_by_1<V>(m: Multiset<V>, x: V)
417 ensures
418 #[trigger] m.insert(x).count(x) == m.count(x) + 1,
419{
420 broadcast use group_multiset_axioms;
421
422}
423
424pub broadcast proof fn lemma_insert_non_decreasing<V>(m: Multiset<V>, x: V, y: V)
429 ensures
430 0 < m.count(y) ==> 0 < #[trigger] m.insert(x).count(y),
431{
432 broadcast use group_multiset_axioms;
433
434}
435
436pub broadcast proof fn lemma_insert_other_elements_unchanged<V>(m: Multiset<V>, x: V, y: V)
439 ensures
440 x != y ==> m.count(y) == #[trigger] m.insert(x).count(y),
441{
442 broadcast use group_multiset_axioms;
443
444}
445
446pub broadcast proof fn lemma_insert_len<V>(m: Multiset<V>, x: V)
449 ensures
450 #[trigger] m.insert(x).len() == m.len() + 1,
451{
452 broadcast use group_multiset_axioms;
453
454}
455
456pub broadcast proof fn lemma_intersection_count<V>(a: Multiset<V>, b: Multiset<V>, x: V)
461 ensures
462 #[trigger] a.intersection_with(b).count(x) == min(a.count(x) as int, b.count(x) as int),
463{
464 broadcast use {group_set_axioms, group_map_axioms, group_multiset_axioms};
465
466 let m = Map::<V, nat>::new(
467 |v: V| a.contains(v),
468 |v: V| min(a.count(v) as int, b.count(v) as int) as nat,
469 );
470 assert(m.dom() =~= a.dom());
471}
472
473pub broadcast proof fn lemma_left_pseudo_idempotence<V>(a: Multiset<V>, b: Multiset<V>)
477 ensures
478 #[trigger] a.intersection_with(b).intersection_with(b) =~= a.intersection_with(b),
479{
480 broadcast use group_multiset_axioms;
481
482 assert forall|x: V| #[trigger]
483 a.intersection_with(b).count(x) == min(a.count(x) as int, b.count(x) as int) by {
484 lemma_intersection_count(a, b, x);
485 }
486 assert forall|x: V| #[trigger]
487 a.intersection_with(b).intersection_with(b).count(x) == min(
488 a.count(x) as int,
489 b.count(x) as int,
490 ) by {
491 lemma_intersection_count(a.intersection_with(b), b, x);
492 assert(min(min(a.count(x) as int, b.count(x) as int) as int, b.count(x) as int) == min(
493 a.count(x) as int,
494 b.count(x) as int,
495 ));
496 }
497}
498
499pub broadcast proof fn lemma_right_pseudo_idempotence<V>(a: Multiset<V>, b: Multiset<V>)
503 ensures
504 #[trigger] a.intersection_with(a.intersection_with(b)) =~= a.intersection_with(b),
505{
506 broadcast use group_multiset_axioms;
507
508 assert forall|x: V| #[trigger]
509 a.intersection_with(b).count(x) == min(a.count(x) as int, b.count(x) as int) by {
510 lemma_intersection_count(a, b, x);
511 }
512 assert forall|x: V| #[trigger]
513 a.intersection_with(a.intersection_with(b)).count(x) == min(
514 a.count(x) as int,
515 b.count(x) as int,
516 ) by {
517 lemma_intersection_count(a, a.intersection_with(b), x);
518 assert(min(a.count(x) as int, min(a.count(x) as int, b.count(x) as int) as int) == min(
519 a.count(x) as int,
520 b.count(x) as int,
521 ));
522 }
523}
524
525pub broadcast proof fn lemma_difference_count<V>(a: Multiset<V>, b: Multiset<V>, x: V)
530 ensures
531 #[trigger] a.difference_with(b).count(x) == clip(a.count(x) - b.count(x)),
532{
533 broadcast use {group_set_axioms, group_map_axioms, group_multiset_axioms};
534
535 let m = Map::<V, nat>::new(|v: V| a.contains(v), |v: V| clip(a.count(v) - b.count(v)));
536 assert(m.dom() =~= a.dom());
537}
538
539pub broadcast proof fn lemma_difference_bottoms_out<V>(a: Multiset<V>, b: Multiset<V>, x: V)
543 ensures
544 #![trigger a.count(x), b.count(x), a.difference_with(b)]
545 a.count(x) <= b.count(x) ==> a.difference_with(b).count(x) == 0,
546{
547 broadcast use group_multiset_axioms;
548
549 lemma_difference_count(a, b, x);
550}
551
552#[macro_export]
553macro_rules! assert_multisets_equal {
554 [$($tail:tt)*] => {
555 ::builtin_macros::verus_proof_macro_exprs!($crate::vstd::multiset::assert_multisets_equal_internal!($($tail)*))
556 };
557}
558
559#[macro_export]
560macro_rules! assert_multisets_equal_internal {
561 (::builtin::spec_eq($m1:expr, $m2:expr)) => {
562 $crate::vstd::multiset::assert_multisets_equal_internal!($m1, $m2)
563 };
564 (::builtin::spec_eq($m1:expr, $m2:expr), $k:ident $( : $t:ty )? => $bblock:block) => {
565 $crate::vstd::multiset::assert_multisets_equal_internal!($m1, $m2, $k $( : $t )? => $bblock)
566 };
567 (crate::builtin::spec_eq($m1:expr, $m2:expr)) => {
568 $crate::vstd::multiset::assert_multisets_equal_internal!($m1, $m2)
569 };
570 (crate::builtin::spec_eq($m1:expr, $m2:expr), $k:ident $( : $t:ty )? => $bblock:block) => {
571 $crate::vstd::multiset::assert_multisets_equal_internal!($m1, $m2, $k $( : $t )? => $bblock)
572 };
573 ($m1:expr, $m2:expr $(,)?) => {
574 $crate::vstd::multiset::assert_multisets_equal_internal!($m1, $m2, key => { })
575 };
576 ($m1:expr, $m2:expr, $k:ident $( : $t:ty )? => $bblock:block) => {
577 #[verifier::spec] let m1 = $m1;
578 #[verifier::spec] let m2 = $m2;
579 $crate::vstd::prelude::assert_by($crate::vstd::prelude::equal(m1, m2), {
580 $crate::vstd::prelude::assert_forall_by(|$k $( : $t )?| {
581 $crate::vstd::prelude::ensures([
582 $crate::vstd::prelude::equal(m1.count($k), m2.count($k))
583 ]);
584 { $bblock }
585 });
586 $crate::vstd::prelude::assert_($crate::vstd::prelude::ext_equal(m1, m2));
587 });
588 }
589}
590
591#[deprecated = "Use `broadcast use group_multiset_properties` instead" ]
593pub proof fn lemma_multiset_properties<V>()
594 ensures
595 forall|m: Multiset<V>, v: V, mult: nat| #[trigger] m.update(v, mult).count(v) == mult, forall|m: Multiset<V>, v1: V, mult: nat, v2: V|
597 v1 != v2 ==> #[trigger] m.update(v1, mult).count(v2) == m.count(v2), forall|m: Multiset<V>|
599 (#[trigger] m.len() == 0 <==> m =~= Multiset::empty()) && (#[trigger] m.len() > 0
600 ==> exists|v: V| 0 < m.count(v)), forall|m: Multiset<V>, x: V, y: V|
602 0 < #[trigger] m.insert(x).count(y) <==> x == y || 0 < m.count(y), forall|m: Multiset<V>, x: V| #[trigger] m.insert(x).count(x) == m.count(x) + 1, forall|m: Multiset<V>, x: V, y: V| 0 < m.count(y) ==> 0 < #[trigger] m.insert(x).count(y), forall|m: Multiset<V>, x: V, y: V|
606 x != y ==> #[trigger] m.count(y) == #[trigger] m.insert(x).count(y), forall|m: Multiset<V>, x: V| #[trigger] m.insert(x).len() == m.len() + 1, forall|a: Multiset<V>, b: Multiset<V>, x: V| #[trigger]
609 a.intersection_with(b).count(x) == min(a.count(x) as int, b.count(x) as int), forall|a: Multiset<V>, b: Multiset<V>| #[trigger]
611 a.intersection_with(b).intersection_with(b) == a.intersection_with(b), forall|a: Multiset<V>, b: Multiset<V>| #[trigger]
613 a.intersection_with(a.intersection_with(b)) == a.intersection_with(b), forall|a: Multiset<V>, b: Multiset<V>, x: V| #[trigger]
615 a.difference_with(b).count(x) == clip(a.count(x) - b.count(x)), forall|a: Multiset<V>, b: Multiset<V>, x: V| #[trigger]
617 a.count(x) <= #[trigger] b.count(x) ==> (#[trigger] a.difference_with(b)).count(x)
618 == 0, {
620 broadcast use {group_multiset_axioms, group_multiset_properties};
621
622}
623
624pub broadcast group group_multiset_properties {
625 lemma_update_same,
626 lemma_update_different,
627 lemma_insert_containment,
628 lemma_insert_increases_count_by_1,
629 lemma_insert_non_decreasing,
630 lemma_insert_other_elements_unchanged,
631 lemma_insert_len,
632 lemma_intersection_count,
633 lemma_left_pseudo_idempotence,
634 lemma_right_pseudo_idempotence,
635 lemma_difference_count,
636 lemma_difference_bottoms_out,
637}
638
639#[doc(hidden)]
640pub use assert_multisets_equal_internal;
641pub use assert_multisets_equal;
642
643}