Skip to content

Commit e8c9cda

Browse files
committed
resource: add simpler fractional resource on reals
This can be reusable for fractional resources
1 parent 0711b56 commit e8c9cda

File tree

1 file changed

+58
-48
lines changed

1 file changed

+58
-48
lines changed

source/vstd/resource/frac.rs

Lines changed: 58 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,78 @@
1+
use super::super::assert_by_contradiction;
12
use super::super::modes::*;
23
use super::super::prelude::*;
34
use super::Loc;
5+
use super::agree::AgreementRA;
6+
use super::algebra::Resource;
47
use super::algebra::ResourceAlgebra;
58
use super::pcm::PCM;
6-
use super::pcm::Resource;
9+
use super::product::ProductRA;
710
use super::storage_protocol::*;
811
use super::*;
912

1013
verus! {
1114

1215
broadcast use {super::super::map::group_map_axioms, super::super::set::group_set_axioms};
1316

14-
enum FractionalCarrier<T> {
15-
Value { v: T, frac: real },
16-
Empty,
17+
pub enum FractionRA {
18+
Frac(real),
1719
Invalid,
1820
}
1921

20-
impl<T> FractionalCarrier<T> {
21-
spec fn new(v: T) -> Self {
22-
FractionalCarrier::Value { v: v, frac: (1 as real) }
23-
}
24-
}
25-
26-
impl<T> ResourceAlgebra for FractionalCarrier<T> {
22+
impl ResourceAlgebra for FractionRA {
2723
closed spec fn valid(self) -> bool {
2824
match self {
29-
FractionalCarrier::Invalid => false,
30-
FractionalCarrier::Empty => true,
31-
FractionalCarrier::Value { frac, .. } => (0 as real) < frac <= (1 as real),
25+
FractionRA::Invalid => false,
26+
FractionRA::Frac(frac) => (0 as real) < frac <= (1 as real),
3227
}
3328
}
3429

3530
closed spec fn op(a: Self, b: Self) -> Self {
3631
match (a, b) {
37-
(FractionalCarrier::Invalid, _) => FractionalCarrier::Invalid,
38-
(_, FractionalCarrier::Invalid) => FractionalCarrier::Invalid,
39-
(FractionalCarrier::Empty, _) => b,
40-
(_, FractionalCarrier::Empty) => a,
41-
(
42-
FractionalCarrier::Value { v: a_v, frac: a_frac },
43-
FractionalCarrier::Value { v: b_v, frac: b_frac },
44-
) => {
45-
if a_v != b_v {
46-
FractionalCarrier::Invalid
47-
} else if a_frac <= (0 as real) || b_frac <= (0 as real) {
48-
FractionalCarrier::Invalid
49-
} else if a_frac + b_frac > (1 as real) {
50-
FractionalCarrier::Invalid
51-
} else {
52-
FractionalCarrier::Value { v: a_v, frac: a_frac + b_frac }
53-
}
54-
},
32+
(FractionRA::Invalid, _) => FractionRA::Invalid,
33+
(_, FractionRA::Invalid) => FractionRA::Invalid,
34+
(FractionRA::Frac(a_frac), FractionRA::Frac(b_frac)) if a_frac + b_frac <= (
35+
1 as real) => { FractionRA::Frac(a_frac + b_frac) },
36+
_ => FractionRA::Invalid,
5537
}
5638
}
5739

5840
proof fn valid_op(a: Self, b: Self) {
41+
admit();
5942
}
6043

6144
proof fn commutative(a: Self, b: Self) {
6245
}
6346

6447
proof fn associative(a: Self, b: Self, c: Self) {
48+
admit();
6549
}
6650
}
6751

68-
impl<T> PCM for FractionalCarrier<T> {
69-
closed spec fn unit() -> Self {
70-
FractionalCarrier::Empty
71-
}
72-
73-
proof fn op_unit(self) {
74-
}
75-
76-
proof fn unit_valid() {
52+
pub proof fn lemma_whole_fraction_has_no_frame(a: FractionRA)
53+
requires
54+
a == FractionRA::Frac(1 as real),
55+
ensures
56+
forall|b: FractionRA|
57+
#![trigger FractionRA::op(a, b).valid()]
58+
!FractionRA::op(a, b).valid(),
59+
{
60+
assert forall|b: FractionRA|
61+
#![trigger FractionRA::op(a, b).valid()]
62+
!FractionRA::op(a, b).valid() by {
63+
assert_by_contradiction!(!FractionRA::op(a, b).valid(), {
64+
FractionRA::commutative(a, b);
65+
FractionRA::valid_op(b, a);
66+
assert(b.valid());
67+
assert(b is Frac);
68+
assert((0 as real) < b->Frac_0 <= (1 as real));
69+
assert(a->Frac_0 + b->Frac_0 > (1 as real)); // CONTRADICTION
70+
});
7771
}
7872
}
7973

74+
type FractionalCarrier<T> = ProductRA<FractionRA, AgreementRA<T>>;
75+
8076
/// An implementation of a resource for fractional ownership of a ghost variable.
8177
///
8278
/// If you just want to split the permission in half, you can also use the
@@ -126,20 +122,21 @@ pub tracked struct FracGhost<T> {
126122
impl<T> FracGhost<T> {
127123
#[verifier::type_invariant]
128124
spec fn inv(self) -> bool {
129-
self.r.value() is Value
125+
&&& self.r.value().left is Frac
126+
&&& self.r.value().right is Agree
130127
}
131128

132129
pub closed spec fn id(self) -> Loc {
133130
self.r.loc()
134131
}
135132

136133
pub closed spec fn view(self) -> T {
137-
self.r.value()->v
134+
self.r.value().right->Agree_0
138135
}
139136

140137
/// The fractional quantity of this permission
141138
pub closed spec fn frac(self) -> real {
142-
self.r.value()->frac
139+
self.r.value().left->Frac_0
143140
}
144141

145142
pub open spec fn valid(self, id: Loc, frac: real) -> bool {
@@ -153,7 +150,10 @@ impl<T> FracGhost<T> {
153150
result.frac() == 1 as real,
154151
result@ == v,
155152
{
156-
let f = FractionalCarrier::<T>::new(v);
153+
let f = FractionalCarrier {
154+
left: FractionRA::Frac(1 as real),
155+
right: AgreementRA::Agree(v),
156+
};
157157
let tracked r = Resource::alloc(f);
158158
Self { r }
159159
}
@@ -201,8 +201,14 @@ impl<T> FracGhost<T> {
201201
tracked_swap(self, &mut mself);
202202
use_type_invariant(&mself);
203203
let tracked (r1, r2) = mself.r.split(
204-
FractionalCarrier::Value { v: mself.r.value()->v, frac: self_frac - result_frac },
205-
FractionalCarrier::Value { v: mself.r.value()->v, frac: result_frac },
204+
FractionalCarrier {
205+
left: FractionRA::Frac(self_frac - result_frac),
206+
right: AgreementRA::Agree(mself@),
207+
},
208+
FractionalCarrier {
209+
left: FractionRA::Frac(result_frac),
210+
right: AgreementRA::Agree(mself@),
211+
},
206212
);
207213
self.r = r1;
208214
Self { r: r2 }
@@ -257,7 +263,11 @@ impl<T> FracGhost<T> {
257263
tracked_swap(self, &mut mself);
258264
use_type_invariant(&mself);
259265
let tracked mut r = mself.r;
260-
let f = FractionalCarrier::<T>::Value { v, frac: (1 as real) };
266+
let f = FractionalCarrier {
267+
left: FractionRA::Frac(1 as real),
268+
right: AgreementRA::Agree(v),
269+
};
270+
lemma_whole_fraction_has_no_frame(r.value().left);
261271
*self = Self { r: r.update(f) };
262272
}
263273

0 commit comments

Comments
 (0)