Library Coq.micromega.RMicromega


Require Import OrderedRing.
Require Import QMicromega RingMicromega.
Require Import Refl.
Require Import Sumbool Raxioms Rfunctions RIneq Rpow_def.
Require Import QArith.
Require Import Qfield.
Require Import Qreals.
Require Import DeclConstant.

Require Setoid.

Definition Rsrt : ring_theory R0 R1 Rplus Rmult Rminus Ropp (@eq R).

Local Open Scope R_scope.

Lemma Rsor : SOR R0 R1 Rplus Rmult Rminus Ropp (@eq R) Rle Rlt.

Lemma Rinv_1 : forall x, x * / 1 = x.

Lemma Qeq_true : forall x y, Qeq_bool x y = true -> Q2R x = Q2R y.

Lemma Qeq_false : forall x y, Qeq_bool x y = false -> Q2R x <> Q2R y.

Lemma Qle_true : forall x y : Q, Qle_bool x y = true -> Q2R x <= Q2R y.

Lemma Q2R_0 : Q2R 0 = 0.

Lemma Q2R_1 : Q2R 1 = 1.

Lemma Q2R_inv_ext : forall x,
  Q2R (/ x) = (if Qeq_bool x 0 then 0 else / Q2R x).

Notation to_nat := N.to_nat.

Lemma QSORaddon :
  @SORaddon R
  R0 R1 Rplus Rmult Rminus Ropp (@eq R) Rle
  Q 0%Q 1%Q Qplus Qmult Qminus Qopp
  Qeq_bool Qle_bool
  Q2R nat to_nat pow.


Inductive Rcst :=
  | C0
  | C1
  | CQ (r : Q)
  | CZ (r : Z)
  | CPlus (r1 r2 : Rcst)
  | CMinus (r1 r2 : Rcst)
  | CMult (r1 r2 : Rcst)
  | CPow (r1 : Rcst) (z:Z+nat)
  | CInv (r : Rcst)
  | COpp (r : Rcst).


Definition z_of_exp (z : Z + nat) :=
  match z with
  | inl z => z
  | inr n => Z.of_nat n
  end.

Fixpoint Q_of_Rcst (r : Rcst) : Q :=
  match r with
    | C0 => 0 # 1
    | C1 => 1 # 1
    | CZ z => z # 1
    | CQ q => q
    | CPlus r1 r2 => Qplus (Q_of_Rcst r1) (Q_of_Rcst r2)
    | CMinus r1 r2 => Qminus (Q_of_Rcst r1) (Q_of_Rcst r2)
    | CMult r1 r2 => Qmult (Q_of_Rcst r1) (Q_of_Rcst r2)
    | CPow r1 z => Qpower (Q_of_Rcst r1) (z_of_exp z)
    | CInv r => Qinv (Q_of_Rcst r)
    | COpp r => Qopp (Q_of_Rcst r)
  end.

Definition is_neg (z: Z+nat) :=
  match z with
  | inl (Zneg _) => true
  | _ => false
  end.

Lemma is_neg_true : forall z, is_neg z = true -> (z_of_exp z < 0)%Z.

Lemma is_neg_false : forall z, is_neg z = false -> (z_of_exp z >= 0)%Z.

Definition CInvR0 (r : Rcst) := Qeq_bool (Q_of_Rcst r) (0 # 1).

Definition CPowR0 (z : Z) (r : Rcst) :=
  Z.ltb z Z0 && Qeq_bool (Q_of_Rcst r) (0 # 1).

Fixpoint R_of_Rcst (r : Rcst) : R :=
  match r with
    | C0 => R0
    | C1 => R1
    | CZ z => IZR z
    | CQ q => Q2R q
    | CPlus r1 r2 => (R_of_Rcst r1) + (R_of_Rcst r2)
    | CMinus r1 r2 => (R_of_Rcst r1) - (R_of_Rcst r2)
    | CMult r1 r2 => (R_of_Rcst r1) * (R_of_Rcst r2)
    | CPow r1 z =>
      match z with
      | inl z =>
        if CPowR0 z r1
        then R0
        else powerRZ (R_of_Rcst r1) z
      | inr n => pow (R_of_Rcst r1) n
      end
    | CInv r =>
      if CInvR0 r then R0
      else Rinv (R_of_Rcst r)
    | COpp r => - (R_of_Rcst r)
  end.

Add Morphism Q2R with signature Qeq ==> @eq R as Q2R_m.
Qed.

Lemma Q2R_pow_pos : forall q p,
    Q2R (pow_pos Qmult q p) = pow_pos Rmult (Q2R q) p.

Lemma Q2R_pow_N : forall q n,
  Q2R (pow_N 1%Q Qmult q n) = pow_N 1 Rmult (Q2R q) n.

Lemma Qmult_integral : forall q r, q * r == 0 -> q == 0 \/ r == 0.

Lemma Qpower_positive_eq_zero : forall q p,
    Qpower_positive q p == 0 -> q == 0.

Lemma Qpower_positive_zero : forall p,
    Qpower_positive 0 p == 0%Q.

Lemma Q2RpowerRZ :
  forall q z
         (DEF : not (q == 0)%Q \/ (z >= Z0)%Z),
    Q2R (q ^ z) = powerRZ (Q2R q) z.

Lemma Qpower0 : forall z, (z <> 0)%Z -> (0 ^ z == 0)%Q.

Lemma Q_of_RcstR : forall c, Q2R (Q_of_Rcst c) = R_of_Rcst c.

Require Import EnvRing.

Definition INZ (n:N) : R :=
  match n with
    | N0 => IZR 0%Z
    | Npos p => IZR (Zpos p)
  end.

Definition Reval_expr := eval_pexpr Rplus Rmult Rminus Ropp R_of_Rcst N.to_nat pow.

Definition Reval_pop2 (o:Op2) : R -> R -> Prop :=
    match o with
      | OpEq => @eq R
      | OpNEq => fun x y => ~ x = y
      | OpLe => Rle
      | OpGe => Rge
      | OpLt => Rlt
      | OpGt => Rgt
    end.

Definition sumboolb {A B : Prop} (x : @sumbool A B) : bool :=
  if x then true else false.

Definition Reval_bop2 (o : Op2) : R -> R -> bool :=
  match o with
  | OpEq => fun x y => sumboolb (Req_EM_T x y)
  | OpNEq => fun x y => negb (sumboolb (Req_EM_T x y))
  | OpLe => fun x y => (sumboolb (Rle_lt_dec x y))
  | OpGe => fun x y => (sumboolb (Rge_gt_dec x y))
  | OpLt => fun x y => (sumboolb (Rlt_le_dec x y))
  | OpGt => fun x y => (sumboolb (Rgt_dec x y))
  end.

Lemma pop2_bop2 :
  forall (op : Op2) (r1 r2 : R), is_true (Reval_bop2 op r1 r2) <-> Reval_pop2 op r1 r2.

Definition Reval_op2 (k: Tauto.kind) : Op2 -> R -> R -> Tauto.rtyp k:=
  if k as k0 return (Op2 -> R -> R -> Tauto.rtyp k0)
  then Reval_pop2 else Reval_bop2.

Lemma Reval_op2_hold : forall b op q1 q2,
    Tauto.hold b (Reval_op2 b op q1 q2) <-> Reval_pop2 op q1 q2.

Definition Reval_formula (e: PolEnv R) (k: Tauto.kind) (ff : Formula Rcst) :=
  let (lhs,o,rhs) := ff in Reval_op2 k o (Reval_expr e lhs) (Reval_expr e rhs).

Definition Reval_formula' :=
  eval_sformula Rplus Rmult Rminus Ropp (@eq R) Rle Rlt N.to_nat pow R_of_Rcst.

Lemma Reval_pop2_eval_op2 : forall o e1 e2,
  Reval_pop2 o e1 e2 <->
  eval_op2 eq Rle Rlt o e1 e2.

Lemma Reval_formula_compat : forall env b f, Tauto.hold b (Reval_formula env b f) <-> Reval_formula' env f.

Definition QReval_expr := eval_pexpr Rplus Rmult Rminus Ropp Q2R to_nat pow.

Definition QReval_formula (e: PolEnv R) (k: Tauto.kind) (ff : Formula Q) :=
  let (lhs,o,rhs) := ff in Reval_op2 k o (QReval_expr e lhs) (QReval_expr e rhs).

Definition QReval_formula' :=
  eval_formula Rplus Rmult Rminus Ropp (@eq R) Rle Rlt Q2R N.to_nat pow.

Lemma QReval_formula_compat : forall env b f, Tauto.hold b (QReval_formula env b f) <-> QReval_formula' env f.

Definition Qeval_nformula :=
  eval_nformula 0 Rplus Rmult (@eq R) Rle Rlt Q2R.

Lemma Reval_nformula_dec : forall env d, (Qeval_nformula env d) \/ ~ (Qeval_nformula env d).

Definition RWitness := Psatz Q.

Definition RWeakChecker := check_normalised_formulas 0%Q 1%Q Qplus Qmult Qeq_bool Qle_bool.

Require Import List.

Lemma RWeakChecker_sound : forall (l : list (NFormula Q)) (cm : RWitness),
  RWeakChecker l cm = true ->
  forall env, make_impl (Qeval_nformula env) l False.

Require Import Coq.micromega.Tauto.

Definition Rnormalise := @cnf_normalise Q 0%Q 1%Q Qplus Qmult Qminus Qopp Qeq_bool Qle_bool.
Definition Rnegate := @cnf_negate Q 0%Q 1%Q Qplus Qmult Qminus Qopp Qeq_bool Qle_bool.

Definition runsat := check_inconsistent 0%Q Qeq_bool Qle_bool.

Definition rdeduce := nformula_plus_nformula 0%Q Qplus Qeq_bool.

Definition RTautoChecker (f : BFormula (Formula Rcst) Tauto.isProp) (w: list RWitness) : bool :=
  @tauto_checker (Formula Q) (NFormula Q)
  unit runsat rdeduce
  (Rnormalise unit) (Rnegate unit)
  RWitness (fun cl => RWeakChecker (List.map fst cl)) (map_bformula (map_Formula Q_of_Rcst) f) w.

Lemma RTautoChecker_sound : forall f w, RTautoChecker f w = true -> forall env, eval_bf (Reval_formula env) f.