Module PedraQ
Hint Resolve top_correct: vpl.
Definition bottom: t := None.
Lemma bottom_correct: forall m, ~(gamma bottom m).
Proof.
simpl; auto.
Qed.
Definition isBottom : t -> imp bool
:= fun p =>
match p with
| None => pure true
| Some pol =>
BIND isEmpty <- Backend.isEmpty (ml pol) -;
pure match isEmpty with
| None => false
| Some cert => Cs.chkEmpty (cons pol) cert
end
end.
Lemma isBottom_correct : forall a, If isBottom a THEN forall m, gamma a m -> False.
Proof.
unfold isBottom.
xasimplify ltac:(
eauto with pedraQ).
Qed.
Global Opaque isBottom.
Definition isIncl (p1 p2:t) : imp bool
:= match p1 with
| None => pure true
| Some pol1 =>
match p2 with
| None =>
BIND isEmpty <- Backend.isEmpty (ml pol1) -;
pure match isEmpty with
| None => false
| Some cert => Cs.chkEmpty (cons pol1) cert
end
| Some pol2 =>
BIND isIncl <- Backend.isIncl (ml pol1, ml pol2) -;
pure match isIncl with
| None => false
| Some cert => Cs.chkIncl (cons pol1) (cons pol2) cert
end
end
end.
Lemma isIncl_correct p1 p2: If isIncl p1 p2 THEN forall m, gamma p1 m -> gamma p2 m.
Proof.
unfold isIncl.
xasimplify ltac:(
eauto with pedraQ).
Qed.
Hint Resolve isIncl_correct: vpl.
Global Opaque isIncl.
Definition meet (p1 p2:t): imp t :=
SOME p1' <- p1 -;
SOME p2' <- p2 -;
BIND meet <- Backend.meet (ml p1', ml p2') -;
pure (
let (maybeP, ce) := meet in
match maybeP with
| Some p => Some (mk (Cs.meet (cons p1') (cons p2') ce) p)
| None =>
if Cs.meetEmpty (cons p1') (cons p2') ce
then None
else failwith "PedraQ.meet" top
end).
Lemma meet_correct p1 p2: WHEN p <- meet p1 p2 THEN forall m, gamma p1 m -> gamma p2 m ->gamma p m.
Proof.
unfold meet.
xasimplify ltac:(
eauto with pedraQ).
Qed.
Definition join (p1 p2:t) : imp t :=
match p1, p2 with
| None, None => pure None
| None, pol
| pol, None => pure pol
| Some pol1, Some pol2 =>
BIND join <- Backend.join (ml pol1, ml pol2) -;
let (shadow, cert) := join in
pure (Some (mk (Cs.buildJoin (cons pol1) (cons pol2) cert) shadow))
end.
Lemma join_correct p1 p2: WHEN p <- join p1 p2 THEN forall m, gamma p1 m \/ gamma p2 m -> gamma p m.
Proof.
unfold join;
xasimplify ltac:(
intuition eauto with pedraQ).
Qed.
Global Hint Resolve join_correct: vpl.
Definition widen (p1 p2: t): imp t :=
match p1, p2 with
| None, None => pure None
| None, p | p, None => pure p
| Some pol1, Some pol2 =>
BIND widen <- Backend.widen (ml pol1, ml pol2) -;
let (cs, shadow) := widen in
pure (Some (mk shadow cs))
end.
Definition project (p: t) (x: PVar.t): imp t
:= SOME p1 <- p -;
BIND project <- Backend.project (ml p1, x) -;
pure (
let (p2, c) := project in
let cs:= Cs.approx (cons p1) c in
if Cs.isFree x cs then
Some (mk cs p2)
else
failwith ("PedraQ.project: "++(PVar.pr x)++" not free in "++(Cs.pr cs)) top).
Lemma project_correct a x: WHEN p <- project a x THEN forall m v, gamma a m -> gamma p (Mem.assign x v m).
Proof.
Global Hint Resolve project_correct: vpl.
End BasicD.
Module ItvD.
Import BasicD.
Definition buildLow (p: polT) (v: LinQ.t) (b: Backend.bndT): QItv.bndT :=
match b with
| Backend.Infty => QItv.Infty
| Backend.Open n f =>
let c:=Cs.combine (cons p) f in
if Cstr.isIncl c (Cstr.lowerToCstr v n) then QItv.Open n else QItv.Infty
| Backend.Closed n f =>
let c:=Cs.combine (cons p) f in
if Cstr.isIncl c (Cstr.lowerOrEqualsToCstr v n) then QItv.Closed n else QItv.Infty
end.
Lemma buildLow_correct (p: polT) (v: LinQ.t) (b: Backend.bndT) m:
gamma (Some p) m -> QItv.satLower (buildLow p v b) (LinQ.eval v m).
Proof.
unfold buildLow;
destruct b;
simpl;
auto;
PedraQsimplify.
Qed.
Definition buildUp (p: polT) (v: LinQ.t) (b: Backend.bndT): QItv.bndT :=
match b with
| Backend.Infty => QItv.Infty
| Backend.Open n f =>
let c:=Cs.combine (cons p) f in
if Cstr.isIncl c (Cstr.upperToCstr v n) then QItv.Open n else QItv.Infty
| Backend.Closed n f =>
let c:=Cs.combine (cons p) f in
if Cstr.isIncl c (Cstr.upperOrEqualsToCstr v n) then QItv.Closed n else QItv.Infty
end.
Lemma buildUp_correct (p: polT) (v: LinQ.t) (b: Backend.bndT) m:
gamma (Some p) m -> QItv.satUpper (buildUp p v b) (LinQ.eval v m).
Proof.
unfold buildUp;
destruct b;
simpl;
auto;
PedraQsimplify.
Qed.
wrapping "mk" function of QItv
Definition QItv_mk (l u: QItv.bndT): QItv.t
:= projT1 (QItv.mk l u).
Lemma QItv_mk_correct l u x: QItv.satLower l x -> QItv.satUpper u x -> QItv.sat (QItv_mk l u) x.
Proof.
Definition getItv (p: t) (v: LinQ.t): imp QItv.t :=
match p with
| None => pure QItv.Bot
| Some pol =>
BIND sItv <- Backend.getItv (ml pol, v) -;
let low := buildLow pol v (Backend.low sItv) in
let up := buildUp pol v (Backend.up sItv) in
pure (QItv_mk low up)
end.
Local Hint Resolve buildUp_correct buildLow_correct QItv_mk_correct: pedraQ.
Lemma getItv_correct (p: t) (v: LinQ.t):
WHEN i <- getItv p v THEN forall m, gamma p m -> QItv.sat i (LinQ.eval v m).
Proof.
unfold getItv;
xasimplify ltac: (
eauto with pedraQ).
Qed.
Global Hint Resolve getItv_correct: pedraQ.
Definition getLowerBound : t -> LinQ.t -> imp QItv.bndT
:= fun p v =>
match p with
| None => failwith "PedraQ.ItvD.getLowerBound" (pure QItv.Infty)
| Some pol =>
BIND b <- Backend.getLowerBound (ml pol, v) -;
pure (buildLow pol v b)
end.
Lemma getLowerBound_correct (p : t) (v : LinQ.t) :
WHEN b <- getLowerBound p v THEN forall m, gamma p m -> QItv.satLower b (LinQ.eval v m).
Proof.
Definition getUpperBound : t -> LinQ.t -> imp QItv.bndT
:= fun p v =>
match p with
| None => failwith "PedraQ.ItvD.getUpperBound" (pure QItv.Infty)
| Some pol =>
BIND b <- Backend.getUpperBound (ml pol, v) -;
pure (buildUp pol v b)
end.
Lemma getUpperBound_correct (p : t) (v : LinQ.t) :
WHEN b <- getUpperBound p v THEN forall m, gamma p m -> QItv.satUpper b (LinQ.eval v m).
Proof.
Hint Resolve getUpperBound_correct getLowerBound_correct: pedraQ.
Definition getItvMode mo (v: LinQ.t) (p:t): imp QItv.t :=
match mo with
| BOTH => getItv p v
| UP => BIND b <- getUpperBound p v -;
pure (QItv_mk QItv.Infty b)
| LOW => BIND b <- getLowerBound p v -;
pure (QItv_mk b QItv.Infty)
end.
Extraction Inline getItvMode.
Lemma getItvMode_correct mo v p:
WHEN i <- (getItvMode mo v p) THEN
forall m, gamma p m -> QItv.sat i (LinQ.eval v m).
Proof.
unfold getItvMode;
destruct mo;
xasimplify ltac: (
eauto with pedraQ).
simpl in * |- *;
intros;
eapply QItv_mk_correct;
simpl;
eauto.
Qed.
Hint Resolve getItvMode_correct: vpl.
End ItvD.
Module CstrD <: HasConcreteConditions QNum Cstr BasicD.
Import BasicD.
Definition assume (c: Cstr.t) (p: t): imp t :=
SOME p1 <- p -;
BIND cid <- Backend.freshId (ml p1) -;
BIND aux <- Backend.add (ml p1, c) -;
pure (let (opt, cert) := aux in
match opt with
| None =>
if (Cs.chkEmpty (Cs.add (cons p1) cid c) cert) then
None
else
failwith "CstrD.assume" top
| Some s => Some (mk (Cs.redAdd (cons p1) cid c cert) s)
end).
Lemma assume_correct: forall c a, WHEN p <- assume c a THEN forall m, Cstr.sat c m -> gamma a m -> gamma p m.
Proof.
unfold assume;
xasimplify ltac:(
unfold not;
eauto with pedraQ).
Qed.
fromCstr c builds a polyhedron from a constraint.
If it fails, default is returned.
Hence default may be chosen according to the fact that precision or soundness is required
Definition fromCstr: Cstr.t -> t -> imp t
:= fun c default =>
BIND cid <- Backend.freshId Backend.top -;
BIND res <- Backend.addp (Backend.top,c) -;
pure match res with
| Backend.Added p (fwd, bwd) =>
match Cs.addp Cs.top cid c fwd bwd with
| Some cs => Some (mk cs p)
| None => failwith "CstrD.fromCstr" default
end
| Backend.Contrad ce =>
if Cs.chkEmpty (Cs.add Cs.top cid c) ce
then None
else failwith "CstrD.fromCstr" default
end.
Currently useless ?? TODO: adapt with default
Lemma fromCstr_correct: forall c p, fromCstr c = Some p ->
forall m, Cstr.sat c m -> gamma p m.
Proof.
intros c p hr m hc.
unfold fromCstr in hr.
destruct (Backend.addp Backend.top c) as p' [fwd bwd]|ce.
- assert (pf := fun cs' =>
Cs.addp_correct Cs.top cs' (Backend.getId Backend.top)
c fwd bwd m).
destruct (Cs.addp Cs.top (Backend.getId Backend.top) c fwd bwd) as cs|.
+ inversion hr.
apply pf; reflexivity|constructor|assumption.
+ discriminate hr.
- assert (pf := Cs.chkEmpty_correct
(Cs.add Cs.top (Backend.getId Backend.top) c) ce).
destruct (Cs.chkEmpty (Cs.add Cs.top (Backend.getId Backend.top) c) ce).
+ inversion hr.
contradiction pf with (m := m).
apply Cs.Add_correct; constructor|assumption.
+ discriminate hr.
Qed.
Local Hint Resolve Cs.addp_precise_c: pedraQ.
Lemma fromCstr_precise c: WHEN p <- fromCstr c None THEN forall m, gamma p m -> Cstr.sat c m.
Proof.
unfold fromCstr;
unfoldDebug;
xtsimplify ltac:
idtac;
intros m.
destruct exta0 as [
p' [
fwd bwd]|
ce].
-
apply try_catch_decomp.
PedraQsimplify.
-
apply if_decomp.
PedraQsimplify.
Qed.
Test whether a polyhedron is included in a given half space.
Definition assert (c: Cstr.t) (p: t): imp bool :=
BIND p' <- fromCstr c None -;
isIncl p p'.
Local Opaque fromCstr.
Local Hint Resolve fromCstr_precise isIncl_correct: pedraQ.
Lemma assert_correct: forall c a, If assert c a THEN forall m, gamma a m -> Cstr.sat c m.
Proof.
intros c a.
unfold assert.
xasimplify ltac: (eauto with pedraQ).
Qed.
Global Opaque assert assume.
Global Hint Resolve assert_correct assume_correct: vpl.
End CstrD.
Module Rename <: HasRename QNum BasicD.
Import BasicD.
Definition rename (x y: PVar.t) (a:t) : imp t :=
SOME p <- a -;
BIND aux <- Backend.rename (x,y,ml p) -;
pure (Some {| cons := Cs.rename x y (cons p) ; ml := aux |}).
Lemma rename_correct: forall x y a, WHEN p <- (rename x y a) THEN
forall m, gamma a (Mem.assign x (m y) m) -> gamma p m.
Proof.
Global Hint Resolve rename_correct: vpl.
End Rename.