Commit cfa68f4b authored by Heiko Becker's avatar Heiko Becker
Browse files

Implement let-Bindings in Coq and show soundness of let checker

parent 5b919837
......@@ -5,15 +5,15 @@
as shown in the soundness theorem.
**)
Require Import Coq.Reals.Reals Coq.QArith.Qreals.
Require Import Daisy.Infra.RealSimps Daisy.Infra.RationalSimps Daisy.Infra.RealRationalProps.
Require Import Daisy.IntervalValidation Daisy.ErrorValidation.
Require Import Daisy.Infra.RealSimps Daisy.Infra.RationalSimps Daisy.Infra.RealRationalProps Daisy.Infra.Ltacs.
Require Import Daisy.IntervalValidation Daisy.ErrorValidation Daisy.Environments.
Require Export Coq.QArith.QArith.
Require Export Daisy.Infra.ExpressionAbbrevs.
(** Certificate checking function **)
Definition CertificateChecker (e:exp Q) (absenv:analysisResult) (P:precond) :=
andb (validIntervalbounds e absenv P) (validErrorbound e absenv).
andb (validIntervalbounds e absenv P NatSet.empty) (validErrorbound e absenv).
(**
Soundness proof for the certificate checker.
......@@ -22,9 +22,10 @@ Definition CertificateChecker (e:exp Q) (absenv:analysisResult) (P:precond) :=
This property is expressed by the predicate precondValidForExec.
**)
Theorem Certificate_checking_is_sound (e:exp Q) (absenv:analysisResult) P:
forall (cenv:env) (vR:R) (vF:R),
eval_exp 0%R cenv P (toRExp e) vR ->
eval_exp (Q2R machineEpsilon) cenv P (toRExp e) vF ->
forall (VarEnv1 VarEnv2 ParamEnv:env) (vR:R) (vF:R),
approxEnv VarEnv1 absenv VarEnv2 ->
eval_exp 0%R VarEnv1 ParamEnv P (toRExp e) vR ->
eval_exp (Q2R machineEpsilon) VarEnv2 ParamEnv P (toRExp e) vF ->
CertificateChecker e absenv P = true ->
(Rabs (vR - vF) <= Q2R (snd (absenv e)))%R.
(**
......@@ -32,17 +33,50 @@ Theorem Certificate_checking_is_sound (e:exp Q) (absenv:analysisResult) P:
validator and the error bound validator.
**)
Proof.
intros cenv vR vF eval_real eval_float certificate_valid.
intros VarEnv1 VarEnv2 ParamEnv vR vF approxC1C2 eval_real eval_float certificate_valid.
unfold CertificateChecker in certificate_valid.
apply Is_true_eq_left in certificate_valid.
apply andb_prop_elim in certificate_valid.
destruct certificate_valid as [iv_valid errorbound_valid].
apply Is_true_eq_true in iv_valid;
apply Is_true_eq_true in errorbound_valid.
andb_to_prop certificate_valid.
assert (exists iv err, absenv e = (iv,err)) by (destruct (absenv e); repeat eexists).
destruct H as [iv [err absenv_eq]].
assert (exists ivlo ivhi, iv = (ivlo, ivhi)) by (destruct iv; repeat eexists).
destruct H as [ivlo [ ivhi iv_eq]].
subst; rewrite absenv_eq in *; simpl in *.
eapply (validErrorbound_sound e cenv absenv vR vF err P); eauto.
eapply (validErrorbound_sound); eauto.
intros v v_in_empty.
rewrite NatSet.mem_spec in v_in_empty.
hnf in v_in_empty.
inversion v_in_empty.
Qed.
Definition CertificateCheckerCmd (f:cmd Q) (absenv:analysisResult) (P:precond) :=
andb (validIntervalboundsCmd f absenv P NatSet.empty)
(validErrorboundCmd f absenv).
Theorem Certificate_checking_cmds_is_sound (f:cmd Q) (absenv:analysisResult) P:
forall (VarEnv1 VarEnv2 ParamEnv:env) outVars envR envF,
approxEnv VarEnv1 absenv VarEnv2 ->
ssaPrg Q f NatSet.empty outVars ->
bstep (toRCmd f) VarEnv1 ParamEnv P 0 (Nop R) envR ->
bstep (toRCmd f) VarEnv2 ParamEnv P (Q2R machineEpsilon) (Nop R) envF ->
CertificateCheckerCmd f absenv P = true ->
(Rabs (envR 0%nat - envF 0%nat) <= Q2R (snd (absenv (Var Q 0))))%R.
(**
The proofs is a simple composition of the soundness proofs for the range
validator and the error bound validator.
**)
Proof.
intros VarEnv1 VarEnv2 ParamEnv outVars envR envF
approxC1C2 ssa_f eval_real eval_float certificate_valid.
unfold CertificateCheckerCmd in certificate_valid.
andb_to_prop certificate_valid.
assert (exists iv err, absenv (Var Q 0) = (iv,err)) by (destruct (absenv (Var Q 0)); repeat eexists).
destruct H as [iv [err absenv_eq]].
assert (exists ivlo ivhi, iv = (ivlo, ivhi)) by (destruct iv; repeat eexists).
destruct H as [ivlo [ ivhi iv_eq]].
subst; rewrite absenv_eq in *; simpl in *.
eapply (validErrorboundCmd_sound); eauto.
intros v v_in_empty.
rewrite NatSet.mem_spec in v_in_empty.
hnf in v_in_empty.
inversion v_in_empty.
Qed.
\ No newline at end of file
......@@ -3,7 +3,7 @@
FIXME: Currently the semantics are stateful. But daisy actually assumes that a variable may not be verwritten?
**)
Require Import Coq.Reals.Reals.
Require Import Daisy.Expressions.
Require Export Daisy.Infra.ExpressionAbbrevs.
(**
Next define what a program is.
Currently no loops, only conditionals and assignments
......
......@@ -97,18 +97,20 @@ Qed.
(**
Copy-Paste proof with minor differences, was easier then manipulating the evaluations and then applying the lemma
**)
Lemma subtract_abs_err_bounded (e1:exp R) (e1R:R) (e1F:R) (e2:exp R) (e2R:R) (e2F:R) (vR:R) (vF:R) (VarEnv ParamEnv:nat->R) P (err1:R) (err2:R):
eval_exp 0%R VarEnv ParamEnv P e1 e1R ->
eval_exp (Q2R machineEpsilon) VarEnv ParamEnv P e1 e1F ->
eval_exp 0%R VarEnv ParamEnv P e2 e2R ->
eval_exp (Q2R machineEpsilon) VarEnv ParamEnv P e2 e2F ->
eval_exp 0%R VarEnv ParamEnv P (Binop Sub e1 e2) vR ->
eval_exp (Q2R machineEpsilon) (updEnv 2 e2F (updEnv 1 e1F VarEnv)) ParamEnv P (Binop Sub (Var R 1) (Var R 2)) vF ->
(Rabs (e1R - e1F) <= err1)%R ->
(Rabs (e2R - e2F) <= err2)%R ->
(Rabs (vR - vF) <= err1 + err2 + ((Rabs (e1F - e2F)) * (Q2R machineEpsilon)))%R.
Lemma subtract_abs_err_bounded (e1:exp Q) (e1R:R) (e1F:R) (e2:exp Q) (e2R:R)
(e2F:R) (vR:R) (vF:R) (VarEnv1 VarEnv2 ParamEnv:nat->R) P absenv:
approxEnv VarEnv1 absenv VarEnv2 ->
eval_exp 0%R VarEnv1 ParamEnv P (toRExp e1) e1R ->
eval_exp (Q2R machineEpsilon) VarEnv2 ParamEnv P (toRExp e1) e1F ->
eval_exp 0%R VarEnv1 ParamEnv P (toRExp e2) e2R ->
eval_exp (Q2R machineEpsilon) VarEnv2 ParamEnv P (toRExp e2) e2F ->
eval_exp 0%R VarEnv1 ParamEnv P (Binop Sub (toRExp e1) (toRExp e2)) vR ->
eval_exp (Q2R machineEpsilon) (updEnv 2 e2F (updEnv 1 e1F VarEnv2)) ParamEnv P (Binop Sub (Var R 1) (Var R 2)) vF ->
(Rabs (e1R - e1F) <= Q2R (snd (absenv e1)))%R ->
(Rabs (e2R - e2F) <= Q2R (snd (absenv e2)))%R ->
(Rabs (vR - vF) <= Q2R (snd (absenv e1)) + Q2R (snd (absenv e2)) + ((Rabs (e1F - e2F)) * (Q2R machineEpsilon)))%R.
Proof.
intros e1_real e1_float e2_real e2_float sub_real sub_float bound_e1 bound_e2.
intros approxCEnv e1_real e1_float e2_real e2_float sub_real sub_float bound_e1 bound_e2.
(* Prove that e1R and e2R are the correct values and that vR is e1R + e2R *)
inversion sub_real; subst.
rewrite delta_0_deterministic in sub_real; auto.
......@@ -149,16 +151,18 @@ Proof.
eapply Rmult_le_compat_l; [apply Rabs_pos | auto].
Qed.
Lemma mult_abs_err_bounded (e1:exp R) (e1R:R) (e1F:R) (e2:exp R) (e2R:R) (e2F:R) (vR:R) (vF:R) (VarEnv ParamEnv:env) (P:precond) (err1:R) (err2:R):
eval_exp 0%R VarEnv ParamEnv P e1 e1R ->
eval_exp (Q2R machineEpsilon) VarEnv ParamEnv P e1 e1F ->
eval_exp 0%R VarEnv ParamEnv P e2 e2R ->
eval_exp (Q2R machineEpsilon) VarEnv ParamEnv P e2 e2F ->
eval_exp 0%R VarEnv ParamEnv P (Binop Mult e1 e2) vR ->
eval_exp (Q2R machineEpsilon) (updEnv 2 e2F (updEnv 1 e1F VarEnv)) ParamEnv P (Binop Mult (Var R 1) (Var R 2)) vF ->
Lemma mult_abs_err_bounded (e1:exp Q) (e1R:R) (e1F:R) (e2:exp Q) (e2R:R) (e2F:R)
(vR:R) (vF:R) (VarEnv1 VarEnv2 ParamEnv:env) (P:precond) absenv:
approxEnv VarEnv1 absenv VarEnv2 ->
eval_exp 0%R VarEnv1 ParamEnv P (toRExp e1) e1R ->
eval_exp (Q2R machineEpsilon) VarEnv2 ParamEnv P (toRExp e1) e1F ->
eval_exp 0%R VarEnv1 ParamEnv P (toRExp e2) e2R ->
eval_exp (Q2R machineEpsilon) VarEnv2 ParamEnv P (toRExp e2) e2F ->
eval_exp 0%R VarEnv1 ParamEnv P (Binop Mult (toRExp e1) (toRExp e2)) vR ->
eval_exp (Q2R machineEpsilon) (updEnv 2 e2F (updEnv 1 e1F VarEnv2)) ParamEnv P (Binop Mult (Var R 1) (Var R 2)) vF ->
(Rabs (vR - vF) <= Rabs (e1R * e2R - e1F * e2F) + Rabs (e1F * e2F) * (Q2R machineEpsilon))%R.
Proof.
intros e1_real e1_float e2_real e2_float mult_real mult_float.
intros approxCEnv e1_real e1_float e2_real e2_float mult_real mult_float.
(* Prove that e1R and e2R are the correct values and that vR is e1R * e2R *)
inversion mult_real; subst.
rewrite delta_0_deterministic in mult_real; auto.
......@@ -193,16 +197,18 @@ Proof.
apply Rabs_pos.
Qed.
Lemma div_abs_err_bounded (e1:exp R) (e1R:R) (e1F:R) (e2:exp R) (e2R:R) (e2F:R) (vR:R) (vF:R) (VarEnv ParamEnv:env) (P:precond) (err1:R) (err2:R):
eval_exp 0%R VarEnv ParamEnv P e1 e1R ->
eval_exp (Q2R machineEpsilon) VarEnv ParamEnv P e1 e1F ->
eval_exp 0%R VarEnv ParamEnv P e2 e2R ->
eval_exp (Q2R machineEpsilon) VarEnv ParamEnv P e2 e2F ->
eval_exp 0%R VarEnv ParamEnv P (Binop Div e1 e2) vR ->
eval_exp (Q2R machineEpsilon) (updEnv 2 e2F (updEnv 1 e1F VarEnv)) ParamEnv P (Binop Div (Var R 1) (Var R 2)) vF ->
Lemma div_abs_err_bounded (e1:exp Q) (e1R:R) (e1F:R) (e2:exp Q) (e2R:R) (e2F:R)
(vR:R) (vF:R) (VarEnv1 VarEnv2 ParamEnv:env) (P:precond) absenv:
approxEnv VarEnv1 absenv VarEnv2 ->
eval_exp 0%R VarEnv1 ParamEnv P (toRExp e1) e1R ->
eval_exp (Q2R machineEpsilon) VarEnv2 ParamEnv P (toRExp e1) e1F ->
eval_exp 0%R VarEnv1 ParamEnv P (toRExp e2) e2R ->
eval_exp (Q2R machineEpsilon) VarEnv2 ParamEnv P (toRExp e2) e2F ->
eval_exp 0%R VarEnv1 ParamEnv P (Binop Div (toRExp e1) (toRExp e2)) vR ->
eval_exp (Q2R machineEpsilon) (updEnv 2 e2F (updEnv 1 e1F VarEnv2)) ParamEnv P (Binop Div (Var R 1) (Var R 2)) vF ->
(Rabs (vR - vF) <= Rabs (e1R / e2R - e1F / e2F) + Rabs (e1F / e2F) * (Q2R machineEpsilon))%R.
Proof.
intros e1_real e1_float e2_real e2_float div_real div_float.
intros approxCenv e1_real e1_float e2_real e2_float div_real div_float.
(* Prove that e1R and e2R are the correct values and that vR is e1R * e2R *)
inversion div_real; subst.
rewrite delta_0_deterministic in div_real; auto.
......
......@@ -8,10 +8,8 @@
**)
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 Daisy.Infra.Abbrevs Daisy.Infra.RationalSimps Daisy.Infra.RealRationalProps Daisy.Infra.RealSimps.
Require Import Daisy.Infra.Ltacs Daisy.Infra.ExpressionAbbrevs Daisy.Commands.
Require Import Daisy.IntervalArith Daisy.IntervalArithQ Daisy.ErrorBounds Daisy.IntervalValidation.
Require Import Daisy.Environments.
Require Import Daisy.Infra.Abbrevs Daisy.Infra.RationalSimps Daisy.Infra.RealRationalProps Daisy.Infra.RealSimps Daisy.Infra.Ltacs.
Require Import Daisy.Environments Daisy.IntervalValidation Daisy.ErrorBounds.
(** Error bound validator **)
Fixpoint validErrorbound (e:exp Q) (absenv:analysisResult) :=
......@@ -49,11 +47,12 @@ Fixpoint validErrorbound (e:exp Q) (absenv:analysisResult) :=
end.
(** Error bound command validator **)
Fixpoint validErrorboundCmd (f:cmd Q) (env:analysisResult) {struct f} : bool :=
match f with
|Let _ x e g => (validErrorbound e env) && (Qeq_bool (snd (env e)) (snd (env (Var Q x)))) && validErrorboundCmd g env
|Ret _ e => validErrorbound e env
|Let _ x e g =>
(validErrorbound e env) && (Qeq_bool (snd (env e)) (snd (env (Var Q x)))) &&
validErrorboundCmd g env
|Ret _ e => validErrorbound e env && (Qeq_bool (snd (env e)) (snd (env (Var Q 0))))
|Nop _ => true
end.
......@@ -111,22 +110,20 @@ Lemma validErrorboundCorrectConstant:
eval_exp 0%R VarEnv1 ParamEnv P (Const (Q2R n)) nR ->
eval_exp (Q2R (RationalSimps.machineEpsilon)) VarEnv2 ParamEnv P (Const (Q2R n)) nF ->
validErrorbound (Const n) absenv = true ->
validIntervalbounds (Const n) absenv P = true ->
(Q2R nlo <= nR <= Q2R nhi)%R ->
absenv (Const n) = ((nlo,nhi),e) ->
(Rabs (nR - nF) <= (Q2R e))%R.
Proof.
intros cenv1 cenv2 PEnv absenv n nR nF e nlo nhi P approx_CEnv eval_real eval_float error_valid intv_valid absenv_const.
intros cenv1 cenv2 PEnv absenv n nR nF e nlo nhi P.
intros approx_CEnv eval_real eval_float error_valid intv_valid absenv_const.
unfold validErrorbound in error_valid.
inversion eval_real; subst.
rewrite delta_0_deterministic in eval_real; auto.
rewrite delta_0_deterministic; auto.
rewrite delta_0_deterministic in *; auto.
clear delta H0.
inversion eval_float; subst.
pose proof (validIntervalbounds_sound (Const n) absenv P cenv1 PEnv (Q2R n) intv_valid eval_real) as iv_valid.
rewrite absenv_const in *; simpl in *.
unfold perturb in *; simpl in *.
unfold perturb; simpl.
rewrite Rabs_err_simpl.
unfold Qleb in error_valid.
andb_to_prop error_valid.
rename R into error_valid.
apply Qle_bool_iff in error_valid.
......@@ -138,10 +135,9 @@ Proof.
eapply Rle_trans.
+ eapply Rmult_le_compat_r.
apply mEps_geq_zero.
destruct iv_valid.
destruct intv_valid.
apply RmaxAbs; eauto.
+ rewrite <- maxAbs_impl_RmaxAbs in error_valid.
unfold RmaxAbsFun in error_valid.
auto.
Qed.
......@@ -151,12 +147,14 @@ Lemma validErrorboundCorrectParam:
eval_exp 0%R VarEnv1 ParamEnv P (toRExp (Param Q v)) nR ->
eval_exp (Q2R RationalSimps.machineEpsilon) VarEnv2 ParamEnv P (toRExp (Param Q v)) nF ->
validErrorbound (Param Q v) absenv = true ->
validIntervalbounds (Param Q v) absenv P = true ->
(Q2R plo <= nR <= Q2R phi)%R ->
(forall n : nat, List.In n (freeVars Q (Param Q v)) ->
Is_true (isSupersetIntv (P n) (fst (absenv (Param Q n))))) ->
absenv (Param Q v) = ((plo,phi),e) ->
(Rabs (nR - nF) <= (Q2R e))%R.
Proof.
intros cenv1 cenv2 PEnv absenv v nR nF e P plo phi approx_CEnv eval_real eval_float error_valid intv_valid absenv_param.
pose proof (ivbounds_approximatesPrecond_sound (Param Q v) absenv P intv_valid) as absenv_approx_p.
intros cenv1 cenv2 PEnv absenv v nR nF e P plo phi.
intros approx_CEnv eval_real eval_float error_valid intv_valid absenv_approx_p absenv_param.
unfold validErrorbound in error_valid.
rewrite absenv_param in error_valid.
inversion eval_real; subst.
......@@ -208,7 +206,8 @@ Lemma validErrorboundCorrectAddition VarEnv1 VarEnv2 ParamEnv absenv
eval_exp (Q2R RationalSimps.machineEpsilon) VarEnv2 ParamEnv P (toRExp e2) nF2 ->
eval_exp (Q2R RationalSimps.machineEpsilon) (updEnv 2 nF2 (updEnv 1 nF1 VarEnv2)) ParamEnv P (toRExp (Binop Plus (Var Q 1) (Var Q 2))) nF ->
validErrorbound (Binop Plus e1 e2) absenv = true ->
validIntervalbounds (Binop Plus e1 e2) absenv P = true ->
(Q2R e1lo <= nR1 <= Q2R e1hi)%R ->
(Q2R e2lo <= nR2 <= Q2R e2hi)%R ->
absenv e1 = ((e1lo,e1hi),err1) ->
absenv e2 = ((e2lo, e2hi),err2) ->
absenv (Binop Plus e1 e2) = ((alo,ahi),e)->
......@@ -217,16 +216,19 @@ Lemma validErrorboundCorrectAddition VarEnv1 VarEnv2 ParamEnv absenv
(Rabs (nR - nF) <= (Q2R e))%R.
Proof.
intros approx_CEnv e1_real e2_real eval_real e1_float e2_float eval_float
valid_error valid_intv absenv_e1 absenv_e2 absenv_add
valid_error valid_intv1 valid_intv2 absenv_e1 absenv_e2 absenv_add
err1_bounded err2_bounded.
eapply Rle_trans.
apply
(add_abs_err_bounded (toRExp e1) nR1 nF1 (toRExp e2) nR2 nF2 nR nF VarEnv1 ParamEnv P (Q2R err1) (Q2R err2));
(add_abs_err_bounded e1 nR1 nF1 e2 nR2 nF2 nR nF VarEnv1 VarEnv2 ParamEnv P absenv);
try auto.
rewrite absenv_e1; auto.
rewrite absenv_e2; auto.
unfold validErrorbound in valid_error at 1.
rewrite absenv_add, absenv_e1, absenv_e2 in valid_error.
andb_to_prop valid_error.
rename R into valid_error.
rewrite absenv_e1, absenv_e2; simpl.
eapply Rle_trans.
apply Rplus_le_compat_l.
eapply Rmult_le_compat_r.
......@@ -242,9 +244,6 @@ Proof.
repeat rewrite <- maxAbs_impl_RmaxAbs in valid_error.
apply valid_error.
clear L R1.
simpl in valid_intv.
rewrite absenv_add, absenv_e1, absenv_e2 in valid_intv.
andb_to_prop valid_intv.
remember (addIntv (widenIntv (e1lo, e1hi) err1) (widenIntv (e2lo, e2hi) err2)) as iv.
iv_assert iv iv_unf.
destruct iv_unf as [ivl [ivh iv_unf]].
......@@ -253,14 +252,8 @@ Proof.
assert (ivlo iv = ivl) by (rewrite iv_unf; auto).
assert (ivhi iv = ivh) by (rewrite iv_unf; auto).
rewrite <- H, <- H0.
pose proof (validIntervalbounds_sound _ _ _ _ _ L0 e1_real) as valid_bounds_e1.
rewrite absenv_e1 in valid_bounds_e1.
simpl in valid_bounds_e1.
pose proof (distance_gives_iv nR1 nF1 (Q2R err1) (Q2R e1lo, Q2R e1hi) valid_bounds_e1 err1_bounded).
pose proof (validIntervalbounds_sound _ _ _ _ _ R1 e2_real) as valid_bounds_e2.
rewrite absenv_e2 in valid_bounds_e2.
simpl in valid_bounds_e2.
pose proof (distance_gives_iv nR2 nF2 (Q2R err2) (Q2R e2lo, Q2R e2hi) valid_bounds_e2 err2_bounded).
pose proof (distance_gives_iv nR1 nF1 (Q2R err1) (Q2R e1lo, Q2R e1hi) valid_intv1 err1_bounded).
pose proof (distance_gives_iv nR2 nF2 (Q2R err2) (Q2R e2lo, Q2R e2hi) valid_intv2 err2_bounded).
pose proof (IntervalArith.interval_addition_valid _ _ _ _ H1 H2).
unfold IntervalArith.contained in H3.
destruct H3.
......@@ -274,15 +267,19 @@ Proof.
repeat rewrite Q2R_minus; auto.
Qed.
Lemma validErrorboundCorrectSubtraction cenv absenv (e1:exp Q) (e2:exp Q) (nR nR1 nR2 nF nF1 nF2 :R) (e err1 err2 :error) (alo ahi e1lo e1hi e2lo e2hi:Q) P :
eval_exp 0%R cenv P (toRExp e1) nR1 ->
eval_exp 0%R cenv P (toRExp e2) nR2 ->
eval_exp 0%R cenv P (toRExp (Binop Sub e1 e2)) nR ->
eval_exp (Q2R RationalSimps.machineEpsilon) cenv P (toRExp e1) nF1 ->
eval_exp (Q2R RationalSimps.machineEpsilon) cenv P (toRExp e2) nF2 ->
eval_exp (Q2R RationalSimps.machineEpsilon) (updEnv 2 nF2 (updEnv 1 nF1 cenv)) P (toRExp (Binop Sub (Var Q 1) (Var Q 2))) nF ->
Lemma validErrorboundCorrectSubtraction VarEnv1 VarEnv2 ParamEnv absenv
(e1:exp Q) (e2:exp Q) (nR nR1 nR2 nF nF1 nF2 :R) (e err1 err2 :error)
(alo ahi e1lo e1hi e2lo e2hi:Q) P :
approxEnv VarEnv1 absenv VarEnv2 ->
eval_exp 0%R VarEnv1 ParamEnv P (toRExp e1) nR1 ->
eval_exp 0%R VarEnv1 ParamEnv P (toRExp e2) nR2 ->
eval_exp 0%R VarEnv1 ParamEnv P (toRExp (Binop Sub e1 e2)) nR ->
eval_exp (Q2R RationalSimps.machineEpsilon) VarEnv2 ParamEnv P (toRExp e1) nF1 ->
eval_exp (Q2R RationalSimps.machineEpsilon) VarEnv2 ParamEnv P (toRExp e2) nF2 ->
eval_exp (Q2R RationalSimps.machineEpsilon) (updEnv 2 nF2 (updEnv 1 nF1 VarEnv2)) ParamEnv P (toRExp (Binop Sub (Var Q 1) (Var Q 2))) nF ->
validErrorbound (Binop Sub e1 e2) absenv = true ->
validIntervalbounds (Binop Sub e1 e2) absenv P = true ->
(Q2R e1lo <= nR1 <= Q2R e1hi)%R ->
(Q2R e2lo <= nR2 <= Q2R e2hi)%R ->
absenv e1 = ((e1lo,e1hi),err1) ->
absenv e2 = ((e2lo, e2hi),err2) ->
absenv (Binop Sub e1 e2) = ((alo,ahi),e)->
......@@ -290,19 +287,22 @@ Lemma validErrorboundCorrectSubtraction cenv absenv (e1:exp Q) (e2:exp Q) (nR nR
(Rabs (nR2 - nF2) <= (Q2R err2))%R ->
(Rabs (nR - nF) <= (Q2R e))%R.
Proof.
intros e1_real e2_real eval_real e1_float e2_float eval_float
valid_error valid_intv absenv_e1 absenv_e2 absenv_sub
intros approxCEnv e1_real e2_real eval_real e1_float e2_float eval_float
valid_error valid_intv1 valid_intv2 absenv_e1 absenv_e2 absenv_sub
err1_bounded err2_bounded.
eapply Rle_trans.
eapply subtract_abs_err_bounded.
apply approxCEnv.
apply e1_real.
apply e1_float.
apply e2_real.
apply e2_float.
apply eval_real.
apply eval_float.
apply err1_bounded.
apply err2_bounded.
rewrite absenv_e1; simpl;
apply err1_bounded.
rewrite absenv_e2; simpl;
apply err2_bounded.
unfold validErrorbound in valid_error at 1.
rewrite absenv_sub, absenv_e1, absenv_e2 in valid_error.
andb_to_prop valid_error.
......@@ -315,13 +315,11 @@ Proof.
repeat rewrite <- Rabs_eq_Qabs in valid_error.
repeat rewrite Q2R_plus in valid_error.
repeat rewrite <- maxAbs_impl_RmaxAbs in valid_error.
rewrite absenv_e1, absenv_e2; simpl.
eapply Rle_trans.
apply Rplus_le_compat_l.
eapply Rmult_le_compat_r.
apply mEps_geq_zero.
simpl in valid_intv.
rewrite absenv_sub, absenv_e1, absenv_e2 in valid_intv.
andb_to_prop valid_intv.
Focus 2.
apply valid_error.
remember (subtractIntv (widenIntv (e1lo, e1hi) err1) (widenIntv (e2lo, e2hi) err2)) as iv.
......@@ -332,14 +330,8 @@ Proof.
assert (ivlo iv = ivl) by (rewrite iv_unf; auto).
assert (ivhi iv = ivh) by (rewrite iv_unf; auto).
rewrite <- H, <- H0.
pose proof (validIntervalbounds_sound _ _ _ _ _ L1 e1_real) as valid_bounds_e1.
rewrite absenv_e1 in valid_bounds_e1.
simpl in valid_bounds_e1.
pose proof (distance_gives_iv nR1 nF1 (Q2R err1) (Q2R e1lo, Q2R e1hi) valid_bounds_e1 err1_bounded).
pose proof (validIntervalbounds_sound _ _ _ _ _ R2 e2_real) as valid_bounds_e2.
rewrite absenv_e2 in valid_bounds_e2.
simpl in valid_bounds_e2.
pose proof (distance_gives_iv nR2 nF2 (Q2R err2) (Q2R e2lo, Q2R e2hi) valid_bounds_e2 err2_bounded).
pose proof (distance_gives_iv nR1 nF1 (Q2R err1) (Q2R e1lo, Q2R e1hi) valid_intv1 err1_bounded).
pose proof (distance_gives_iv nR2 nF2 (Q2R err2) (Q2R e2lo, Q2R e2hi) valid_intv2 err2_bounded).
pose proof (IntervalArith.interval_subtraction_valid _ _ _ _ H1 H2).
unfold IntervalArith.contained in H3.
destruct H3.
......@@ -359,15 +351,19 @@ Proof.
repeat rewrite Q2R_minus; auto.
Qed.
Lemma validErrorboundCorrectMult cenv absenv (e1:exp Q) (e2:exp Q) (nR nR1 nR2 nF nF1 nF2 :R) (e err1 err2 :error) (alo ahi e1lo e1hi e2lo e2hi:Q) P :
eval_exp 0%R cenv P (toRExp e1) nR1 ->
eval_exp 0%R cenv P (toRExp e2) nR2 ->
eval_exp 0%R cenv P (toRExp (Binop Mult e1 e2)) nR ->
eval_exp (Q2R RationalSimps.machineEpsilon) cenv P (toRExp e1) nF1 ->
eval_exp (Q2R RationalSimps.machineEpsilon) cenv P (toRExp e2) nF2 ->
eval_exp (Q2R RationalSimps.machineEpsilon) (updEnv 2 nF2 (updEnv 1 nF1 cenv)) P (toRExp (Binop Mult (Var Q 1) (Var Q 2))) nF ->
Lemma validErrorboundCorrectMult VarEnv1 VarEnv2 ParamEnv absenv
(e1:exp Q) (e2:exp Q) (nR nR1 nR2 nF nF1 nF2 :R) (e err1 err2 :error)
(alo ahi e1lo e1hi e2lo e2hi:Q) P :
approxEnv VarEnv1 absenv VarEnv2 ->
eval_exp 0%R VarEnv1 ParamEnv P (toRExp e1) nR1 ->
eval_exp 0%R VarEnv1 ParamEnv P (toRExp e2) nR2 ->
eval_exp 0%R VarEnv1 ParamEnv P (toRExp (Binop Mult e1 e2)) nR ->
eval_exp (Q2R RationalSimps.machineEpsilon) VarEnv2 ParamEnv P (toRExp e1) nF1 ->
eval_exp (Q2R RationalSimps.machineEpsilon) VarEnv2 ParamEnv P (toRExp e2) nF2 ->
eval_exp (Q2R RationalSimps.machineEpsilon) (updEnv 2 nF2 (updEnv 1 nF1 VarEnv2)) ParamEnv P (toRExp (Binop Mult (Var Q 1) (Var Q 2))) nF ->
validErrorbound (Binop Mult e1 e2) absenv = true ->
validIntervalbounds (Binop Mult e1 e2) absenv P = true ->
(Q2R e1lo <= nR1 <= Q2R e1hi)%R ->
(Q2R e2lo <= nR2 <= Q2R e2hi)%R ->
absenv e1 = ((e1lo,e1hi),err1) ->
absenv e2 = ((e2lo, e2hi),err2) ->
absenv (Binop Mult e1 e2) = ((alo,ahi),e)->
......@@ -375,11 +371,11 @@ Lemma validErrorboundCorrectMult cenv absenv (e1:exp Q) (e2:exp Q) (nR nR1 nR2 n
(Rabs (nR2 - nF2) <= (Q2R err2))%R ->
(Rabs (nR - nF) <= (Q2R e))%R.
Proof.
intros e1_real e2_real eval_real e1_float e2_float eval_float
valid_error valid_intv absenv_e1 absenv_e2 absenv_mult
intros approxCEnv e1_real e2_real eval_real e1_float e2_float eval_float
valid_error valid_e1 valid_e2 absenv_e1 absenv_e2 absenv_mult
err1_bounded err2_bounded.
eapply Rle_trans.
eapply (mult_abs_err_bounded (toRExp e1) _ _ (toRExp e2)); eauto.
eapply (mult_abs_err_bounded e1 _ _ e2); eauto.
unfold validErrorbound in valid_error at 1.
rewrite absenv_mult, absenv_e1, absenv_e2 in valid_error.
andb_to_prop valid_error.
......@@ -398,41 +394,38 @@ Proof.
eapply Rle_trans.
Focus 2.
apply valid_error.
(* Simplify Interval correctness assumption *)
simpl in valid_intv.
rewrite absenv_mult, absenv_e1, absenv_e2 in valid_intv.
andb_to_prop valid_intv.
pose proof (validIntervalbounds_sound _ _ _ _ _ L0 e1_real) as valid_e1.
pose proof (validIntervalbounds_sound _ _ _ _ _ R1 e2_real) as valid_e2.
apply Rplus_le_compat.
- unfold Rabs in err1_bounded.
unfold Rabs in err2_bounded.
(* Before doing case distinction, prove bounds that will be used many times: *)
assert (nR1 <= RmaxAbsFun (Q2R e1lo, Q2R e1hi))%R
as upperBound_nR1
by (apply contained_leq_maxAbs_val; unfold contained;
rewrite absenv_e1 in valid_e1; simpl; auto).
by (apply contained_leq_maxAbs_val; unfold contained; auto).
assert (nR2 <= RmaxAbsFun (Q2R e2lo, Q2R e2hi))%R
as upperBound_nR2
by (apply contained_leq_maxAbs_val; unfold contained;
rewrite absenv_e2 in valid_e2; simpl; auto).
by (apply contained_leq_maxAbs_val; unfold contained; auto).
assert (-nR1 <= RmaxAbsFun (Q2R e1lo, Q2R e1hi))%R
as upperBound_Ropp_nR1
by (apply contained_leq_maxAbs_neg_val; unfold contained;
rewrite absenv_e1 in valid_e1; simpl; auto).
by (apply contained_leq_maxAbs_neg_val; unfold contained; auto).
assert (- nR2 <= RmaxAbsFun (Q2R e2lo, Q2R e2hi))%R
as upperBound_Ropp_nR2
by (apply contained_leq_maxAbs_neg_val; unfold contained;
rewrite absenv_e2 in valid_e2; simpl; auto).
assert (nR1 * Q2R err2 <= RmaxAbsFun (Q2R e1lo, Q2R e1hi) * Q2R err2)%R as bound_nR1 by (apply Rmult_le_compat_r; auto).
assert (- nR1 * Q2R err2 <= RmaxAbsFun (Q2R e1lo, Q2R e1hi) * Q2R err2)%R as bound_neg_nR1 by (apply Rmult_le_compat_r; auto).
assert (nR2 * Q2R err1 <= RmaxAbsFun (Q2R e2lo, Q2R e2hi) * Q2R err1)%R as bound_nR2 by (apply Rmult_le_compat_r; auto).
assert (- nR2 * Q2R err1 <= RmaxAbsFun (Q2R e2lo, Q2R e2hi) * Q2R err1)%R as bound_neg_nR2 by (apply Rmult_le_compat_r; auto).
by (apply contained_leq_maxAbs_neg_val; unfold contained; auto).
assert (nR1 * Q2R err2 <= RmaxAbsFun (Q2R e1lo, Q2R e1hi) * Q2R err2)%R
as bound_nR1 by (apply Rmult_le_compat_r; auto).
assert (- nR1 * Q2R err2 <= RmaxAbsFun (Q2R e1lo, Q2R e1hi) * Q2R err2)%R
as bound_neg_nR1 by (apply Rmult_le_compat_r; auto).
assert (nR2 * Q2R err1 <= RmaxAbsFun (Q2R e2lo, Q2R e2hi) * Q2R err1)%R
as bound_nR2 by (apply Rmult_le_compat_r; auto).
assert (- nR2 * Q2R err1 <= RmaxAbsFun (Q2R e2lo, Q2R e2hi) * Q2R err1)%R
as bound_neg_nR2 by (apply Rmult_le_compat_r; auto).
assert (- (Q2R err1 * Q2R err2) <= Q2R err1 * Q2R err2)%R as err_neg_bound
by (rewrite Ropp_mult_distr_l; apply Rmult_le_compat_r; lra).
assert (0 <= RmaxAbsFun (Q2R e1lo, Q2R e1hi) * Q2R err2)%R as zero_up_nR1 by lra.
assert (RmaxAbsFun (Q2R e1lo, Q2R e1hi) * Q2R err2 <= RmaxAbsFun (Q2R e1lo, Q2R e1hi) * Q2R err2 + RmaxAbsFun (Q2R e2lo, Q2R e2hi) * Q2R err1)%R as nR1_to_sum by lra.
assert (RmaxAbsFun (Q2R e1lo, Q2R e1hi) * Q2R err2 + RmaxAbsFun (Q2R e2lo, Q2R e2hi) * Q2R err1 <= RmaxAbsFun (Q2R e1lo, Q2R e1hi) * Q2R err2 + RmaxAbsFun (Q2R e2lo, Q2R e2hi) * Q2R err1 + Q2R err1 * Q2R err2)%R as sum_to_errsum by lra.
assert (0 <= RmaxAbsFun (Q2R e1lo, Q2R e1hi) * Q2R err2)%R
as zero_up_nR1 by lra.
assert (RmaxAbsFun (Q2R e1lo, Q2R e1hi) * Q2R err2 <= RmaxAbsFun (Q2R e1lo, Q2R e1hi) * Q2R err2 + RmaxAbsFun (Q2R e2lo, Q2R e2hi) * Q2R err1)%R
as nR1_to_sum by lra.
assert (RmaxAbsFun (Q2R e1lo, Q2R e1hi) * Q2R err2 + RmaxAbsFun (Q2R e2lo, Q2R e2hi) * Q2R err1 <= RmaxAbsFun (Q2R e1lo, Q2R e1hi) * Q2R err2 + RmaxAbsFun (Q2R e2lo, Q2R e2hi) * Q2R err1 + Q2R err1 * Q2R err2)%R
as sum_to_errsum by lra.
clear e1_real e1_float e2_real e2_float eval_real eval_float valid_error
absenv_e1 absenv_e2.
(* Large case distinction for
......@@ -864,14 +857,8 @@ Proof.
assert (ivlo iv = ivl) by (rewrite iv_unf; auto).
assert (ivhi iv = ivh) by (rewrite iv_unf; auto).
rewrite <- H, <- H0.
pose proof (validIntervalbounds_sound _ _ _ _ _ L0 e1_real) as valid_bounds_e1.
rewrite absenv_e1 in valid_bounds_e1.
simpl in valid_bounds_e1.
pose proof (distance_gives_iv nR1 nF1 (Q2R err1) (Q2R e1lo, Q2R e1hi) valid_bounds_e1 err1_bounded).
pose proof (validIntervalbounds_sound _ _ _ _ _ R1 e2_real) as valid_bounds_e2.
rewrite absenv_e2 in valid_bounds_e2.
simpl in valid_bounds_e2.
pose proof (distance_gives_iv nR2 nF2 (Q2R err2) (Q2R e2lo, Q2R e2hi) valid_bounds_e2 err2_bounded).
pose proof (distance_gives_iv nR1 nF1 (Q2R err1) (Q2R e1lo, Q2R e1hi) valid_e1 err1_bounded).
pose proof (distance_gives_iv nR2 nF2 (Q2R err2) (Q2R e2lo, Q2R e2hi) valid_e2 err2_bounded).
pose proof (IntervalArith.interval_multiplication_valid _ _ _ _ H1 H2).
unfold IntervalArith.contained in H3.
destruct H3.
......@@ -889,15 +876,20 @@ Proof.
repeat rewrite Q2R_plus; auto.
Qed.
Lemma validErrorboundCorrectDiv cenv absenv (e1:exp Q) (e2:exp Q) (nR nR1 nR2 nF nF1 nF2 :R) (e err1 err2 :error) (alo ahi e1lo e1hi e2lo e2hi:Q) P :
eval_exp 0%R cenv P (toRExp e1) nR1 ->
eval_exp 0%R cenv P (toRExp e2) nR2 ->
eval_exp 0%R cenv P (toRExp (Binop Div e1 e2)) nR ->
eval_exp (Q2R RationalSimps.machineEpsilon) cenv P (toRExp e1) nF1 ->
eval_exp (Q2R RationalSimps.machineEpsilon) cenv P (toRExp e2) nF2 ->
eval_exp (Q2R RationalSimps.machineEpsilon) (updEnv 2 nF2 (updEnv 1 nF1 cenv)) P (toRExp (Binop Div (Var Q 1) (Var Q 2))) nF ->
Lemma validErrorboundCorrectDiv VarEnv1 VarEnv2 ParamEnv absenv
(e1:exp Q) (e2:exp Q) (nR nR1 nR2 nF nF1 nF2 :R) (e err1 err2 :error)
(alo ahi e1lo e1hi e2lo e2hi:Q) P :
approxEnv VarEnv1 absenv VarEnv2 ->
eval_exp 0%R VarEnv1 ParamEnv P (toRExp e1) nR1 ->
eval_exp 0%R VarEnv1 ParamEnv P (toRExp e2) nR2 ->
eval_exp 0%R VarEnv1 ParamEnv P (toRExp (Binop Div e1 e2)) nR ->
eval_exp (Q2R RationalSimps.machineEpsilon) VarEnv2 ParamEnv P (toRExp e1) nF1 ->
eval_exp (Q2R RationalSimps.machineEpsilon) VarEnv2 ParamEnv P (toRExp e2) nF2 ->
eval_exp (Q2R RationalSimps.machineEpsilon) (updEnv 2 nF2 (updEnv 1 nF1 VarEnv2)) ParamEnv P (toRExp (Binop Div (Var Q 1) (Var Q 2))) nF ->
validErrorbound (Binop Div e1 e2) absenv = true ->
validIntervalbounds (Binop Div e1 e2) absenv P = true ->
(Q2R e1lo <= nR1 <= Q2R e1hi)%R ->
(Q2R e2lo <= nR2 <= Q2R e2hi)%R ->
(Qleb e2hi 0 && negb (Qeq_bool e2hi 0) || Qleb 0 e2lo && negb (Qeq_bool e2lo 0) = true) ->
absenv e1 = ((e1lo,e1hi),err1) ->
absenv e2 = ((e2lo, e2hi),err2) ->
absenv (Binop Div e1 e2) = ((alo,ahi),e)->
......@@ -905,31 +897,21 @@ Lemma validErrorboundCorrectDiv cenv absenv (e1:exp Q) (e2:exp Q) (nR nR1 nR2 nF
(Rabs (nR2 - nF2) <= (Q2R err2))%R ->