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 <= s
158 &&
159 pairwise_disjoint(parts) &&
161 s == parts.flatten()
163}
164
165pub proof fn lemma_flatten_cardinality_under_disjointness<A>(parts: Set<Set<A>>)
168 requires
169 pairwise_disjoint(parts),
170 ensures
171 parts.flatten().len() == parts.fold(0nat, |acc: nat, p: Set<A>| acc + p.len()),
172 decreases parts.len(),
173{
174 if parts.is_empty() {
175 assert(parts.flatten() == Set::<A>::empty());
176 assert(parts.to_iset() == ISet::empty());
177 lemma_fold_empty(0nat, |acc: nat, p: Set<A>| acc + p.len());
178 } else {
179 let p = parts.choose();
180 let rest = parts.remove(p);
181 assert(parts == rest.insert(p));
182 lemma_flatten_cardinality_under_disjointness(rest);
183 assert(rest.flatten().len() == rest.fold(0nat, |acc: nat, p: Set<A>| acc + p.len()));
184 assert(parts.flatten() == rest.flatten().union(p));
185 assert(parts.flatten().len() == rest.flatten().len() + p.len()) by {
186 lemma_set_disjoint_lens(rest.flatten(), p);
187 }
188 assert(parts.to_iset() == rest.to_iset().insert(p));
189 lemma_fold_insert(rest.to_iset(), 0nat, |acc: nat, p: Set<A>| acc + p.len(), p);
190 }
191}
192
193pub proof fn lemma_flatten_cardinality_under_disjointness_same_length<A>(parts: Set<Set<A>>, c: nat)
196 requires
197 pairwise_disjoint(parts),
198 parts.all(|p: Set<A>| p.len() == c),
199 ensures
200 parts.flatten().len() == parts.len() * c,
201 decreases parts.len(),
202{
203 if parts.is_empty() {
204 assert(parts.flatten() == Set::<A>::empty());
205 } else {
206 let p = parts.choose();
207 let rest = parts.remove(p);
208 assert(parts == rest.insert(p));
209 lemma_flatten_cardinality_under_disjointness_same_length(rest, c);
210 assert(parts.flatten() == rest.flatten().union(p));
211 assert(parts.flatten().len() == rest.flatten().len() + p.len()) by {
212 lemma_set_disjoint_lens(rest.flatten(), p);
213 }
214 assert(parts.flatten().len() == (rest.len() + 1) * c) by (nonlinear_arith)
215 requires
216 parts.flatten().len() == rest.len() * c + c,
217 ;
218 }
219}
220
221pub open spec fn set_prop_mutual_exclusion<A>(s: Set<A>, f: spec_fn(A) -> bool) -> bool {
222 forall|x: A, y: A| #[trigger]
223 s.contains(x) && #[trigger] s.contains(y) && x != y ==> !(f(x) && f(y))
224}
225
226proof fn lemma_set_prop_mutual_exclusion_internal<A>(s: Set<A>, f: spec_fn(A) -> bool)
227 requires
228 set_prop_mutual_exclusion(s, f),
229 ensures
230 s.filter(f).len() <= 1,
231 decreases s.len(),
232{
233 if s.len() == 0 {
234 assert(s.filter(f).is_empty());
235 } else {
236 let x = s.choose();
237 lemma_set_prop_mutual_exclusion_internal(s.remove(x), f);
238 if s.remove(x).filter(f).len() == 0 {
239 if f(x) {
240 assert(s.filter(f) == s.remove(x).filter(f).insert(x));
241 } else {
242 assert(s.filter(f) == s.remove(x).filter(f));
243 }
244 } else {
245 let a = s.remove(x).filter(f).choose();
246 assert(s.remove(x).filter(f).contains(a));
247 assert(s.filter(f) == s.remove(x).filter(f));
248 }
249 }
250}
251
252pub proof fn lemma_set_prop_mutual_exclusion<A>(s: Set<A>, f: spec_fn(A) -> bool)
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}