Fixpoint max_var_psatz (w : Psatz Z) : positive :=
match w with
| PsatzIn _ n => xH
| PsatzSquare p => max_var xH (Psquare 0 1 Z.add Z.mul Zeq_bool p)
| PsatzMulC p w => Pos.max (max_var xH p) (max_var_psatz w)
| PsatzMulE w1 w2 => Pos.max (max_var_psatz w1) (max_var_psatz w2)
| PsatzAdd w1 w2  => Pos.max (max_var_psatz w1) (max_var_psatz w2)
| _   => xH
end.
Fixpoint max_var_prf (w : ZArithProof) : positive :=
match w with
| DoneProof => xH
| RatProof w pf | CutProof w pf => Pos.max (max_var_psatz w) (max_var_prf pf)
| SplitProof p pf1 pf2 => Pos.max (max_var xH p) (Pos.max (max_var_prf pf1) (max_var_prf pf1))
| EnumProof w1 w2 l => List.fold_left
(fun acc prf => Pos.max acc (max_var_prf prf)) l
(Pos.max (max_var_psatz w1) (max_var_psatz w2))
| ExProof _ pf => max_var_prf pf
end.
Fixpoint ZChecker  (l:list (NFormula Z)) (pf : ZArithProof)  {struct pf} : bool :=
match pf with
| DoneProof => false
| RatProof w pf =>
match eval_Psatz l w  with
| None => false
| Some f =>
if Zunsat f then true
else ZChecker (f::l) pf
end
| CutProof w pf =>
match eval_Psatz l w with
| None => false
| Some f =>
match genCuttingPlane f with
| None => true
| Some cp => ZChecker (nformula_of_cutting_plane cp::l) pf
end
end
| SplitProof p pf1 pf2 =>
match genCuttingPlane (p,NonStrict) , genCuttingPlane (popp p, NonStrict) with
| None , _ | _ , None => false
| Some cp1 , Some cp2 =>
ZChecker (nformula_of_cutting_plane cp1::l) pf1
&&
ZChecker (nformula_of_cutting_plane cp2::l) pf2
end
| ExProof x prf =>
let fr := max_var_nformulae l in
if Pos.leb x fr then
let z    := Pos.succ fr in
let t    := Pos.succ z in
let nfx  := xnnormalise (mk_eq_pos x z t) in
let posz := xnnormalise (bound_var z) in
let post := xnnormalise (bound_var t) in
ZChecker (nfx::posz::post::l) prf
else false
| EnumProof w1 w2 pf =>
match eval_Psatz l w1 , eval_Psatz l w2 with
|  Some f1 , Some f2 =>
match genCuttingPlane f1 , genCuttingPlane f2 with
|Some (e1,z1,op1) , Some (e2,z2,op2) =>
if (valid_cut_sign op1 && valid_cut_sign op2 && is_pol_Z0 (padd e1 e2))
then
(fix label (pfs:list ZArithProof) :=
fun lb ub =>
match pfs with
| nil => if Z.gtb lb ub then true else false
| pf::rsr => andb (ZChecker ((psub e1 (Pc lb), Equal) :: l) pf) (label rsr (Z.add lb 1%Z) ub)
end)   pf (Z.opp z1)  z2
else false
|   _    ,   _   => true
end
|   _   ,  _ => false
end
end.
Fixpoint bdepth (pf : ZArithProof) : nat :=
match pf with
| DoneProof  => O
| RatProof _ p =>  S (bdepth p)
| CutProof _  p =>   S  (bdepth p)
| SplitProof _ p1 p2 => S (Nat.max (bdepth p1) (bdepth p2))
| EnumProof _ _ l => S (List.fold_right (fun pf x => Nat.max (bdepth pf) x)   O l)
| ExProof _ p   => S (bdepth p)
end.

(* Specifications: *)
Lemma in_bdepth : forall l a b  y, In y l ->  ltof ZArithProof bdepth y (EnumProof a b  l).
Lemma ltof_bdepth_split_l :
forall p pf1 pf2,
ltof ZArithProof bdepth pf1 (SplitProof p pf1 pf2).
Lemma ltof_bdepth_split_r :
forall p pf1 pf2,
ltof ZArithProof bdepth pf2 (SplitProof p pf1 pf2).
Lemma eval_Psatz_sound : forall env w l f',
make_conj (eval_nformula env) l ->
eval_Psatz l w  = Some f' ->  eval_nformula env f'.
Lemma makeCuttingPlane_ns_sound : forall env e e' c,
eval_nformula env (e, NonStrict) ->
makeCuttingPlane e = (e',c) ->
eval_nformula env (nformula_of_cutting_plane (e', c, NonStrict)).
Lemma cutting_plane_sound : forall env f p,
eval_nformula env f ->
genCuttingPlane f = Some p ->
eval_nformula env (nformula_of_cutting_plane p).
Lemma  genCuttingPlaneNone : forall env f,
genCuttingPlane f = None ->
eval_nformula env f -> False.
Lemma eval_nformula_mk_eq_pos : forall env x z t,
env x = env z - env t ->
eval_nformula env (xnnormalise (mk_eq_pos x z t)).
Lemma eval_nformula_bound_var : forall env x,
env x >= 0 ->
eval_nformula env (xnnormalise (bound_var x)).