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