Commit 92da81e9 authored by Heiko Becker's avatar Heiko Becker

Port Error validator to finite maps, some proof simplification in interval validator

parent 41b255c9
...@@ -6,23 +6,21 @@ ...@@ -6,23 +6,21 @@
encoded in the analysis result. The validator is used in the file encoded in the analysis result. The validator is used in the file
CertificateChecker.v to build the complete checker. CertificateChecker.v to build the complete checker.
**) **)
Require Import Coq.QArith.QArith Coq.QArith.Qminmax Coq.QArith.Qabs From Coq
Coq.QArith.Qreals Coq.micromega.Psatz Coq.Reals.Reals. Require Import QArith.QArith QArith.Qminmax QArith.Qabs QArith.Qreals
Require Import Daisy.Infra.Abbrevs Daisy.Infra.RationalSimps micromega.Psatz Reals.Reals.
Daisy.Infra.RealRationalProps Daisy.Infra.RealSimps From Daisy
Daisy.Infra.Ltacs Daisy.Environments Require Import Infra.Abbrevs Infra.RationalSimps Infra.RealRationalProps
Daisy.IntervalValidation Daisy.Typing Daisy.ErrorBounds. Infra.RealSimps Infra.Ltacs Environments IntervalValidation Typing
ErrorBounds.
(** Error bound validator **) (** Error bound validator **)
Fixpoint validErrorbound (e:exp Q) (* analyzed expression *) Fixpoint validErrorbound (e:exp Q) (* analyzed expression *)
(typeMap:exp Q -> option mType) (* derived types for e *) (typeMap:DaisyMap.t mType) (* derived types for e *)
(A:analysisResult) (* encoded result of Daisy *) (A:analysisResult) (* encoded result of Daisy *)
(dVars:NatSet.t) (* let-bound variables encountered previously *):= (dVars:NatSet.t) (* let-bound variables encountered previously *):=
let (intv, err) := (A e) in match DaisyMap.find e A, DaisyMap.find e typeMap with
let mopt := typeMap e in | Some (intv, err), Some m =>
match mopt with
| None => false
| Some m =>
if (Qleb 0 err) (* encoding soundness: errors are positive *) if (Qleb 0 err) (* encoding soundness: errors are positive *)
then then
match e with (* case analysis for the expression *) match e with (* case analysis for the expression *)
...@@ -34,60 +32,74 @@ Fixpoint validErrorbound (e:exp Q) (* analyzed expression *) ...@@ -34,60 +32,74 @@ Fixpoint validErrorbound (e:exp Q) (* analyzed expression *)
Qleb (maxAbs intv * (mTypeToQ m)) err Qleb (maxAbs intv * (mTypeToQ m)) err
|Unop Neg e1 => |Unop Neg e1 =>
if (validErrorbound e1 typeMap A dVars) if (validErrorbound e1 typeMap A dVars)
then Qeq_bool err (snd (A e1)) then
match DaisyMap.find e1 A with
| Some (iv_e1, err1) => Qeq_bool err err1
| None => false
end
else false else false
|Unop Inv e1 => false |Unop Inv e1 => false
|Binop b e1 e2 => |Binop b e1 e2 =>
if ((validErrorbound e1 typeMap A dVars) if ((validErrorbound e1 typeMap A dVars)
&& (validErrorbound e2 typeMap A dVars)) && (validErrorbound e2 typeMap A dVars))
then then
let (ive1, err1) := A e1 in match DaisyMap.find e1 A, DaisyMap.find e2 A with
let (ive2, err2) := A e2 in | Some (ive1, err1), Some (ive2, err2) =>
let errIve1 := widenIntv ive1 err1 in let errIve1 := widenIntv ive1 err1 in
let errIve2 := widenIntv ive2 err2 in let errIve2 := widenIntv ive2 err2 in
let upperBoundE1 := maxAbs ive1 in let upperBoundE1 := maxAbs ive1 in
let upperBoundE2 := maxAbs ive2 in let upperBoundE2 := maxAbs ive2 in
match b with match b with
| Plus => | Plus =>
Qleb (err1 + err2 + (maxAbs (addIntv errIve1 errIve2)) * (mTypeToQ m)) err Qleb (err1 + err2 + (maxAbs (addIntv errIve1 errIve2)) * (mTypeToQ m)) err
| Sub => | Sub =>
Qleb (err1 + err2 + (maxAbs (subtractIntv errIve1 errIve2)) * (mTypeToQ m)) err Qleb (err1 + err2 + (maxAbs (subtractIntv errIve1 errIve2)) * (mTypeToQ m)) err
| Mult => | Mult =>
Qleb ((upperBoundE1 * err2 + upperBoundE2 * err1 + err1 * err2) + (maxAbs (multIntv errIve1 errIve2)) * (mTypeToQ m)) err Qleb ((upperBoundE1 * err2 + upperBoundE2 * err1 + err1 * err2) + (maxAbs (multIntv errIve1 errIve2)) * (mTypeToQ m)) err
| Div => | Div =>
if (((Qleb (ivhi errIve2) 0) && (negb (Qeq_bool (ivhi errIve2) 0))) || if (((Qleb (ivhi errIve2) 0) && (negb (Qeq_bool (ivhi errIve2) 0))) ||
((Qleb 0 (ivlo errIve2)) && (negb (Qeq_bool (ivlo errIve2) 0)))) ((Qleb 0 (ivlo errIve2)) && (negb (Qeq_bool (ivlo errIve2) 0))))
then then
let upperBoundInvE2 := maxAbs (invertIntv ive2) in let upperBoundInvE2 := maxAbs (invertIntv ive2) in
let minAbsIve2 := minAbs (errIve2) in let minAbsIve2 := minAbs (errIve2) in
let errInv := (1 / (minAbsIve2 * minAbsIve2)) * err2 in let errInv := (1 / (minAbsIve2 * minAbsIve2)) * err2 in
Qleb ((upperBoundE1 * errInv + upperBoundInvE2 * err1 + err1 * errInv) + (maxAbs (divideIntv errIve1 errIve2)) * (mTypeToQ m)) err Qleb ((upperBoundE1 * errInv + upperBoundInvE2 * err1 + err1 * errInv) + (maxAbs (divideIntv errIve1 errIve2)) * (mTypeToQ m)) err
else false else false
end
| _, _ => false
end end
else false else false
|Downcast m1 e1 => |Downcast m1 e1 =>
if validErrorbound e1 typeMap A dVars if validErrorbound e1 typeMap A dVars
then then
let (ive1, err1) := A e1 in match DaisyMap.find e1 A with
let errIve1 := widenIntv ive1 err1 in | Some (ive1, err1) =>
(Qleb (err1 + maxAbs errIve1 * (mTypeToQ m1)) err) let errIve1 := widenIntv ive1 err1 in
(Qleb (err1 + maxAbs errIve1 * (mTypeToQ m1)) err)
| None => false
end
else else
false false
end end
else false else false
| _, _ => false
end. end.
(** Error bound command validator **) (** Error bound command validator **)
Fixpoint validErrorboundCmd (f:cmd Q) (* analyzed cmd with let's *) Fixpoint validErrorboundCmd (f:cmd Q) (* analyzed cmd with let's *)
(typeMap:exp Q -> option mType) (* inferred types *) typeMap (* inferred types *)
(A:analysisResult) (* Daisy's encoded result *) (A:analysisResult) (* Daisy's encoded result *)
(dVars:NatSet.t) (* defined variables *) (dVars:NatSet.t) (* defined variables *)
: bool := : bool :=
match f with match f with
|Let m x e g => |Let m x e g =>
if ((validErrorbound e typeMap A dVars) && (Qeq_bool (snd (A e)) (snd (A (Var Q x))))) match DaisyMap.find e A, DaisyMap.find (Var Q x) A with
then validErrorboundCmd g typeMap A (NatSet.add x dVars) | Some (iv_e, err_e), Some (iv_x, err_x) =>
else false if ((validErrorbound e typeMap A dVars) && (Qeq_bool err_e err_x))
then validErrorboundCmd g typeMap A (NatSet.add x dVars)
else false
| _,_ => false
end
|Ret e => validErrorbound e typeMap A dVars |Ret e => validErrorbound e typeMap A dVars
end. end.
......
...@@ -91,6 +91,15 @@ Ltac match_simpl := ...@@ -91,6 +91,15 @@ Ltac match_simpl :=
repeat match_factorize; repeat match_factorize;
try pair_factorize. try pair_factorize.
Ltac bool_factorize :=
match goal with
| [H: _ = true |- _] => andb_to_prop H
end.
Ltac Daisy_compute :=
repeat
(match_simpl || bool_factorize).
(* Ltac destruct_if := *) (* Ltac destruct_if := *)
(* match goal with *) (* match goal with *)
(* | [H: if ?c then ?a else ?b = _ |- _ ] => *) (* | [H: if ?c then ?a else ?b = _ |- _ ] => *)
......
...@@ -105,22 +105,20 @@ Theorem ivbounds_approximatesPrecond_sound f A P dVars iv err: ...@@ -105,22 +105,20 @@ Theorem ivbounds_approximatesPrecond_sound f A P dVars iv err:
Proof. Proof.
induction f; cbn; intros approx_true var var_in_fV find_A; set_tac. induction f; cbn; intros approx_true var var_in_fV find_A; set_tac.
- subst. - subst.
match_simpl. Daisy_compute.
destruct (var mem dVars) eqn:?; set_tac; try congruence. destruct (var mem dVars) eqn:?; set_tac; try congruence.
andb_to_prop approx_true; unfold isSupersetIntv. Daisy_compute.
unfold isSupersetIntv.
apply andb_prop_intro; split; apply andb_prop_intro; split;
apply Is_true_eq_left; auto. apply Is_true_eq_left; auto.
- match_simpl. - Daisy_compute; try congruence.
andb_to_prop approx_true.
apply IHf; try auto. apply IHf; try auto.
set_tac. set_tac.
- match_simpl. - Daisy_compute; try congruence.
andb_to_prop approx_true.
destruct H. destruct H.
+ apply IHf1; try auto; set_tac. + apply IHf1; try auto; set_tac.
+ apply IHf2; try auto; set_tac. + apply IHf2; try auto; set_tac.
- match_simpl. - Daisy_compute; try congruence.
andb_to_prop approx_true.
apply IHf; try auto; set_tac. apply IHf; try auto; set_tac.
Qed. Qed.
...@@ -142,20 +140,16 @@ Lemma validBoundsDiv_uneq_zero e1 e2 A P V ivlo_e2 ivhi_e2 err: ...@@ -142,20 +140,16 @@ Lemma validBoundsDiv_uneq_zero e1 e2 A P V ivlo_e2 ivhi_e2 err:
(ivhi_e2 < 0) \/ (0 < ivlo_e2). (ivhi_e2 < 0) \/ (0 < ivlo_e2).
Proof. Proof.
intros A_eq validBounds; cbn in *. intros A_eq validBounds; cbn in *.
match_simpl. Daisy_compute; try congruence.
andb_to_prop validBounds.
repeat match_simpl.
andb_to_prop R.
unfold isSupersetIntv in *; simpl in *.
apply le_neq_bool_to_lt_prop; auto. apply le_neq_bool_to_lt_prop; auto.
Qed. Qed.
Definition dVars_range_valid (dVars:NatSet.t) (E:env) (A:analysisResult) :Prop := Definition dVars_range_valid (dVars:NatSet.t) (E:env) (A:analysisResult) :Prop :=
forall v, NatSet.In v dVars -> forall v, NatSet.In v dVars ->
exists vR ivlo ivhi err, exists vR iv err,
E v = Some vR /\ E v = Some vR /\
DaisyMap.find (Var Q v) A = Some ((ivlo, ivhi), err) /\ DaisyMap.find (Var Q v) A = Some (iv, err) /\
(Q2R ivlo <= vR <= Q2R ivhi)%R. (Q2R (fst iv) <= vR <= Q2R (snd iv))%R.
Definition fVars_P_sound (fVars:NatSet.t) (E:env) (P:precond) :Prop := Definition fVars_P_sound (fVars:NatSet.t) (E:env) (P:precond) :Prop :=
forall v, forall v,
...@@ -167,6 +161,11 @@ Definition vars_typed (S:NatSet.t) (Gamma: nat -> option mType) := ...@@ -167,6 +161,11 @@ Definition vars_typed (S:NatSet.t) (Gamma: nat -> option mType) :=
forall v, NatSet.In v S -> forall v, NatSet.In v S ->
exists m :mType, Gamma v = Some m. exists m :mType, Gamma v = Some m.
Ltac kill_trivial_exists :=
match goal with
| [ |- exists iv err v, Some (?i,?e) = Some (iv, err) /\ _ /\ _] => exists i, e
end.
Theorem validIntervalbounds_sound (f:exp Q) (A:analysisResult) (P:precond) Theorem validIntervalbounds_sound (f:exp Q) (A:analysisResult) (P:precond)
fVars dVars (E:env) Gamma: fVars dVars (E:env) Gamma:
validIntervalbounds f A P dVars = true -> validIntervalbounds f A P dVars = true ->
...@@ -174,22 +173,23 @@ Theorem validIntervalbounds_sound (f:exp Q) (A:analysisResult) (P:precond) ...@@ -174,22 +173,23 @@ Theorem validIntervalbounds_sound (f:exp Q) (A:analysisResult) (P:precond)
NatSet.Subset (NatSet.diff (Expressions.usedVars f) dVars) fVars -> NatSet.Subset (NatSet.diff (Expressions.usedVars f) dVars) fVars ->
fVars_P_sound fVars E P -> fVars_P_sound fVars E P ->
vars_typed (NatSet.union fVars dVars) Gamma -> vars_typed (NatSet.union fVars dVars) Gamma ->
exists ivlo ivhi err vR, exists iv err vR,
DaisyMap.find f A = Some ((ivlo, ivhi), err) /\ DaisyMap.find f A = Some (iv, err) /\
eval_exp E (toRMap Gamma) (toREval (toRExp f)) vR M0 /\ eval_exp E (toRMap Gamma) (toREval (toRExp f)) vR M0 /\
(Q2R ivlo <= vR <= Q2R ivhi)%R. (Q2R (fst iv) <= vR <= Q2R (snd iv))%R.
Proof. Proof.
induction f; induction f;
intros valid_bounds valid_definedVars usedVars_subset valid_freeVars types_defined; intros valid_bounds valid_definedVars usedVars_subset valid_freeVars types_defined;
cbn in *. cbn in *.
- match_simpl. - Daisy_compute.
destruct (NatSet.mem n dVars) eqn:?; simpl in *. destruct (NatSet.mem n dVars) eqn:?; simpl in *.
+ destruct (valid_definedVars n) + destruct (valid_definedVars n)
as [vR [ivlo_n [ivhi_n [err_n [env_valid [map_n bounds_valid]]]]]]; as [vR [iv_n [err_n [env_valid [map_n bounds_valid]]]]];
try set_tac. try set_tac.
rewrite map_n in *. rewrite map_n in *.
inversion Heqo; subst. inversion Heqo; subst.
exists ivlo_n, ivhi_n, e; eexists; split; [auto| split; try eauto ]. kill_trivial_exists.
eexists; split; [auto| split; try eauto ].
eapply Var_load; simpl; try auto. eapply Var_load; simpl; try auto.
destruct (types_defined n) as [m type_m]; destruct (types_defined n) as [m type_m];
set_tac. set_tac.
...@@ -199,43 +199,42 @@ Proof. ...@@ -199,43 +199,42 @@ Proof.
assert (NatSet.In n fVars) by set_tac. assert (NatSet.In n fVars) by set_tac.
andb_to_prop valid_bounds. andb_to_prop valid_bounds.
canonize_hyps; simpl in *. canonize_hyps; simpl in *.
exists (fst i), (snd i), e; eexists; split; kill_trivial_exists.
[destruct i; auto | split]. eexists; split; [auto | split].
* econstructor; try eauto. * econstructor; try eauto.
destruct (types_defined n) as [m type_m]; set_tac. destruct (types_defined n) as [m type_m];
set_tac.
match_simpl; auto. match_simpl; auto.
* lra. * lra.
- match_simpl. - Daisy_compute; canonize_hyps; simpl in *.
andb_to_prop valid_bounds. kill_trivial_exists.
canonize_hyps; simpl in *. exists (perturb (Q2R v) 0).
exists (fst i), (snd i), e, (perturb (Q2R v) 0). split; [auto| split].
split; [destruct i; auto| split].
+ econstructor; try eauto. apply Rabs_0_equiv. + econstructor; try eauto. apply Rabs_0_equiv.
+ unfold perturb; simpl; lra. + unfold perturb; simpl; lra.
- match_simpl. - Daisy_compute; simpl in *; try congruence.
andb_to_prop valid_bounds. destruct IHf as [iv_f [err_f [vF [iveq_f [eval_f valid_bounds_f]]]]];
match_simpl.
destruct IHf as [ivlo_f [ivhi_f [err_f [vF [iveq_f [eval_f valid_bounds_f]]]]]];
try auto. try auto.
destruct u; try andb_to_prop R. inversion iveq_f; subst.
+ exists (fst i), (snd i), e, (evalUnop Neg vF); split; destruct u; try andb_to_prop R; simpl in *.
[destruct i; auto | split ; + kill_trivial_exists.
exists (evalUnop Neg vF); split;
[auto | split ;
[econstructor; eauto | ]]. [econstructor; eauto | ]].
canonize_hyps; simpl in *. canonize_hyps.
rewrite Q2R_opp in *. rewrite Q2R_opp in *.
destruct valid_bounds_f. simpl; lra.
inversion iveq_f; subst; simpl in *; lra. + rename L0 into nodiv0.
+ inversion iveq_f; subst; simpl in *.
rename L0 into nodiv0.
apply le_neq_bool_to_lt_prop in nodiv0. apply le_neq_bool_to_lt_prop in nodiv0.
exists (fst i), (snd i), e, (perturb (evalUnop Inv vF) 0); split; kill_trivial_exists.
exists (perturb (evalUnop Inv vF) 0); split;
[destruct i; auto | split]. [destruct i; auto | split].
* econstructor; eauto; try apply Rabs_0_equiv. * econstructor; eauto; try apply Rabs_0_equiv.
(* Absence of division by zero *) (* Absence of division by zero *)
hnf. destruct nodiv0 as [nodiv0 | nodiv0]; apply Qlt_Rlt in nodiv0; hnf. destruct nodiv0 as [nodiv0 | nodiv0]; apply Qlt_Rlt in nodiv0;
rewrite Q2R0_is_0 in nodiv0; lra. rewrite Q2R0_is_0 in nodiv0; lra.
* canonize_hyps. * canonize_hyps.
pose proof (interval_inversion_valid ((Q2R ivlo_f),(Q2R ivhi_f)) (a :=vF)) as inv_valid. pose proof (interval_inversion_valid ((Q2R (fst iv_f)),(Q2R (snd iv_f))) (a :=vF)) as inv_valid.
unfold invertInterval in inv_valid; simpl in *. unfold invertInterval in inv_valid; simpl in *.
rewrite delta_0_deterministic; [| rewrite Rbasic_fun.Rabs_R0; lra]. rewrite delta_0_deterministic; [| rewrite Rbasic_fun.Rabs_R0; lra].
destruct inv_valid; try auto. destruct inv_valid; try auto.
...@@ -245,7 +244,7 @@ Proof. ...@@ -245,7 +244,7 @@ Proof.
- rewrite Q2R_inv; try auto. - rewrite Q2R_inv; try auto.
destruct nodiv0; try lra. destruct nodiv0; try lra.
hnf; intros. hnf; intros.
assert (0 < Q2R (ivhi_f))%R. assert (0 < Q2R (snd iv_f))%R.
{ eapply Rlt_le_trans. { eapply Rlt_le_trans.
apply Qlt_Rlt in H1. apply Qlt_Rlt in H1.
rewrite <- Q2R0_is_0. rewrite <- Q2R0_is_0.
...@@ -258,7 +257,7 @@ Proof. ...@@ -258,7 +257,7 @@ Proof.
- rewrite <- Q2R_inv; try auto. - rewrite <- Q2R_inv; try auto.
hnf; intros. hnf; intros.
destruct nodiv0; try lra. destruct nodiv0; try lra.
assert (Q2R ivlo_f < 0)%R. assert (Q2R (fst iv_f) < 0)%R.
{ eapply Rle_lt_trans. { eapply Rle_lt_trans.
Focus 2. Focus 2.
rewrite <- Q2R0_is_0; rewrite <- Q2R0_is_0;
...@@ -267,23 +266,23 @@ Proof. ...@@ -267,23 +266,23 @@ Proof.
} }
rewrite <- Q2R0_is_0 in H3. rewrite <- Q2R0_is_0 in H3.
apply Rlt_Qlt in H3. lra. } apply Rlt_Qlt in H3. lra. }
- match_simpl. - Daisy_compute; try congruence.
andb_to_prop valid_bounds. destruct IHf1 as [iv_f1 [err1 [vF1 [env1 [eval_f1 valid_f1]]]]];
repeat match_simpl.
destruct IHf1 as [ivlo_f1 [ivhi_f1 [err1 [vF1 [env1 [eval_f1 valid_f1]]]]]];
try auto; set_tac. try auto; set_tac.
destruct IHf2 as [ivlo_f2 [ivhi_f2 [err2 [vF2 [env2 [eval_f2 valid_f2]]]]]]; destruct IHf2 as [iv_f2 [err2 [vF2 [env2 [eval_f2 valid_f2]]]]];
try auto; set_tac. try auto; set_tac.
assert (M0 = join M0 M0) as M0_join by (cbv; auto); assert (M0 = join M0 M0) as M0_join by (cbv; auto);
rewrite M0_join. rewrite M0_join.
exists (fst i), (snd i), e, (perturb (evalBinop b vF1 vF2) 0); kill_trivial_exists.
exists (perturb (evalBinop b vF1 vF2) 0);
split; [destruct i; auto | ]. split; [destruct i; auto | ].
inversion env1; inversion env2; subst. inversion env1; inversion env2; subst.
destruct b; simpl in *. destruct b; simpl in *.
* split; * split;
[econstructor; try congruence; apply Rabs_0_equiv | ]. [econstructor; try congruence; apply Rabs_0_equiv | ].
pose proof (interval_addition_valid ((Q2R ivlo_f1), Q2R ivhi_f1) pose proof (interval_addition_valid ((Q2R (fst iv_f1)), Q2R (snd iv_f1))
(Q2R ivlo_f2, Q2R ivhi_f2)) as valid_add. (Q2R (fst iv_f2), Q2R (snd iv_f2)))
as valid_add.
specialize (valid_add vF1 vF2 valid_f1 valid_f2). specialize (valid_add vF1 vF2 valid_f1 valid_f2).
unfold isSupersetIntv in R. unfold isSupersetIntv in R.
andb_to_prop R. andb_to_prop R.
...@@ -293,8 +292,8 @@ Proof. ...@@ -293,8 +292,8 @@ Proof.
unfold perturb. lra. unfold perturb. lra.
* split; * split;
[econstructor; try congruence; apply Rabs_0_equiv |]. [econstructor; try congruence; apply Rabs_0_equiv |].
pose proof (interval_subtraction_valid (Q2R ivlo_f1, Q2R ivhi_f1) pose proof (interval_subtraction_valid ((Q2R (fst iv_f1)), Q2R (snd iv_f1))
(Q2R ivlo_f2, Q2R ivhi_f2)) (Q2R (fst iv_f2), Q2R (snd iv_f2)))
as valid_sub. as valid_sub.
specialize (valid_sub vF1 vF2 valid_f1 valid_f2). specialize (valid_sub vF1 vF2 valid_f1 valid_f2).
unfold isSupersetIntv in R. unfold isSupersetIntv in R.
...@@ -306,8 +305,8 @@ Proof. ...@@ -306,8 +305,8 @@ Proof.
unfold perturb; lra. unfold perturb; lra.
* split; * split;
[ econstructor; try congruence; apply Rabs_0_equiv |]. [ econstructor; try congruence; apply Rabs_0_equiv |].
pose proof (interval_multiplication_valid (Q2R ivlo_f1, Q2R ivhi_f1) pose proof (interval_multiplication_valid ((Q2R (fst iv_f1)), Q2R (snd iv_f1))
(Q2R ivlo_f2, Q2R ivhi_f2)) (Q2R (fst iv_f2), Q2R (snd iv_f2)))
as valid_mul. as valid_mul.
specialize (valid_mul vF1 vF2 valid_f1 valid_f2). specialize (valid_mul vF1 vF2 valid_f1 valid_f2).
unfold isSupersetIntv in R. unfold isSupersetIntv in R.
...@@ -325,19 +324,19 @@ Proof. ...@@ -325,19 +324,19 @@ Proof.
{ hnf; intros. { hnf; intros.
destruct L as [L | L]; apply Qlt_Rlt in L; rewrite Q2R0_is_0 in L; lra. } destruct L as [L | L]; apply Qlt_Rlt in L; rewrite Q2R0_is_0 in L; lra. }
{ pose proof (interval_division_valid (a:=vF1) (b:=vF2) { pose proof (interval_division_valid (a:=vF1) (b:=vF2)
(Q2R ivlo_f1, Q2R ivhi_f1) ((Q2R (fst iv_f1)), Q2R (snd iv_f1))
(Q2R ivlo_f2, Q2R ivhi_f2)) (Q2R (fst iv_f2), Q2R (snd iv_f2)))
as valid_div. as valid_div.
simpl in *. simpl in *.
destruct valid_div; try auto. destruct valid_div; try auto.
- destruct L; rewrite <- Q2R0_is_0; [left | right]; apply Qlt_Rlt; auto. - destruct L; rewrite <- Q2R0_is_0; [left | right]; apply Qlt_Rlt; auto.
- assert (~ ivhi_f2 == 0). - assert (~ (snd iv_f2) == 0).
{ hnf; intros. destruct L; try lra. { hnf; intros. destruct L; try lra.
assert (0 < ivhi_f2) by (apply Rlt_Qlt; apply Qlt_Rlt in H2; lra). assert (0 < (snd iv_f2)) by (apply Rlt_Qlt; apply Qlt_Rlt in H2; lra).
lra. } lra. }
assert (~ ivlo_f2 == 0). assert (~ (fst iv_f2) == 0).
{ hnf; intros; destruct L; try lra. { hnf; intros; destruct L; try lra.
assert (ivlo_f2 < 0) by (apply Rlt_Qlt; apply Qlt_Rlt in H3; lra). assert ((fst iv_f2) < 0) by (apply Rlt_Qlt; apply Qlt_Rlt in H3; lra).
lra. } lra. }
repeat (rewrite <- Q2R_inv in *; try auto). repeat (rewrite <- Q2R_inv in *; try auto).
repeat rewrite <- Q2R_mult in *. repeat rewrite <- Q2R_mult in *.
...@@ -348,10 +347,11 @@ Proof. ...@@ -348,10 +347,11 @@ Proof.
- match_simpl. - match_simpl.
andb_to_prop valid_bounds. andb_to_prop valid_bounds.
match_simpl. match_simpl.
destruct IHf as [ivlo_f [ivhi_f [err_f [vF [env_f [eval_f valid_f]]]]]]; destruct IHf as [iv_f [err_f [vF [env_f [eval_f valid_f]]]]];
try auto. try auto.
inversion env_f; subst. inversion env_f; subst.
exists (fst i), (snd i), e, (perturb vF 0). kill_trivial_exists.
exists (perturb vF 0).
split; [destruct i; try auto |]. split; [destruct i; try auto |].
split; [try econstructor; try eauto; try apply Rabs_0_equiv; unfold isMorePrecise; auto |]. split; [try econstructor; try eauto; try apply Rabs_0_equiv; unfold isMorePrecise; auto |].
unfold isSupersetIntv in *; andb_to_prop R. unfold isSupersetIntv in *; andb_to_prop R.
...@@ -407,20 +407,20 @@ Theorem validIntervalboundsCmd_sound (f:cmd Q) (A:analysisResult) Gamma: ...@@ -407,20 +407,20 @@ Theorem validIntervalboundsCmd_sound (f:cmd Q) (A:analysisResult) Gamma:
vars_typed (NatSet.union fVars dVars) Gamma -> vars_typed (NatSet.union fVars dVars) Gamma ->
NatSet.Subset (NatSet.diff (Commands.freeVars f) dVars) fVars -> NatSet.Subset (NatSet.diff (Commands.freeVars f) dVars) fVars ->
validIntervalboundsCmd f A P dVars = true -> validIntervalboundsCmd f A P dVars = true ->
exists elo ehi err vR, exists iv_e err_e vR,
DaisyMap.find (getRetExp f) A = Some ((elo, ehi), err) /\ DaisyMap.find (getRetExp f) A = Some (iv_e, err_e) /\
bstep (toREvalCmd (toRCmd f)) E (toRMap Gamma) vR M0 /\ bstep (toREvalCmd (toRCmd f)) E (toRMap Gamma) vR M0 /\
(Q2R elo <= vR <= Q2R ehi)%R. (Q2R (fst iv_e) <= vR <= Q2R (snd iv_e))%R.
Proof. Proof.
revert Gamma. revert Gamma.
induction f; induction f;
intros * ssa_f dVars_sound fVars_valid types_valid usedVars_subset valid_bounds_f; intros * ssa_f dVars_sound fVars_valid types_valid usedVars_subset valid_bounds_f;
cbn in *. cbn in *.
- repeat match_simpl. andb_to_prop valid_bounds_f. - Daisy_compute.
inversion ssa_f; subst. inversion ssa_f; subst.
canonize_hyps. canonize_hyps.
pose proof (validIntervalbounds_sound e (Gamma:=Gamma) (E:=E) (fVars:=fVars) L) as validIV_e. pose proof (validIntervalbounds_sound e (Gamma:=Gamma) (E:=E) (fVars:=fVars) L) as validIV_e.
destruct validIV_e as [v_lo [v_hi [err_v [v [find_v [eval_e valid_bounds_e]]]]]]; destruct validIV_e as [iv_e [err_v [v [find_v [eval_e valid_bounds_e]]]]];
try auto. try auto.
{ set_tac. repeat split; auto.