1use vstd::{prelude::*, set::fold::*, set_lib::*};
3
4verus! {
5
6pub proof fn lemma_filter_all_false<T>(s: Set<T>, f: spec_fn(T) -> bool)
9 requires
10 s.all(|x: T| !f(x)),
11 ensures
12 s.filter(f).is_empty(),
13{
14}
15
16pub proof fn lemma_insert_filter_true<T>(s: Set<T>, f: spec_fn(T) -> bool, x: T)
20 requires
21 !s.contains(x),
22 f(x),
23 ensures
24 s.insert(x).filter(f) =~= s.filter(f).insert(x),
25{
26}
27
28pub proof fn lemma_insert_filter_false<T>(s: Set<T>, f: spec_fn(T) -> bool, x: T)
31 requires
32 !s.contains(x),
33 !f(x),
34 ensures
35 s.insert(x).filter(f) =~= s.filter(f),
36{
37}
38
39pub proof fn lemma_remove_filter_true<T>(s: Set<T>, f: spec_fn(T) -> bool, x: T)
43 requires
44 s.contains(x),
45 f(x),
46 ensures
47 s.remove(x).filter(f) =~= s.filter(f).remove(x),
48{
49}
50
51pub proof fn lemma_nat_range_finite(l: nat, r: nat)
53 requires
54 l <= r,
55 ensures
56 Set::new(|p: nat| l <= p < r).finite(),
57 Set::new(|p: nat| l <= p < r).len() == (r - l) as nat,
58 decreases r - l,
59{
60 if l == r {
61 assert(Set::new(|p: nat| l <= p < r) == Set::<nat>::empty());
62 } else {
63 lemma_nat_range_finite(l, (r - 1) as nat);
64 assert(Set::new(|p| l <= p < r - 1).insert((r - 1) as nat) == Set::new(
65 |p: nat| l <= p < r,
66 ));
67 }
68}
69
70pub proof fn lemma_set_separation<T>(s: Set<T>, f: spec_fn(T) -> bool)
72 requires
73 s.finite(),
74 ensures
75 #![trigger s.filter(f)]
76 s.filter(f).disjoint(s.filter(|x| !f(x))),
77 s =~= s.filter(f) + s.filter(|x| !f(x)),
78 s.filter(f).len() + s.filter(|x| !f(x)).len() == s.len(),
79 decreases s.len(),
80{
81 if s.is_empty() {
82 assert(s.filter(f) == Set::<T>::empty());
83 assert(s.filter(|x| !f(x)) == Set::<T>::empty());
84 } else {
85 let x = s.choose();
86 lemma_set_separation(s.remove(x), f);
87 if f(x) {
88 assert(s.filter(f) == s.remove(x).filter(f).insert(x));
89 assert(s.filter(|x| !f(x)) == s.remove(x).filter(|x| !f(x)));
90 } else {
91 assert(s.filter(f) == s.remove(x).filter(f));
92 assert(s.filter(|x| !f(x)) == s.remove(x).filter(|x| !f(x)).insert(x));
93 }
94 }
95}
96
97pub proof fn lemma_filter_len_unchanged_implies_equal<T>(s: Set<T>, f: spec_fn(T) -> bool)
100 requires
101 s.finite(),
102 s.filter(f).len() == s.len(),
103 ensures
104 s.filter(f) =~= s,
105{
106 lemma_set_separation(s, f)
107}
108
109pub proof fn lemma_empty_bad_set_implies_forall<T>(p: spec_fn(T) -> bool, q: spec_fn(T) -> bool)
112 requires
113 Set::new(|x: T| p(x)).filter(|x| !q(x)).is_empty(),
114 ensures
115 forall|x: T| #[trigger] p(x) ==> q(x),
116{
117 assert forall|x: T| #[trigger] p(x) implies q(x) by {
118 if !q(x) {
119 assert(Set::new(|x: T| p(x)).filter(|x| !q(x)).contains(x));
120 };
121 }
122}
123
124pub proof fn lemma_full_good_set_implies_forall<T>(p: spec_fn(T) -> bool, q: spec_fn(T) -> bool)
127 requires
128 Set::new(|x: T| p(x)).finite(),
129 Set::new(|x: T| p(x)).len() == Set::new(|x: T| p(x)).filter(q).len(),
130 ensures
131 forall|x: T| #[trigger] p(x) ==> q(x),
132{
133 lemma_set_separation(Set::new(|x: T| p(x)), q);
134 assert forall|x: T| #[trigger] p(x) implies q(x) by {
135 if !q(x) {
136 assert(Set::new(|x: T| p(x)).filter(|x| !q(x)).contains(x));
137 };
138 }
139}
140
141pub open spec fn pairwise_disjoint<A>(sets: Set<Set<A>>) -> bool {
143 forall|s1: Set<A>, s2: Set<A>|
144 #![trigger sets.contains(s1), sets.contains(s2)]
145 sets.contains(s1) && sets.contains(s2) && s1 != s2 ==> s1.disjoint(s2)
146}
147
148pub open spec fn is_partition<A>(s: Set<A>, parts: Set<Set<A>>) -> bool {
149 forall|part: Set<A>| #[trigger]
151 parts.contains(part) ==> !part.is_empty() && part <= s
152 &&
153 pairwise_disjoint(parts) &&
155 s == parts.flatten()
157}
158
159pub proof fn lemma_flatten_cardinality_under_disjointness<A>(parts: Set<Set<A>>)
162 requires
163 parts.finite(),
164 pairwise_disjoint(parts),
165 forall|p: Set<A>| #[trigger] parts.contains(p) ==> p.finite(),
166 ensures
167 parts.flatten().len() == parts.fold(0nat, |acc: nat, p: Set<A>| acc + p.len()),
168 parts.flatten().finite(),
169 decreases parts.len(),
170{
171 if parts.is_empty() {
172 assert(parts.flatten() == Set::<A>::empty());
173 lemma_fold_empty(0nat, |acc: nat, p: Set<A>| acc + p.len());
174 } else {
175 let p = parts.choose();
176 let rest = parts.remove(p);
177 assert(parts == rest.insert(p));
178 lemma_flatten_cardinality_under_disjointness(rest);
179 assert(rest.flatten().len() == rest.fold(0nat, |acc: nat, p: Set<A>| acc + p.len()));
180 assert(parts.flatten() == rest.flatten().union(p));
181 assert(parts.flatten().len() == rest.flatten().len() + p.len()) by {
182 lemma_set_disjoint_lens(rest.flatten(), p);
183 }
184 lemma_fold_insert(rest, 0nat, |acc: nat, p: Set<A>| acc + p.len(), p);
185 }
186}
187
188pub proof fn lemma_flatten_cardinality_under_disjointness_same_length<A>(parts: Set<Set<A>>, c: nat)
191 requires
192 parts.finite(),
193 pairwise_disjoint(parts),
194 parts.all(|p: Set<A>| p.finite() && p.len() == c),
195 ensures
196 parts.flatten().len() == parts.len() * c,
197 parts.flatten().finite(),
198 decreases parts.len(),
199{
200 if parts.is_empty() {
201 assert(parts.flatten() == Set::<A>::empty());
202 } else {
203 let p = parts.choose();
204 let rest = parts.remove(p);
205 assert(parts == rest.insert(p));
206 lemma_flatten_cardinality_under_disjointness_same_length(rest, c);
207 assert(parts.flatten() == rest.flatten().union(p));
208 assert(parts.flatten().len() == rest.flatten().len() + p.len()) by {
209 lemma_set_disjoint_lens(rest.flatten(), p);
210 }
211 assert(parts.flatten().len() == (rest.len() + 1) * c) by (nonlinear_arith)
212 requires
213 parts.flatten().len() == rest.len() * c + c,
214 ;
215 }
216}
217
218pub open spec fn set_prop_mutual_exclusion<A>(s: Set<A>, f: spec_fn(A) -> bool) -> bool {
219 forall|x: A, y: A| #[trigger]
220 s.contains(x) && #[trigger] s.contains(y) && x != y ==> !(f(x) && f(y))
221}
222
223proof fn lemma_set_prop_mutual_exclusion_internal<A>(s: Set<A>, f: spec_fn(A) -> bool)
224 requires
225 s.finite(),
226 set_prop_mutual_exclusion(s, f),
227 ensures
228 s.filter(f).len() <= 1,
229 decreases s.len(),
230{
231 if s.len() == 0 {
232 assert(s.filter(f).is_empty());
233 } else {
234 let x = s.choose();
235 lemma_set_prop_mutual_exclusion_internal(s.remove(x), f);
236 if s.remove(x).filter(f).len() == 0 {
237 if f(x) {
238 assert(s.filter(f) == s.remove(x).filter(f).insert(x));
239 } else {
240 assert(s.filter(f) == s.remove(x).filter(f));
241 }
242 } else {
243 let a = s.remove(x).filter(f).choose();
244 assert(s.remove(x).filter(f).contains(a));
245 assert(s.filter(f) == s.remove(x).filter(f));
246 }
247 }
248}
249
250pub proof fn lemma_set_prop_mutual_exclusion<A>(s: Set<A>, f: spec_fn(A) -> bool)
251 requires
252 s.finite(),
253 ensures
254 set_prop_mutual_exclusion(s, f) <==> s.filter(f).len() <= 1,
255{
256 if set_prop_mutual_exclusion(s, f) {
257 lemma_set_prop_mutual_exclusion_internal(s, f);
258 }
259 if s.filter(f).len() <= 1 {
260 assert forall|x: A, y: A| #[trigger]
261 s.contains(x) && #[trigger] s.contains(y) && x != y implies !(f(x) && f(y)) by {
262 if f(x) && f(y) {
263 assert(s.filter(f).contains(x));
264 assert(s.filter(f).contains(y));
265 if s.filter(f).len() == 1 {
266 Set::lemma_is_singleton(s.filter(f));
267 }
268 }
269 };
270 }
271}
272
273}