Commit ddca2214 authored by Heiko Becker's avatar Heiko Becker

Prove soundness of Range validator for unary operators and division

parents b7ef63c0 3eb5483d
...@@ -58,6 +58,8 @@ You can then run Daisy on an input file as follows: ...@@ -58,6 +58,8 @@ You can then run Daisy on an input file as follows:
$ ./daisy testcases/rosa/Doppler.scala $ ./daisy testcases/rosa/Doppler.scala
``` ```
## Checking Interval Arithmetic Certificates
If you want to produce certificates to check them in either of the supported backends, If you want to produce certificates to check them in either of the supported backends,
you have to call Daisy as with you have to call Daisy as with
```bash ```bash
......
(** (**
This file contains the coq implementation of the error bound validator as well as its soundness proof. This file contains the coq implementation of the error bound validator as well
It is explained in section 5 of the paper. as its soundness proof. The function validErrorbound is the Error bound
The validator is used in the file CertificateChecker.v to build the complete checker. validator from the certificate checking process. Under the assumption that a
valid range arithmetic result has been computed, it can validate error bounds
encoded in the analysis result. The validator is used in the file
CertificateChecker.v to build the complete checker.
**) **)
Require Import Coq.QArith.QArith Coq.QArith.Qminmax Coq.QArith.Qabs Coq.QArith.Qreals Coq.Lists.List. Require Import Coq.QArith.QArith Coq.QArith.Qminmax Coq.QArith.Qabs Coq.QArith.Qreals Coq.Lists.List.
Require Import Coq.micromega.Psatz Coq.Reals.Reals. Require Import Coq.micromega.Psatz Coq.Reals.Reals.
......
...@@ -23,13 +23,36 @@ Definition binop_eq_bool (b1:binop) (b2:binop) := ...@@ -23,13 +23,36 @@ Definition binop_eq_bool (b1:binop) (b2:binop) :=
Next define an evaluation function for binary operators on reals. Next define an evaluation function for binary operators on reals.
Errors are added on the expression evaluation level later. Errors are added on the expression evaluation level later.
**) **)
Fixpoint eval_binop (o:binop) (v1:R) (v2:R) := Definition eval_binop (o:binop) (v1:R) (v2:R) :=
match o with match o with
| Plus => Rplus v1 v2 | Plus => Rplus v1 v2
| Sub => Rminus v1 v2 | Sub => Rminus v1 v2
| Mult => Rmult v1 v2 | Mult => Rmult v1 v2
| Div => Rdiv v1 v2 | Div => Rdiv v1 v2
end. end.
(**
Expressions will use unary operators.
Define them first
**)
Inductive unop: Type := Neg | Inv.
Definition unop_eq_bool (o1:unop) (o2:unop) :=
match o1 with
|Neg => match o2 with |Neg => true |_=> false end
|Inv => match o2 with |Inv => true |_ => false end
end.
(**
Define evaluation for unary operators on reals.
Errors are added on the expression evaluation level later.
**)
Definition eval_unop (o:unop) (v:R):=
match o with
|Neg => (- v)%R
|Inv => (/ v)%R
end .
(** (**
Define expressions parametric over some value type V. Define expressions parametric over some value type V.
Will ease reasoning about different instantiations later. Will ease reasoning about different instantiations later.
...@@ -41,6 +64,7 @@ Inductive exp (V:Type): Type := ...@@ -41,6 +64,7 @@ Inductive exp (V:Type): Type :=
Var: nat -> exp V Var: nat -> exp V
| Param: nat -> exp V | Param: nat -> exp V
| Const: V -> exp V | Const: V -> exp V
| Unop: unop -> exp V -> exp V
| Binop: binop -> exp V -> exp V -> exp V. | Binop: binop -> exp V -> exp V -> exp V.
...@@ -61,9 +85,14 @@ Fixpoint exp_eq_bool (e1:exp Q) (e2:exp Q) := ...@@ -61,9 +85,14 @@ Fixpoint exp_eq_bool (e1:exp Q) (e2:exp Q) :=
|Const n2 => Qeq_bool n1 n2 |Const n2 => Qeq_bool n1 n2
| _=> false | _=> false
end end
|Binop b1 e11 e12 => |Unop o1 e11 =>
match e2 with
|Unop o2 e22 => andb (unop_eq_bool o1 o2) (exp_eq_bool e11 e22)
|_ => false
end
|Binop o1 e11 e12 =>
match e2 with match e2 with
|Binop b2 e21 e22 => andb (binop_eq_bool b1 b2) (andb (exp_eq_bool e11 e21) (exp_eq_bool e12 e22)) |Binop o2 e21 e22 => andb (binop_eq_bool o1 o2) (andb (exp_eq_bool e11 e21) (exp_eq_bool e12 e22))
|_ => false |_ => false
end end
end. end.
...@@ -89,7 +118,12 @@ Inductive eval_exp (eps:R) (env:env_ty) : (exp R) -> R -> Prop := ...@@ -89,7 +118,12 @@ Inductive eval_exp (eps:R) (env:env_ty) : (exp R) -> R -> Prop :=
| Const_dist n delta: | Const_dist n delta:
Rle (Rabs delta) eps -> Rle (Rabs delta) eps ->
eval_exp eps env (Const n) (perturb n delta) eval_exp eps env (Const n) (perturb n delta)
|Binop_dist op e1 e2 v1 v2 delta: (** Unary negation is special! We do not have a new error here since IEE 754 gives us a sign bit **)
| Unop_neg e1 v1: eval_exp eps env e1 v1 -> eval_exp eps env (Unop Neg e1) (eval_unop Neg v1)
| Unop_inv e1 v1 delta: Rle (Rabs delta) eps ->
eval_exp eps env e1 v1 ->
eval_exp eps env (Unop Inv e1) (perturb (eval_unop Inv v1) delta)
| Binop_dist op e1 e2 v1 v2 delta:
Rle (Rabs delta) eps -> Rle (Rabs delta) eps ->
eval_exp eps env e1 v1 -> eval_exp eps env e1 v1 ->
eval_exp eps env e2 v2 -> eval_exp eps env e2 v2 ->
...@@ -120,10 +154,13 @@ Lemma eval_0_det (e:exp R) (env:env_ty): ...@@ -120,10 +154,13 @@ Lemma eval_0_det (e:exp R) (env:env_ty):
v1 = v2. v1 = v2.
Proof. Proof.
induction e; intros v1 v2 eval_v1 eval_v2; induction e; intros v1 v2 eval_v1 eval_v2;
inversion eval_v1; inversion eval_v2; [ auto | | | ]; inversion eval_v1; inversion eval_v2; [ auto | | | | | | | ];
repeat try rewrite perturb_0_val; auto. repeat try rewrite perturb_0_val; subst; auto.
subst. - rewrite (IHe v0 v3); auto.
rewrite (IHe1 v0 v4); auto. - inversion H3.
- inversion H4.
- rewrite (IHe v0 v3); auto.
- rewrite (IHe1 v0 v4); auto.
rewrite (IHe2 v3 v5); auto. rewrite (IHe2 v3 v5); auto.
Qed. Qed.
...@@ -134,7 +171,7 @@ evaluating the subexpressions and then binding the result values to different ...@@ -134,7 +171,7 @@ evaluating the subexpressions and then binding the result values to different
variables in the environment. variables in the environment.
This needs the property that variables are not perturbed as opposed to parameters This needs the property that variables are not perturbed as opposed to parameters
**) **)
Lemma existential_rewriting (b:binop) (e1:exp R) (e2:exp R) (eps:R) (cenv:env_ty) (v:R): Lemma existential_rewriting_binary (b:binop) (e1:exp R) (e2:exp R) (eps:R) (cenv:env_ty) (v:R):
(eval_exp eps cenv (Binop b e1 e2) v <-> (eval_exp eps cenv (Binop b e1 e2) v <->
exists v1 v2, exists v1 v2,
eval_exp eps cenv e1 v1 /\ eval_exp eps cenv e1 v1 /\
...@@ -157,6 +194,28 @@ Proof. ...@@ -157,6 +194,28 @@ Proof.
constructor; auto. constructor; auto.
Qed. Qed.
Lemma existential_rewriting_unary (e:exp R) (eps:R) (cenv:env_ty) (v:R):
(eval_exp eps cenv (Unop Inv e) v <->
exists v1,
eval_exp eps cenv e v1 /\
eval_exp eps (updEnv 1 v1 cenv) (Unop Inv (Var R 1)) v).
Proof.
split.
- intros eval_un.
inversion eval_un; subst.
exists v1.
repeat split; try auto.
constructor; try auto.
constructor; auto.
- intros exists_val.
destruct exists_val as [v1 [eval_e1 eval_e_env]].
inversion eval_e_env; subst.
inversion H1; subst.
unfold updEnv in *; simpl in *.
constructor; auto.
Qed.
(** (**
Using the parametric expressions, define boolean expressions for conditionals Using the parametric expressions, define boolean expressions for conditionals
**) **)
......
...@@ -6,12 +6,13 @@ Require Import Coq.QArith.QArith Coq.QArith.Qminmax Coq.QArith.Qabs Coq.QArith.Q ...@@ -6,12 +6,13 @@ Require Import Coq.QArith.QArith Coq.QArith.Qminmax Coq.QArith.Qabs Coq.QArith.Q
Require Import Coq.Reals.Reals Coq.micromega.Psatz. Require Import Coq.Reals.Reals Coq.micromega.Psatz.
Require Import Daisy.Infra.RationalSimps Daisy.Infra.Abbrevs Daisy.Expressions Daisy.IntervalArith. Require Import Daisy.Infra.RationalSimps Daisy.Infra.Abbrevs Daisy.Expressions Daisy.IntervalArith.
Fixpoint toRExp (e:exp Q) := Fixpoint toRExp (f:exp Q) :=
match e with match f with
|Var _ v => Var R v |Var _ v => Var R v
|Param _ v => Param R v |Param _ v => Param R v
|Const n => Const (Q2R n) |Const n => Const (Q2R n)
|Binop b e1 e2 => Binop b (toRExp e1) (toRExp e2) |Unop o f1 => Unop o (toRExp f1)
|Binop o f1 f2 => Binop o (toRExp f1) (toRExp f2)
end. end.
Lemma Q2R0_is_0: Lemma Q2R0_is_0:
......
(** (**
Interval arithmetic checker and its soundness proof Interval arithmetic checker and its soundness proof.
Explained in section 4 of the paper, used in CertificateChecker.v to build full checker, The function validIntervalbounds checks wether the given analysis result is
a valid range arithmetic for each sub term of the given expression e.
The computation is done using our formalized interval arithmetic.
The function is used in CertificateChecker.v to build the full checker.
**) **)
Require Import Coq.QArith.QArith Coq.QArith.Qreals QArith.Qminmax Coq.Lists.List Coq.micromega.Psatz. Require Import Coq.QArith.QArith Coq.QArith.Qreals QArith.Qminmax Coq.Lists.List Coq.micromega.Psatz.
Require Import Daisy.Infra.Abbrevs Daisy.Infra.RationalSimps Daisy.Infra.RealRationalProps. Require Import Daisy.Infra.Abbrevs Daisy.Infra.RationalSimps Daisy.Infra.RealRationalProps.
...@@ -8,12 +11,13 @@ Require Import Daisy.Infra.ExpressionAbbrevs Daisy.IntervalArithQ Daisy.Interval ...@@ -8,12 +11,13 @@ Require Import Daisy.Infra.ExpressionAbbrevs Daisy.IntervalArithQ Daisy.Interval
Import Lists.List.ListNotations. Import Lists.List.ListNotations.
Fixpoint freeVars (V:Type) (e:exp V) : list nat:= Fixpoint freeVars (V:Type) (f:exp V) : list nat:=
match e with match f with
|Const n => [] |Const n => []
|Var _ v => [] |Var _ v => []
|Param _ v => [v] |Param _ v => [v]
|Binop b e1 e2 => (freeVars V e1) ++ (freeVars V e2) |Unop o f1 => freeVars V f1
|Binop o f1 f2 => (freeVars V f1) ++ (freeVars V f2)
end. end.
Fixpoint validIntervalbounds (e:exp Q) (absenv:analysisResult) (P:precond):= Fixpoint validIntervalbounds (e:exp Q) (absenv:analysisResult) (P:precond):=
...@@ -24,6 +28,23 @@ Fixpoint validIntervalbounds (e:exp Q) (absenv:analysisResult) (P:precond):= ...@@ -24,6 +28,23 @@ Fixpoint validIntervalbounds (e:exp Q) (absenv:analysisResult) (P:precond):=
isSupersetIntv (P v) intv isSupersetIntv (P v) intv
| Const n => | Const n =>
isSupersetIntv (n,n) intv isSupersetIntv (n,n) intv
| Unop o f1 =>
let rec := validIntervalbounds f1 absenv P in
let (iv1, _) := absenv f1 in
let opres :=
match o with
| Neg =>
let new_iv := negateIntv iv1 in
isSupersetIntv new_iv intv
| Inv =>
let nodiv0 := orb
(andb (Qleb (ivhi iv1) 0) (negb (Qeq_bool (ivhi iv1) 0)))
(andb (Qleb 0 (ivlo iv1)) (negb (Qeq_bool (ivlo iv1) 0))) in
let new_iv := invertIntv iv1 in
andb (isSupersetIntv new_iv intv) nodiv0
end
in
andb rec opres
| Binop b e1 e2 => | Binop b e1 e2 =>
let rec := andb (validIntervalbounds e1 absenv P) (validIntervalbounds e2 absenv P) in let rec := andb (validIntervalbounds e1 absenv P) (validIntervalbounds e2 absenv P) in
let (iv1,_) := absenv e1 in let (iv1,_) := absenv e1 in
...@@ -50,12 +71,12 @@ Fixpoint validIntervalbounds (e:exp Q) (absenv:analysisResult) (P:precond):= ...@@ -50,12 +71,12 @@ Fixpoint validIntervalbounds (e:exp Q) (absenv:analysisResult) (P:precond):=
andb rec opres andb rec opres
end. end.
Theorem ivbounds_approximatesPrecond_sound e absenv P: Theorem ivbounds_approximatesPrecond_sound f absenv P:
validIntervalbounds e absenv P = true -> validIntervalbounds f absenv P = true ->
forall v, In v (freeVars Q e) -> forall v, In v (freeVars Q f) ->
Is_true(isSupersetIntv (P v) (fst (absenv (Param Q v)))). Is_true(isSupersetIntv (P v) (fst (absenv (Param Q v)))).
Proof. Proof.
induction e; unfold validIntervalbounds. induction f; unfold validIntervalbounds.
- intros approx_true v v_in_fV; simpl in *; contradiction. - intros approx_true v v_in_fV; simpl in *; contradiction.
- intros approx_true v v_in_fV; simpl in *. - intros approx_true v v_in_fV; simpl in *.
unfold isSupersetIntv. unfold isSupersetIntv.
...@@ -65,19 +86,27 @@ Proof. ...@@ -65,19 +86,27 @@ Proof.
destruct i; simpl in *. destruct i; simpl in *.
apply Is_true_eq_left in approx_true; auto. apply Is_true_eq_left in approx_true; auto.
- intros approx_true v0 v_in_fV; simpl in *; contradiction. - intros approx_true v0 v_in_fV; simpl in *; contradiction.
- intros approx_unary_true v v_in_fV.
unfold freeVars in v_in_fV.
apply Is_true_eq_left in approx_unary_true.
destruct (absenv (Unop u f)); destruct (absenv f); simpl in *.
apply andb_prop_elim in approx_unary_true.
destruct approx_unary_true.
apply IHf; try auto.
apply Is_true_eq_true; auto.
- intros approx_bin_true v v_in_fV. - intros approx_bin_true v v_in_fV.
unfold freeVars in v_in_fV. unfold freeVars in v_in_fV.
apply in_app_or in v_in_fV. apply in_app_or in v_in_fV.
apply Is_true_eq_left in approx_bin_true. apply Is_true_eq_left in approx_bin_true.
destruct (absenv (Binop b e1 e2)); destruct (absenv e1); destruct (absenv e2); simpl in *. destruct (absenv (Binop b f1 f2)); destruct (absenv f1); destruct (absenv f2); simpl in *.
apply andb_prop_elim in approx_bin_true. apply andb_prop_elim in approx_bin_true.
destruct approx_bin_true. destruct approx_bin_true.
apply andb_prop_elim in H. apply andb_prop_elim in H.
destruct H. destruct H.
destruct v_in_fV as [v_in_fV_e1 | v_in_fV_e2]. destruct v_in_fV as [v_in_fV_f1 | v_in_fV_f2].
+ apply IHe1; auto. + apply IHf1; auto.
apply Is_true_eq_true; auto. apply Is_true_eq_true; auto.
+ apply IHe2; auto. + apply IHf2; auto.
apply Is_true_eq_true; auto. apply Is_true_eq_true; auto.
Qed. Qed.
...@@ -114,38 +143,33 @@ Proof. ...@@ -114,38 +143,33 @@ Proof.
apply le_neq_bool_to_lt_prop; auto. apply le_neq_bool_to_lt_prop; auto.
Qed. Qed.
Theorem validIntervalbounds_sound (e:exp Q): Theorem validIntervalbounds_sound (f:exp Q) (absenv:analysisResult) (P:precond) cenv:
forall (absenv:analysisResult) (P:precond) cenv vR, forall vR,
precondValidForExec P cenv -> precondValidForExec P cenv ->
validIntervalbounds e absenv P = true -> validIntervalbounds f absenv P = true ->
eval_exp 0%R cenv (toRExp e) vR -> eval_exp 0%R cenv (toRExp f) vR ->
(Q2R (fst (fst(absenv e))) <= vR <= Q2R (snd (fst (absenv e))))%R. (Q2R (fst (fst(absenv f))) <= vR <= Q2R (snd (fst (absenv f))))%R.
Proof. Proof.
induction e. induction f.
- intros absenv P cenv vR precond_valid valid_bounds eval_e. - intros vR precond_valid valid_bounds eval_f.
pose proof (ivbounds_approximatesPrecond_sound (Var Q n) absenv P valid_bounds) as env_approx_p. pose proof (ivbounds_approximatesPrecond_sound (Var Q n) absenv P valid_bounds) as env_approx_p.
unfold validIntervalbounds in valid_bounds. unfold validIntervalbounds in valid_bounds.
destruct (absenv (Var Q n)); inversion valid_bounds. destruct (absenv (Var Q n)); inversion valid_bounds.
- intros absenv P cenv vR precond_valid valid_bounds eval_e. - intros vR precond_valid valid_bounds eval_f.
pose proof (ivbounds_approximatesPrecond_sound (Param Q n) absenv P valid_bounds) as env_approx_p. pose proof (ivbounds_approximatesPrecond_sound (Param Q n) absenv P valid_bounds) as env_approx_p.
unfold validIntervalbounds in valid_bounds. unfold validIntervalbounds in valid_bounds.
assert (exists intv err, absenv (Param Q n) = (intv,err)) case_eq (absenv (Param Q n)).
as absenv_n intros intv err absenv_n.
by (destruct (absenv (Param Q n)); repeat eexists; auto).
destruct absenv_n as [intv [err absenv_n]].
rewrite absenv_n in valid_bounds. rewrite absenv_n in valid_bounds.
unfold precondValidForExec in precond_valid. unfold precondValidForExec in precond_valid.
specialize (env_approx_p n). specialize (env_approx_p n).
assert (exists ivlo ivhi, P n = (ivlo, ivhi)) as p_n case_eq (P n); intros ivlo ivhi p_n.
by (destruct (P n); repeat eexists; auto).
destruct p_n as [ivlo [ivhi p_n]].
unfold isSupersetIntv, freeVars in env_approx_p. unfold isSupersetIntv, freeVars in env_approx_p.
assert (In n (n::nil)) by (unfold In; auto). assert (In n (n::nil)) as n_in_n by (unfold In; auto).
specialize (env_approx_p H). specialize (env_approx_p n_in_n).
rewrite p_n, absenv_n in env_approx_p. rewrite p_n, absenv_n in env_approx_p.
specialize (precond_valid n); rewrite p_n in precond_valid. specialize (precond_valid n); rewrite p_n in precond_valid.
inversion eval_e; subst. inversion eval_f; subst.
rewrite absenv_n; simpl.
rewrite perturb_0_val; auto. rewrite perturb_0_val; auto.
destruct intv as [abslo abshi]; simpl in *. destruct intv as [abslo abshi]; simpl in *.
apply andb_prop_elim in env_approx_p. apply andb_prop_elim in env_approx_p.
...@@ -162,15 +186,14 @@ Proof. ...@@ -162,15 +186,14 @@ Proof.
+ eapply Rle_trans. + eapply Rle_trans.
apply env_le_ivhi. apply env_le_ivhi.
apply ivhi_le_abshi. apply ivhi_le_abshi.
- intros absenv P cenv vR valid_precond valid_bounds eval_e. - intros vR valid_precond valid_bounds eval_f.
pose proof (ivbounds_approximatesPrecond_sound (Const v) absenv P valid_bounds) as env_approx_p. pose proof (ivbounds_approximatesPrecond_sound (Const v) absenv P valid_bounds) as env_approx_p.
unfold validIntervalbounds in valid_bounds. unfold validIntervalbounds in valid_bounds.
destruct (absenv (Const v)) as [intv err]. destruct (absenv (Const v)) as [intv err]; simpl.
simpl.
apply Is_true_eq_left in valid_bounds. apply Is_true_eq_left in valid_bounds.
apply andb_prop_elim in valid_bounds. apply andb_prop_elim in valid_bounds.
destruct valid_bounds as [valid_lo valid_hi]. destruct valid_bounds as [valid_lo valid_hi].
inversion eval_e; subst. inversion eval_f; subst.
rewrite perturb_0_val; auto. rewrite perturb_0_val; auto.
unfold contained; simpl. unfold contained; simpl.
split. split.
...@@ -182,32 +205,128 @@ Proof. ...@@ -182,32 +205,128 @@ Proof.
unfold Qleb in *. unfold Qleb in *.
apply Qle_bool_iff in valid_hi. apply Qle_bool_iff in valid_hi.
apply Qle_Rle in valid_hi; auto. apply Qle_Rle in valid_hi; auto.
- intros absenv P cenv vR valid_precond valid_bounds eval_e; - intros vR valid_precond valid_bounds eval_f;
inversion eval_e; subst. pose proof (ivbounds_approximatesPrecond_sound (Unop u f) absenv P valid_bounds) as env_approx_p.
pose proof (ivbounds_approximatesPrecond_sound (Binop b e1 e2) absenv P valid_bounds) as env_approx_p. case_eq (absenv (Unop u f)); intros intv err absenv_unop.
rewrite perturb_0_val in eval_e; auto. destruct intv as [unop_lo unop_hi]; simpl.
unfold validIntervalbounds in valid_bounds.
rewrite absenv_unop in valid_bounds.
case_eq (absenv f); intros intv_f err_f absenv_f.
rewrite absenv_f in valid_bounds.
apply Is_true_eq_left in valid_bounds.
apply andb_prop_elim in valid_bounds.
destruct valid_bounds as [valid_rec valid_unop].
apply Is_true_eq_true in valid_rec.
inversion eval_f; subst.
+ specialize (IHf v1 valid_precond valid_rec H2).
rewrite absenv_f in IHf; simpl in IHf.
(* TODO: Make lemma *)
unfold isSupersetIntv in valid_unop.
apply andb_prop_elim in valid_unop.
destruct valid_unop as [valid_lo valid_hi].
apply Is_true_eq_true in valid_lo; apply Is_true_eq_true in valid_hi.
apply Qle_bool_iff in valid_lo; apply Qle_bool_iff in valid_hi.
pose proof (interval_negation_valid (Q2R (fst intv_f),(Q2R (snd intv_f))) v1) as negation_valid.
unfold contained, negateInterval in negation_valid; simpl in *.
apply Qle_Rle in valid_lo; apply Qle_Rle in valid_hi.
destruct IHf.
unfold eval_unop; split.
* eapply Rle_trans. apply valid_lo.
rewrite Q2R_opp; lra.
* eapply Rle_trans.
Focus 2. apply valid_hi.
rewrite Q2R_opp; lra.
+ specialize (IHf v1 valid_precond valid_rec H3).
rewrite absenv_f in IHf; simpl in IHf.
apply andb_prop_elim in valid_unop.
destruct valid_unop as [valid_unop nodiv0].
(* TODO: Make lemma *)
unfold isSupersetIntv in valid_unop.
apply andb_prop_elim in valid_unop.
destruct valid_unop as [valid_lo valid_hi].
apply Is_true_eq_true in valid_lo; apply Is_true_eq_true in valid_hi.
apply Qle_bool_iff in valid_lo; apply Qle_bool_iff in valid_hi.
assert ((Q2R (ivhi intv_f) < 0)%R \/ (0 < Q2R (ivlo intv_f))%R) as nodiv0_prop.
* apply Is_true_eq_true in nodiv0.
apply le_neq_bool_to_lt_prop in nodiv0.
destruct nodiv0.
{ left; rewrite <- Q2R0_is_0; apply Qlt_Rlt; auto. }
{ right; rewrite <- Q2R0_is_0; apply Qlt_Rlt; auto. }
* pose proof (interval_inversion_valid (Q2R (fst intv_f),(Q2R (snd intv_f))) v1) as inv_valid.
unfold contained, invertInterval in inv_valid; simpl in *.
apply Qle_Rle in valid_lo; apply Qle_Rle in valid_hi.
destruct IHf.
rewrite perturb_0_val; auto.
unfold eval_unop, perturb; split.
{ eapply Rle_trans. apply valid_lo.
destruct nodiv0_prop as [nodiv0_neg | nodiv0_pos].
(* TODO: Extract lemma maybe *)
- assert (0 < - (Q2R (snd intv_f)))%R as negation_pos by lra.
assert (- (Q2R (snd intv_f)) <= - v1)%R as negation_flipped_hi by lra.
apply Rinv_le_contravar in negation_flipped_hi; try auto.
rewrite <- Ropp_inv_permute in negation_flipped_hi; try lra.
rewrite <- Ropp_inv_permute in negation_flipped_hi; try lra.
apply Ropp_le_contravar in negation_flipped_hi.
repeat rewrite Ropp_involutive in negation_flipped_hi;
rewrite Q2R_inv; auto.
hnf; intros is_0.
rewrite <- Q2R0_is_0 in nodiv0_neg.
apply Rlt_Qlt in nodiv0_neg; lra.
- rewrite Q2R_inv.
apply Rinv_le_contravar; try lra.
hnf; intros is_0.
assert (Q2R (fst intv_f) <= Q2R (snd intv_f))%R by lra.
rewrite <- Q2R0_is_0 in nodiv0_pos.
apply Rlt_Qlt in nodiv0_pos; apply Rle_Qle in H2; lra.
}
{ eapply Rle_trans.
Focus 2. apply valid_hi.
destruct nodiv0_prop as [nodiv0_neg | nodiv0_pos].
- assert (Q2R (fst intv_f) < 0)%R as fst_lt_0 by lra.
assert (0 < - (Q2R (fst intv_f)))%R as negation_pos by lra.
assert (- v1 <= - (Q2R (fst intv_f)))%R as negation_flipped_lo by lra.
apply Rinv_le_contravar in negation_flipped_lo; try auto.
rewrite <- Ropp_inv_permute in negation_flipped_lo; try lra.
rewrite <- Ropp_inv_permute in negation_flipped_lo; try lra.
apply Ropp_le_contravar in negation_flipped_lo.
repeat rewrite Ropp_involutive in negation_flipped_lo;
rewrite Q2R_inv; auto.
hnf; intros is_0.
rewrite <- Q2R0_is_0 in negation_pos.
rewrite <- Q2R_opp in negation_pos.
apply Rlt_Qlt in negation_pos; lra.
assert (0 < - (Q2R (snd intv_f)))%R by lra.
lra.
- rewrite Q2R_inv.
apply Rinv_le_contravar; try lra.
hnf; intros is_0.
assert (Q2R (fst intv_f) <= Q2R (snd intv_f))%R by lra.
rewrite <- Q2R0_is_0 in nodiv0_pos.
apply Rlt_Qlt in nodiv0_pos; apply Rle_Qle in H2; lra.
}
- intros vR valid_precond valid_bounds eval_f; inversion eval_f; subst.
pose proof (ivbounds_approximatesPrecond_sound (Binop b f1 f2) absenv P valid_bounds) as env_approx_p.
rewrite perturb_0_val in eval_f; auto.
rewrite perturb_0_val; auto. rewrite perturb_0_val; auto.
simpl in valid_bounds. simpl in valid_bounds.
env_assert absenv (Binop b e1 e2) absenv_bin. case_eq (absenv (Binop b f1 f2)); intros iv err absenv_bin.
env_assert absenv e1 absenv_e1. case_eq (absenv f1); intros iv1 err1 absenv_f1.
env_assert absenv e2 absenv_e2. case_eq (absenv f2); intros iv2 err2 absenv_f2.
destruct absenv_bin as [iv [err absenv_bin]]; rewrite absenv_bin in valid_bounds; rewrite absenv_bin. rewrite absenv_bin, absenv_f1, absenv_f2 in valid_bounds.
destruct absenv_e1 as [iv1 [err1 absenv_e1]]; rewrite absenv_e1 in valid_bounds.
destruct absenv_e2 as [iv2 [err2 absenv_e2]]; rewrite absenv_e2 in valid_bounds.
apply Is_true_eq_left in valid_bounds. apply Is_true_eq_left in valid_bounds.
apply andb_prop_elim in valid_bounds. apply andb_prop_elim in valid_bounds.
destruct valid_bounds as [valid_rec valid_bin]. destruct valid_bounds as [valid_rec valid_bin].
apply andb_prop_elim in valid_rec. apply andb_prop_elim in valid_rec.
destruct valid_rec as [valid_e1 valid_e2]. destruct valid_rec as [valid_e1 valid_e2].
apply Is_true_eq_true in valid_e1; apply Is_true_eq_true in valid_e2. apply Is_true_eq_true in valid_e1; apply Is_true_eq_true in valid_e2.
specialize (IHe1 absenv P cenv v1 valid_precond valid_e1 H4); specialize (IHf1 v1 valid_precond valid_e1 H4);
specialize (IHe2 absenv P cenv v2 valid_precond valid_e2 H5). specialize (IHf2 v2 valid_precond valid_e2 H5).
rewrite absenv_e1 in IHe1.