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