vstd/contrib/exec_spec/
multiset.rs1use crate::contrib::exec_spec::*;
3use crate::prelude::*;
4use std::collections::HashMap;
5
6verus! {
7
8broadcast use {
12 crate::group_vstd_default,
13 crate::std_specs::hash::group_hash_axioms,
14 crate::std_specs::hash::lemma_hashmap_deepview_dom,
15};
16
17#[derive(Eq, Debug)]
19pub struct ExecMultiset<T: std::hash::Hash + std::cmp::Eq> {
20 pub m: HashMap<T, usize>,
21}
22
23impl<T: std::hash::Hash + std::cmp::Eq> PartialEq for ExecMultiset<T> {
25 #[verifier::external_body]
26 fn eq(&self, other: &Self) -> bool {
27 let count = |m: &HashMap<T, usize>, k: &T| m.get(k).copied().unwrap_or(0);
28 self.m.iter().all(|(k, v)| count(&other.m, k) == *v) && other.m.iter().all(
29 |(k, v)| count(&self.m, k) == *v,
30 )
31 }
32}
33
34#[cfg(verus_keep_ghost)]
35impl<
36 T: ObeysDeepEq + std::hash::Hash + std::cmp::Eq,
37> crate::std_specs::cmp::PartialEqSpecImpl for ExecMultiset<T> {
38 open spec fn obeys_eq_spec() -> bool {
39 true
40 }
41
42 open spec fn eq_spec(&self, other: &Self) -> bool {
43 self.deep_view() == other.deep_view()
44 }
45}
46
47impl<T: ObeysDeepEq + std::hash::Hash + std::cmp::Eq> ObeysDeepEq for ExecMultiset<T> {
48 proof fn lemma_obeys_deep_eq() {
49 reveal(crate::laws_eq::obeys_deep_eq);
50 }
51}
52
53impl<T: DeepView + std::hash::Hash + std::cmp::Eq> DeepView for ExecMultiset<T> {
62 type V = Multiset<<T as DeepView>::V>;
63
64 open spec fn deep_view(&self) -> Self::V {
65 Multiset::from_map(self.m.deep_view().map_values(|v| v as nat))
66 }
67}
68
69impl<'a, T: ObeysDeepEq + DeepViewClone + std::hash::Hash + std::cmp::Eq> ToRef<
70 &'a ExecMultiset<T>,
71> for &'a ExecMultiset<T> {
72 #[inline(always)]
73 fn get_ref(self) -> &'a ExecMultiset<T> {
74 &self
75 }
76}
77
78impl<'a, T: ObeysDeepEq + DeepViewClone + std::hash::Hash + std::cmp::Eq> ToOwned<
79 ExecMultiset<T>,
80> for &'a ExecMultiset<T> {
81 #[verifier::external_body]
82 #[inline(always)]
83 fn get_owned(self) -> ExecMultiset<T> {
84 let mut new_map = HashMap::new();
85 for (k, v) in self.m.iter() {
86 new_map.insert(k.deep_clone(), v.deep_clone());
87 }
88 ExecMultiset { m: new_map }
89 }
90}
91
92impl<
93 T: ObeysDeepEq + DeepViewClone + std::hash::Hash + std::cmp::Eq,
94> DeepViewClone for ExecMultiset<T> {
95 #[verifier::external_body]
96 #[inline(always)]
97 fn deep_clone(&self) -> Self {
98 let mut new_map = HashMap::new();
99 for (k, v) in self.m.iter() {
100 new_map.insert(k.deep_clone(), v.deep_clone());
101 }
102 ExecMultiset { m: new_map }
103 }
104}
105
106impl<
107 'a,
108 T: ObeysDeepEq + DeepViewClone + std::hash::Hash + std::cmp::Eq,
109> ExecSpecLen for &'a ExecMultiset<T> {
110 #[inline(always)]
111 #[verifier::external_body]
112 fn exec_len(self) -> (res: usize)
113 ensures
114 res == self.deep_view().len(),
115 {
116 let mut len = 0;
117 for (_, v) in self.m.iter() {
118 len = len + v;
119 }
120 len
121 }
122}
123
124pub trait ExecSpecMultisetCount: Sized + DeepView {
129 type Elem;
130
131 fn exec_count(self, value: Self::Elem) -> usize;
132}
133
134pub trait ExecSpecMultisetEmpty: Sized {
136 fn exec_empty() -> Self;
137}
138
139pub trait ExecSpecMultisetSingleton: Sized {
141 type Elem;
142
143 fn exec_singleton(v: Self::Elem) -> Self;
144}
145
146pub trait ExecSpecMultisetAdd<'a, Out: Sized + DeepView>: Sized + DeepView + ToOwned<Out> {
148 fn exec_add(self, m2: Self) -> Out;
149}
150
151pub trait ExecSpecMultisetSub<'a, Out: Sized + DeepView>: Sized + DeepView + ToOwned<Out> {
153 fn exec_sub(self, m2: Self) -> Out;
154}
155
156impl<
160 'a,
161 T: ObeysDeepEq + DeepViewClone + std::hash::Hash + std::cmp::Eq,
162> ExecSpecMultisetCount for &'a ExecMultiset<T> {
163 type Elem = T;
164
165 #[inline(always)]
166 #[verifier::external_body]
167 fn exec_count(self, value: Self::Elem) -> (res: usize)
168 ensures
169 res == self.deep_view().count(value.deep_view()),
170 {
171 match self.m.get(&value) {
172 Some(v) => v.deep_clone(),
173 None => 0,
174 }
175 }
176}
177
178impl<T: ObeysDeepEq + std::hash::Hash + std::cmp::Eq> ExecSpecMultisetEmpty for ExecMultiset<T> {
179 #[verifier::external_body]
180 #[inline(always)]
181 fn exec_empty() -> (res: Self)
182 ensures
183 res.deep_view() =~= Multiset::empty(),
184 {
185 ExecMultiset { m: HashMap::new() }
186 }
187}
188
189impl<
190 T: ObeysDeepEq + DeepViewClone + std::hash::Hash + std::cmp::Eq,
191> ExecSpecMultisetSingleton for ExecMultiset<T> {
192 type Elem = T;
193
194 #[verifier::external_body]
195 #[inline(always)]
196 fn exec_singleton(v: Self::Elem) -> (res: Self)
197 ensures
198 res.deep_view() =~= Multiset::singleton(v.deep_view()),
199 {
200 let mut m = HashMap::new();
201 m.insert(v.deep_clone(), 1);
202 ExecMultiset { m }
203 }
204}
205
206impl<'a, T> ExecSpecMultisetAdd<'a, ExecMultiset<T>> for &'a ExecMultiset<T> where
207 T: ObeysDeepEq + DeepViewClone + std::hash::Hash + std::cmp::Eq,
208 {
209 #[verifier::external_body]
210 #[inline(always)]
211 fn exec_add(self, m2: Self) -> (res: ExecMultiset<T>)
212 ensures
213 res.deep_view() =~= self.deep_view().add(m2.deep_view()),
214 {
215 let mut add = self.deep_clone();
216 for (k, v) in m2.m.iter() {
217 if !add.m.contains_key(k) {
218 add.m.insert(k.deep_clone(), v.deep_clone());
219 } else {
220 let new_count = add.m.get(k).unwrap() + v;
221 add.m.insert(k.deep_clone(), new_count);
222 }
223 }
224 add
225 }
226}
227
228impl<'a, T> ExecSpecMultisetSub<'a, ExecMultiset<T>> for &'a ExecMultiset<T> where
229 T: ObeysDeepEq + DeepViewClone + std::hash::Hash + std::cmp::Eq,
230 {
231 #[verifier::external_body]
232 #[inline(always)]
233 fn exec_sub(self, m2: Self) -> (res: ExecMultiset<T>)
234 ensures
235 res.deep_view() =~= self.deep_view().sub(m2.deep_view()),
236 {
237 let mut sub = HashMap::new();
238 for (k, v) in self.m.iter() {
239 if m2.m.contains_key(k) {
240 let v2 = m2.m.get(k).unwrap();
241 if v2 < v {
242 sub.insert(k.deep_clone(), v.deep_clone() - v2);
243 }
244 } else {
245 sub.insert(k.deep_clone(), v.deep_clone());
246 }
247 }
248 ExecMultiset { m: sub }
249 }
250}
251
252}