1use super::super::modes::*;
2use super::super::prelude::*;
3use super::Loc;
4use super::agree::AgreementRA;
5use super::algebra::Resource;
6use super::algebra::ResourceAlgebra;
7use super::pcm::PCM;
8use super::product::ProductRA;
9use super::storage_protocol::*;
10use super::*;
11
12verus! {
13
14broadcast use {super::super::map::group_map_axioms, super::super::set::group_set_axioms};
15
16pub enum FractionRA {
17 Frac(real),
18 Invalid,
19}
20
21impl FractionRA {
22 pub open spec fn new(f: real) -> Self
23 recommends
24 0real < f <= 1real,
25 {
26 FractionRA::Frac(f)
27 }
28
29 pub open spec fn frac(self) -> real
30 recommends
31 self is Frac,
32 {
33 self->Frac_0
34 }
35}
36
37impl ResourceAlgebra for FractionRA {
38 open spec fn valid(self) -> bool {
39 match self {
40 FractionRA::Invalid => false,
41 FractionRA::Frac(frac) => (0 as real) < frac <= (1 as real),
42 }
43 }
44
45 open spec fn op(a: Self, b: Self) -> Self {
46 match (a, b) {
47 (FractionRA::Invalid, _) => FractionRA::Invalid,
48 (_, FractionRA::Invalid) => FractionRA::Invalid,
49 (FractionRA::Frac(a_frac), FractionRA::Frac(b_frac)) => {
50 if !a.valid() || !b.valid() {
51 FractionRA::Invalid
52 } else if a_frac + b_frac <= (1 as real) {
53 FractionRA::Frac(a_frac + b_frac)
54 } else {
55 FractionRA::Invalid
56 }
57 },
58 }
59 }
60
61 proof fn valid_op(a: Self, b: Self) {
62 }
63
64 proof fn commutative(a: Self, b: Self) {
65 }
66
67 proof fn associative(a: Self, b: Self, c: Self) {
68 }
69}
70
71pub proof fn lemma_whole_fraction_has_no_frame(a: FractionRA)
72 requires
73 a == FractionRA::Frac(1 as real),
74 ensures
75 forall|b: FractionRA|
76 #![trigger FractionRA::op(a, b).valid()]
77 !FractionRA::op(a, b).valid(),
78{
79 assert forall|b: FractionRA|
80 #![trigger FractionRA::op(a, b).valid()]
81 !FractionRA::op(a, b).valid() by {
82 if FractionRA::op(a, b).valid() {
83 FractionRA::commutative(a, b);
84 FractionRA::valid_op(b, a);
85 assert(b.valid());
86 assert(b is Frac);
87 assert((0 as real) < b->Frac_0 <= (1 as real));
88 assert(a->Frac_0 + b->Frac_0 > (1 as real)); };
90 }
91}
92
93type FractionalCarrier<T> = ProductRA<FractionRA, AgreementRA<T>>;
94
95pub tracked struct FracGhost<T> {
138 r: Resource<FractionalCarrier<T>>,
139}
140
141impl<T> FracGhost<T> {
142 #[verifier::type_invariant]
143 spec fn inv(self) -> bool {
144 &&& self.r.value().left is Frac
145 &&& self.r.value().right is Agree
146 }
147
148 pub closed spec fn id(self) -> Loc {
149 self.r.loc()
150 }
151
152 pub closed spec fn view(self) -> T {
153 self.r.value().right->Agree_0
154 }
155
156 pub closed spec fn frac(self) -> real {
158 self.r.value().left->Frac_0
159 }
160
161 pub open spec fn valid(self, id: Loc, frac: real) -> bool {
162 &&& self.id() == id
163 &&& self.frac() == frac
164 }
165
166 pub proof fn new(v: T) -> (tracked result: Self)
168 ensures
169 result.frac() == 1 as real,
170 result@ == v,
171 {
172 let f = FractionalCarrier {
173 left: FractionRA::Frac(1 as real),
174 right: AgreementRA::Agree(v),
175 };
176 let tracked r = Resource::alloc(f);
177 Self { r }
178 }
179
180 pub proof fn agree(tracked self: &Self, tracked other: &Self)
182 requires
183 self.id() == other.id(),
184 ensures
185 self@ == other@,
186 {
187 use_type_invariant(self);
188 use_type_invariant(other);
189 let tracked joined = self.r.join_shared(&other.r);
190 joined.validate()
191 }
192
193 pub proof fn take(tracked &mut self) -> (tracked result: Self)
195 ensures
196 result == *old(self),
197 {
198 self.bounded();
199 let tracked mut mself = Self::dummy();
200 tracked_swap(self, &mut mself);
201 mself
202 }
203
204 pub proof fn split_to(tracked &mut self, result_frac: real) -> (tracked result: Self)
207 requires
208 (0 as real) < result_frac < old(self).frac(),
209 ensures
210 final(self).id() == old(self).id(),
211 result.id() == final(self).id(),
212 final(self)@ == old(self)@,
213 result@ == old(self)@,
214 final(self).frac() == old(self).frac() - result_frac,
215 result.frac() == result_frac,
216 {
217 self.bounded();
218 let self_frac = self.frac();
219 let tracked mut mself = Self::dummy();
220 tracked_swap(self, &mut mself);
221 use_type_invariant(&mself);
222 let tracked (r1, r2) = mself.r.split(
223 FractionalCarrier {
224 left: FractionRA::Frac(self_frac - result_frac),
225 right: AgreementRA::Agree(mself@),
226 },
227 FractionalCarrier {
228 left: FractionRA::Frac(result_frac),
229 right: AgreementRA::Agree(mself@),
230 },
231 );
232 self.r = r1;
233 Self { r: r2 }
234 }
235
236 pub proof fn split(tracked &mut self) -> (tracked result: Self)
239 ensures
240 final(self).id() == old(self).id(),
241 result.id() == final(self).id(),
242 final(self)@ == old(self)@,
243 result@ == old(self)@,
244 final(self).frac() == old(self).frac() / 2 as real,
245 result.frac() == old(self).frac() / 2 as real,
246 {
247 self.bounded();
248 self.split_to(self.frac() / 2 as real)
249 }
250
251 pub proof fn combine(tracked &mut self, tracked other: Self)
253 requires
254 old(self).id() == other.id(),
255 ensures
256 final(self).id() == old(self).id(),
257 final(self)@ == old(self)@,
258 final(self)@ == other@,
259 final(self).frac() == old(self).frac() + other.frac(),
260 {
261 self.bounded();
262 let tracked mut mself = Self::dummy();
263 tracked_swap(self, &mut mself);
264 use_type_invariant(&mself);
265 use_type_invariant(&other);
266 let tracked mut r = mself.r;
267 r.validate_2(&other.r);
268 *self = Self { r: r.join(other.r) };
269 }
270
271 pub proof fn update(tracked &mut self, v: T)
273 requires
274 old(self).frac() == (1 as real),
275 ensures
276 final(self).id() == old(self).id(),
277 final(self)@ == v,
278 final(self).frac() == old(self).frac(),
279 {
280 self.bounded();
281 let tracked mut mself = Self::dummy();
282 tracked_swap(self, &mut mself);
283 use_type_invariant(&mself);
284 let tracked mut r = mself.r;
285 let f = FractionalCarrier {
286 left: FractionRA::Frac(1 as real),
287 right: AgreementRA::Agree(v),
288 };
289 lemma_whole_fraction_has_no_frame(r.value().left);
290 *self = Self { r: r.update(f) };
291 }
292
293 pub proof fn update_with(tracked &mut self, tracked other: &mut Self, v: T)
296 requires
297 old(self).id() == old(other).id(),
298 old(self).frac() + old(other).frac() == 1 as real,
299 ensures
300 final(self).id() == old(self).id(),
301 final(other).id() == old(other).id(),
302 final(self).frac() == old(self).frac(),
303 final(other).frac() == old(other).frac(),
304 old(self)@ == old(other)@,
305 final(self)@ == v,
306 final(other)@ == v,
307 {
308 let ghost other_frac = other.frac();
309 other.bounded();
310
311 let tracked mut xother = Self::dummy();
312 tracked_swap(other, &mut xother);
313 self.bounded();
314 self.combine(xother);
315 self.update(v);
316
317 let tracked mut xother = self.split_to(other_frac);
318 tracked_swap(other, &mut xother);
319 }
320
321 pub proof fn bounded(tracked &self)
323 ensures
324 (0 as real) < self.frac() <= (1 as real),
325 {
326 use_type_invariant(self);
327 self.r.validate()
328 }
329
330 pub proof fn dummy() -> (tracked result: Self) {
333 Self::new(arbitrary())
334 }
335}
336
337}