use super::super::prelude::*;
use super::algebra::ResourceAlgebra;
use super::pcm::PCM;
use super::relations::*;
verus! {
impl<RA: ResourceAlgebra> ResourceAlgebra for Option<RA> {
open spec fn valid(self) -> bool {
match self {
Some(v) => v.valid(),
None => true,
}
}
open spec fn op(a: Self, b: Self) -> Self {
match (a, b) {
(Some(a), Some(b)) => Some(RA::op(a, b)),
(None, _) => b,
(_, None) => a,
}
}
proof fn associative(a: Self, b: Self, c: Self) {
match (a, b, c) {
(Some(a), Some(b), Some(c)) => RA::associative(a, b, c),
(_, _, _) => {},
}
}
proof fn commutative(a: Self, b: Self) {
match (a, b) {
(Some(a), Some(b)) => RA::commutative(a, b),
(_, _) => {},
}
}
proof fn valid_op(a: Self, b: Self) {
match (a, b) {
(Some(a), Some(b)) => RA::valid_op(a, b),
(_, _) => {},
}
}
}
impl<RA: ResourceAlgebra> PCM for Option<RA> {
open spec fn unit() -> Self {
None
}
proof fn op_unit(self) {
}
proof fn unit_valid() {
}
}
pub proof fn lemma_incl_opt<RA: ResourceAlgebra>(a: RA, b: RA)
requires
incl::<RA>(a, b),
ensures
incl::<Option<RA>>(Some(a), Some(b)),
{
let c = choose|x| RA::op(a, x) == b;
assert(Option::<RA>::op(Some(a), Some(c)) == Some(b));
}
pub proof fn lemma_incl_opt_rev<RA: ResourceAlgebra>(a: RA, b: RA)
requires
incl::<Option<RA>>(Some(a), Some(b)),
ensures
incl::<RA>(a, b) || a == b,
{
let c = choose|x| Option::<RA>::op(Some(a), x) == Some(b);
if c is None {
Some(a).op_unit();
}
}
pub proof fn lemma_set_op_opt<RA: ResourceAlgebra>(s: ISet<RA>, t: RA)
ensures
set_op(s, t).map(|b| Some(b)) == set_op(s.map(|x| Some(x)), Some(t)),
{
broadcast use super::super::iset::group_iset_lemmas;
let s_mapped = s.map(|x| Some(x));
let original = set_op(s, t);
let map_after = original.map(|b| Some(b));
let map_before = set_op(s_mapped, Some(t));
assert forall|v| map_after.contains(v) implies map_before.contains(v) by {
let q = choose|q| #[trigger] s.contains(q) && v->Some_0 == RA::op(q, t);
assert(s_mapped.contains(Some(q)));
}
assert forall|v| map_before.contains(v) implies map_after.contains(v) by {
let q = choose|q| #[trigger] s_mapped.contains(q) && v == Option::<RA>::op(q, Some(t));
assert(original.contains(v->Some_0));
}
}
}