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
18broadcast use group_set_lemmas;
19
20#[verifier::external_body]
53#[verifier::ext_equal]
54#[verifier::accept_recursive_types(V)]
55pub struct Multiset<V> {
56 dummy: marker::PhantomData<V>,
57}
58
59impl<V> Multiset<V> {
60 pub uninterp spec fn count(self, value: V) -> nat;
62
63 pub uninterp spec fn len(self) -> nat;
65
66 pub uninterp spec fn empty() -> Self;
68
69 pub uninterp spec fn from_map(m: Map<V, nat>) -> Self;
72
73 pub open spec fn from_set(m: Set<V>) -> Self {
74 Self::from_map(Map::new(m, |v| 1))
75 }
76
77 pub uninterp spec fn singleton(v: V) -> Self;
79
80 pub uninterp spec fn add(self, m2: Self) -> Self;
83
84 pub uninterp spec fn sub(self, m2: Self) -> Self;
92
93 pub open spec fn insert(self, v: V) -> Self {
97 self.add(Self::singleton(v))
98 }
99
100 pub open spec fn remove(self, v: V) -> Self {
104 self.sub(Self::singleton(v))
105 }
106
107 pub open spec fn update(self, v: V, mult: nat) -> Self {
109 let map = Map::new(
110 self.dom().insert(v),
111 |key: V|
112 if key == v {
113 mult
114 } else {
115 self.count(key)
116 },
117 );
118 Self::from_map(map)
119 }
120
121 pub open spec fn subset_of(self, m2: Self) -> bool {
125 forall|v: V| self.count(v) <= m2.count(v)
126 }
127
128 #[verifier::inline]
129 pub open spec fn spec_le(self, m2: Self) -> bool {
130 self.subset_of(m2)
131 }
132
133 pub uninterp spec fn filter(self, f: impl Fn(V) -> bool) -> Self;
135
136 pub open spec fn choose(self) -> V {
143 choose|v: V| self.count(v) > 0
144 }
145
146 pub open spec fn contains(self, v: V) -> bool {
148 self.count(v) > 0
149 }
150
151 #[verifier::inline]
153 pub open spec fn spec_has(self, v: V) -> bool {
154 self.contains(v)
155 }
156
157 pub open spec fn intersection_with(self, other: Self) -> Self {
161 let m = Map::<V, nat>::new(
162 self.dom(),
163 |v: V| min(self.count(v) as int, other.count(v) as int) as nat,
164 );
165 Self::from_map(m)
166 }
167
168 pub open spec fn difference_with(self, other: Self) -> Self {
171 let m = Map::<V, nat>::new(self.dom(), |v: V| clip(self.count(v) - other.count(v)));
172 Self::from_map(m)
173 }
174
175 pub open spec fn is_disjoint_from(self, other: Self) -> bool {
179 forall|x: V| self.count(x) == 0 || other.count(x) == 0
180 }
181
182 axiom fn axiom_dom_finite(self)
185 ensures
186 #[trigger] ISet::new(|v: V| self.count(v) > 0).finite(),
187 ;
188
189 pub closed spec fn dom(self) -> Set<V> {
191 Set::new(|v: V| self.count(v) > 0).unwrap()
192 }
193
194 pub broadcast proof fn dom_ensures(self)
197 ensures
198 #![trigger(self.dom())]
199 forall|v: V| #[trigger]
200 self.dom().contains(v) <==> self.count(v) > 0,
201 {
202 self.axiom_dom_finite();
203 assert forall|v: V| #[trigger] self.dom().contains(v) <==> self.count(v) > 0 by {
204 super::iset::lemma_iset_new(|vv: V| self.count(vv) > 0, v);
205 }
206 }
207}
208
209pub broadcast axiom fn axiom_multiset_empty<V>(v: V)
212 ensures
213 #[trigger] Multiset::empty().count(v) == 0,
214;
215
216pub broadcast proof fn lemma_multiset_empty_len<V>(m: Multiset<V>)
221 ensures
222 #[trigger] m.len() == 0 <==> m =~= Multiset::empty(),
223 #[trigger] m.len() > 0 ==> exists|v: V| 0 < m.count(v),
224{
225 broadcast use group_multiset_axioms;
226
227 assert(m.len() == 0 <==> m =~= Multiset::empty());
228}
229
230pub broadcast axiom fn axiom_multiset_contained<V>(m: Map<V, nat>, v: V)
234 requires
235 m.dom().contains(v),
236 ensures
237#[trigger] Multiset::from_map(m).count(v) == m[v],
240;
241
242pub broadcast axiom fn axiom_multiset_new_not_contained<V>(m: Map<V, nat>, v: V)
245 requires
246 !m.dom().contains(v),
247 ensures
248 #[trigger] Multiset::from_map(m).count(v) == 0,
249;
250
251pub broadcast proof fn lemma_from_map_dom<V>(mymap: Map<V, nat>)
252 requires
253 forall|k| #[trigger] mymap.contains_key(k) ==> mymap[k] > 0,
254 ensures
255 #[trigger] Multiset::from_map(mymap).dom() == mymap.dom(),
256{
257 broadcast use {
258 super::set::group_set_lemmas,
259 Multiset::dom_ensures,
260 axiom_multiset_contained,
261 axiom_multiset_new_not_contained,
262 };
263
264 let lhs = Multiset::from_map(mymap).dom();
265 let rhs = mymap.dom();
266 assert forall|v: V| lhs.contains(v) <==> rhs.contains(v) by {
267 if lhs.contains(v) {
268 assert(Multiset::from_map(mymap).count(v) > 0);
269 if !mymap.dom().contains(v) {
270 axiom_multiset_new_not_contained(mymap, v);
271 assert(false);
272 }
273 }
274 if rhs.contains(v) {
275 assert(mymap.dom().contains(v));
276 assert(mymap.contains_key(v));
277 axiom_multiset_contained(mymap, v);
278 assert(mymap[v] > 0);
279 assert(Multiset::from_map(mymap).count(v) > 0);
280 assert(lhs.contains(v));
281 }
282 };
283 axiom_set_ext_equal(lhs, rhs);
284}
285
286pub broadcast axiom fn axiom_multiset_singleton<V>(v: V)
290 ensures
291 (#[trigger] Multiset::singleton(v)).count(v) == 1,
292;
293
294pub broadcast axiom fn axiom_multiset_singleton_different<V>(v: V, w: V)
297 ensures
298 v != w ==> #[trigger] Multiset::singleton(v).count(w) == 0,
299;
300
301pub broadcast axiom fn axiom_multiset_add<V>(m1: Multiset<V>, m2: Multiset<V>, v: V)
305 ensures
306 #[trigger] m1.add(m2).count(v) == m1.count(v) + m2.count(v),
307;
308
309pub broadcast axiom fn axiom_multiset_sub<V>(m1: Multiset<V>, m2: Multiset<V>, v: V)
314 ensures
315 #[trigger] m1.sub(m2).count(v) == if m1.count(v) >= m2.count(v) {
316 m1.count(v) - m2.count(v)
317 } else {
318 0
319 },
320;
321
322pub broadcast axiom fn axiom_multiset_ext_equal<V>(m1: Multiset<V>, m2: Multiset<V>)
325 ensures
326 #[trigger] (m1 =~= m2) <==> (forall|v: V| m1.count(v) == m2.count(v)),
327;
328
329pub broadcast axiom fn axiom_multiset_ext_equal_deep<V>(m1: Multiset<V>, m2: Multiset<V>)
330 ensures
331 #[trigger] (m1 =~~= m2) <==> m1 =~= m2,
332;
333
334pub broadcast axiom fn axiom_len_empty<V>()
337 ensures
338 (#[trigger] Multiset::<V>::empty().len()) == 0,
339;
340
341pub broadcast axiom fn axiom_len_singleton<V>(v: V)
343 ensures
344 (#[trigger] Multiset::<V>::singleton(v).len()) == 1,
345;
346
347pub broadcast axiom fn axiom_len_add<V>(m1: Multiset<V>, m2: Multiset<V>)
349 ensures
350 (#[trigger] m1.add(m2).len()) == m1.len() + m2.len(),
351;
352
353pub broadcast axiom fn axiom_len_sub<V>(m1: Multiset<V>, m2: Multiset<V>)
356 requires
357 m2.subset_of(m1),
358 ensures
359 (#[trigger] m1.sub(m2).len()) == m1.len() - m2.len(),
360;
361
362pub broadcast axiom fn axiom_count_le_len<V>(m: Multiset<V>, v: V)
364 ensures
365 #[trigger] m.count(v) <= #[trigger] m.len(),
366;
367
368pub broadcast axiom fn axiom_filter_count<V>(m: Multiset<V>, f: spec_fn(V) -> bool, v: V)
372 ensures
373 (#[trigger] m.filter(f).count(v)) == if f(v) {
374 m.count(v)
375 } else {
376 0
377 },
378;
379
380pub broadcast axiom fn axiom_choose_count<V>(m: Multiset<V>)
384 requires
385 #[trigger] m.len() != 0,
386 ensures
387 #[trigger] m.count(m.choose()) > 0,
388;
389
390pub broadcast group group_multiset_axioms {
391 axiom_multiset_empty,
392 axiom_multiset_contained,
393 axiom_multiset_new_not_contained,
394 lemma_from_map_dom,
395 axiom_multiset_singleton,
396 axiom_multiset_singleton_different,
397 axiom_multiset_add,
398 axiom_multiset_sub,
399 axiom_multiset_ext_equal,
400 axiom_multiset_ext_equal_deep,
401 axiom_len_empty,
402 axiom_len_singleton,
403 axiom_len_add,
404 axiom_len_sub,
405 axiom_count_le_len,
406 axiom_filter_count,
407 axiom_choose_count,
408}
409
410pub broadcast proof fn lemma_update_same<V>(m: Multiset<V>, v: V, mult: nat)
414 ensures
415 #[trigger] m.update(v, mult).count(v) == mult,
416{
417 broadcast use {
418 group_set_lemmas,
419 super::map::group_map_lemmas,
420 group_multiset_axioms,
421 Multiset::dom_ensures,
422 };
423
424 reveal(Multiset::update);
425 let key_set = m.dom().insert(v);
426 let fv = |key: V|
427 if key == v {
428 mult
429 } else {
430 m.count(key)
431 };
432 let map = Map::new(key_set, fv);
433 crate::vstd::map_lib::lemma_map_new_domain(key_set, fv);
434 assert(key_set.contains(v));
435 assert(map.dom().contains(v));
436 assert(map[v] == mult);
437 axiom_multiset_contained(map, v);
438}
439
440pub broadcast proof fn lemma_update_different<V>(m: Multiset<V>, v1: V, mult: nat, v2: V)
443 requires
444 v1 != v2,
445 ensures
446 #[trigger] m.update(v1, mult).count(v2) == m.count(v2),
447{
448 broadcast use {group_set_lemmas, super::map::group_map_lemmas, group_multiset_axioms};
449 broadcast use {axiom_multiset_contained, Multiset::dom_ensures};
450
451 reveal(Multiset::update);
452 let key_set = m.dom().insert(v1);
453 let fv = |key: V|
454 if key == v1 {
455 mult
456 } else {
457 m.count(key)
458 };
459 let map = Map::new(key_set, fv);
460 crate::vstd::map_lib::lemma_map_new_domain(key_set, fv);
461 if map.dom().contains(v2) {
462 assert(map[v2] == m.count(v2));
463 axiom_multiset_contained(map, v2);
464 } else {
465 axiom_multiset_new_not_contained(map, v2);
466 assert(!m.dom().contains(v2)) by {
467 if m.dom().contains(v2) {
468 assert(key_set.contains(v2));
469 assert(map.dom().contains(v2));
470 assert(false);
471 }
472 }
473 m.dom_ensures();
474 assert(m.count(v2) == 0);
475 }
476}
477
478pub broadcast proof fn lemma_insert_containment<V>(m: Multiset<V>, x: V, y: V)
484 ensures
485 0 < #[trigger] m.insert(x).count(y) <==> x == y || 0 < m.count(y),
486{
487 broadcast use group_multiset_axioms;
488
489}
490
491pub broadcast proof fn lemma_insert_increases_count_by_1<V>(m: Multiset<V>, x: V)
494 ensures
495 #[trigger] m.insert(x).count(x) == m.count(x) + 1,
496{
497 broadcast use group_multiset_axioms;
498
499}
500
501pub broadcast proof fn lemma_insert_non_decreasing<V>(m: Multiset<V>, x: V, y: V)
506 ensures
507 0 < m.count(y) ==> 0 < #[trigger] m.insert(x).count(y),
508{
509 broadcast use group_multiset_axioms;
510
511}
512
513pub broadcast proof fn lemma_insert_other_elements_unchanged<V>(m: Multiset<V>, x: V, y: V)
516 ensures
517 x != y ==> m.count(y) == #[trigger] m.insert(x).count(y),
518{
519 broadcast use group_multiset_axioms;
520
521}
522
523pub broadcast proof fn lemma_insert_len<V>(m: Multiset<V>, x: V)
526 ensures
527 #[trigger] m.insert(x).len() == m.len() + 1,
528{
529 broadcast use group_multiset_axioms;
530
531}
532
533pub broadcast proof fn lemma_intersection_count<V>(a: Multiset<V>, b: Multiset<V>, x: V)
538 ensures
539 #[trigger] a.intersection_with(b).count(x) == min(a.count(x) as int, b.count(x) as int),
540{
541 broadcast use {group_set_lemmas, super::map::group_map_lemmas, group_multiset_axioms};
542 broadcast use {group_multiset_axioms, Multiset::dom_ensures};
543
544 let m = Map::new(a.dom(), |v: V| min(a.count(v) as int, b.count(v) as int) as nat);
545 crate::vstd::map_lib::lemma_map_new_domain(
546 a.dom(),
547 |v: V| min(a.count(v) as int, b.count(v) as int) as nat,
548 );
549 if m.dom().contains(x) {
550 assert(m[x] == min(a.count(x) as int, b.count(x) as int) as nat);
551 axiom_multiset_contained(m, x);
552 } else {
553 axiom_multiset_new_not_contained(m, x);
554 assert(!a.dom().contains(x));
555 a.dom_ensures();
556 assert(a.count(x) == 0) by {
557 if a.count(x) != 0 {
558 assert(a.count(x) > 0);
559 assert(a.dom().contains(x));
560 assert(false);
561 }
562 }
563 assert(min(a.count(x) as int, b.count(x) as int) == 0);
564 }
565}
566
567pub broadcast proof fn lemma_left_pseudo_idempotence<V>(a: Multiset<V>, b: Multiset<V>)
571 ensures
572 #[trigger] a.intersection_with(b).intersection_with(b) =~= a.intersection_with(b),
573{
574 broadcast use group_multiset_axioms;
575
576 assert forall|x: V| #[trigger]
577 a.intersection_with(b).count(x) == min(a.count(x) as int, b.count(x) as int) by {
578 lemma_intersection_count(a, b, x);
579 }
580 assert forall|x: V| #[trigger]
581 a.intersection_with(b).intersection_with(b).count(x) == min(
582 a.count(x) as int,
583 b.count(x) as int,
584 ) by {
585 lemma_intersection_count(a.intersection_with(b), b, x);
586 assert(min(min(a.count(x) as int, b.count(x) as int) as int, b.count(x) as int) == min(
587 a.count(x) as int,
588 b.count(x) as int,
589 ));
590 }
591}
592
593pub broadcast proof fn lemma_right_pseudo_idempotence<V>(a: Multiset<V>, b: Multiset<V>)
597 ensures
598 #[trigger] a.intersection_with(a.intersection_with(b)) =~= a.intersection_with(b),
599{
600 broadcast use group_multiset_axioms;
601
602 assert forall|x: V| #[trigger]
603 a.intersection_with(b).count(x) == min(a.count(x) as int, b.count(x) as int) by {
604 lemma_intersection_count(a, b, x);
605 }
606 assert forall|x: V| #[trigger]
607 a.intersection_with(a.intersection_with(b)).count(x) == min(
608 a.count(x) as int,
609 b.count(x) as int,
610 ) by {
611 lemma_intersection_count(a, a.intersection_with(b), x);
612 assert(min(a.count(x) as int, min(a.count(x) as int, b.count(x) as int) as int) == min(
613 a.count(x) as int,
614 b.count(x) as int,
615 ));
616 }
617}
618
619pub broadcast proof fn lemma_difference_count<V>(a: Multiset<V>, b: Multiset<V>, x: V)
624 ensures
625 #[trigger] a.difference_with(b).count(x) == clip(a.count(x) - b.count(x)),
626{
627 broadcast use {
628 group_set_lemmas,
629 super::map::group_map_lemmas,
630 group_multiset_axioms,
631 Multiset::dom_ensures,
632 };
633
634 let map = Map::<V, nat>::new(a.dom(), |v: V| clip(a.count(v) - b.count(v)));
635 crate::vstd::map_lib::lemma_map_new_domain(a.dom(), |v: V| clip(a.count(v) - b.count(v)));
636 if map.dom().contains(x) {
637 assert(map[x] == clip(a.count(x) - b.count(x)));
638 axiom_multiset_contained(map, x);
639 } else {
640 axiom_multiset_new_not_contained(map, x);
641 assert(!a.dom().contains(x));
642 a.dom_ensures();
643 assert(a.count(x) == 0) by {
644 if a.count(x) != 0 {
645 assert(a.count(x) > 0);
646 assert(a.dom().contains(x));
647 assert(false);
648 }
649 }
650 assert(clip(a.count(x) - b.count(x)) == 0);
651 }
652}
653
654pub broadcast proof fn lemma_difference_bottoms_out<V>(a: Multiset<V>, b: Multiset<V>, x: V)
658 ensures
659 #![trigger a.count(x), b.count(x), a.difference_with(b)]
660 a.count(x) <= b.count(x) ==> a.difference_with(b).count(x) == 0,
661{
662 broadcast use group_multiset_axioms;
663
664 lemma_difference_count(a, b, x);
665}
666
667#[macro_export]
668macro_rules! assert_multisets_equal {
669 [$($tail:tt)*] => {
670 $crate::vstd::prelude::verus_proof_macro_exprs!($crate::vstd::multiset::assert_multisets_equal_internal!($($tail)*))
671 };
672}
673
674#[macro_export]
675macro_rules! assert_multisets_equal_internal {
676 (::verus_builtin::spec_eq($m1:expr, $m2:expr)) => {
677 $crate::vstd::multiset::assert_multisets_equal_internal!($m1, $m2)
678 };
679 (::verus_builtin::spec_eq($m1:expr, $m2:expr), $k:ident $( : $t:ty )? => $bblock:block) => {
680 $crate::vstd::multiset::assert_multisets_equal_internal!($m1, $m2, $k $( : $t )? => $bblock)
681 };
682 (crate::verus_builtin::spec_eq($m1:expr, $m2:expr)) => {
683 $crate::vstd::multiset::assert_multisets_equal_internal!($m1, $m2)
684 };
685 (crate::verus_builtin::spec_eq($m1:expr, $m2:expr), $k:ident $( : $t:ty )? => $bblock:block) => {
686 $crate::vstd::multiset::assert_multisets_equal_internal!($m1, $m2, $k $( : $t )? => $bblock)
687 };
688 ($m1:expr, $m2:expr $(,)?) => {
689 $crate::vstd::multiset::assert_multisets_equal_internal!($m1, $m2, key => { })
690 };
691 ($m1:expr, $m2:expr, $k:ident $( : $t:ty )? => $bblock:block) => {
692 #[verifier::spec] let m1 = $m1;
693 #[verifier::spec] let m2 = $m2;
694 $crate::vstd::prelude::assert_by($crate::vstd::prelude::equal(m1, m2), {
695 $crate::vstd::prelude::assert_forall_by(|$k $( : $t )?| {
696 $crate::vstd::prelude::ensures([
697 $crate::vstd::prelude::equal(m1.count($k), m2.count($k))
698 ]);
699 { $bblock }
700 });
701 $crate::vstd::prelude::assert_($crate::vstd::prelude::ext_equal(m1, m2));
702 });
703 }
704}
705
706pub broadcast group group_multiset_properties {
707 lemma_update_same,
708 lemma_update_different,
709 lemma_multiset_empty_len,
710 lemma_insert_containment,
711 lemma_insert_increases_count_by_1,
712 lemma_insert_non_decreasing,
713 lemma_insert_other_elements_unchanged,
714 lemma_insert_len,
715 lemma_intersection_count,
716 lemma_left_pseudo_idempotence,
717 lemma_right_pseudo_idempotence,
718 lemma_difference_count,
719 lemma_difference_bottoms_out,
720 Multiset::dom_ensures,
721}
722
723#[doc(hidden)]
724pub use assert_multisets_equal_internal;
725pub use assert_multisets_equal;
726
727}