Section BOUND.
Context {TX TG ID : Type}.
Variable tag_of_var : positive -> positive -> option bool -> TG.
Definition bound_vars  (fr : positive)
(v : Vars.t) : @GFormula (Formula Z) TX TG ID :=
Vars.fold (fun k acc =>
let y := (xO (fr + k)) in
let z := (xI (fr + k)) in
Cj
(Cj (A (mk_eq_pos k y z) (tag_of_var fr k None))
(Cj (A (bound_var y) (tag_of_var fr k (Some false)))
(A (bound_var z) (tag_of_var fr k (Some true)))))
acc) v TT.
Definition bound_problem  (F : @GFormula (Formula Z) TX TG ID) : GFormula :=
let v := vars_of_bformula F in
I (bound_vars (Pos.succ (Vars.max_element v)) v) None F.
Definition bound_problem_fr (fr : positive) (F : @GFormula (Formula Z) TX TG ID) : GFormula :=
let v := vars_of_bformula F in
I (bound_vars fr v) None F.
End BOUND.
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 e pf1 pf2 => match ZChecker ((e,NonStrict)::l) pf1 , ZChecker (( *)
| 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)
| EnumProof _ _ l => S (List.fold_right (fun pf x => Max.max (bdepth pf) x)   O l)
end.
Definition ZTautoChecker  (f : BFormula (Formula Z)) (w: list ZArithProof): bool :=
@tauto_checker (Formula Z) (NFormula Z) unit Zunsat Zdeduce normalise negate  ZArithProof (fun cl => ZChecker (List.map fst cl)) f w.
Record is_diff_env_elt (fr : positive) (env env' : positive -> Z) (x:positive):=
{
eq_env  : env x = env' x;
eq_diff : env x = env' (xO (fr+ x)) - env' (xI (fr + x));
pos_xO  : env' (xO (fr+x)) >= 0;
pos_xI  : env' (xI (fr+x)) >= 0;
}.
Definition is_diff_env  (s : Vars.t) (env env' : positive -> Z) :=
let fr := Pos.succ (Vars.max_element s) in
forall x, Vars.mem x s = true ->
is_diff_env_elt fr env env' x.
Definition mk_diff_env  (s : Vars.t) (env : positive -> Z) :=
let fr := Vars.max_element s in
fun x =>
if Pos.leb x fr
then env x
else
let fr' := Pos.succ fr in
match x with
| xO x => if Z.leb (env (x - fr')%positive) 0
then 0 else env (x -fr')%positive
| xI x => if Z.leb (env (x - fr')%positive) 0
then - (env (x - fr')%positive) else 0
| xH   => 0
end.
Definition agree_env (v : Vars.t) (env env' : positive -> Z) : Prop :=
forall x, Vars.mem x v = true -> env x = env' x.

Lemma agree_env_union : forall s1 s2 env env',
agree_env (Vars.union s1 s2) env env' ->
agree_env s1 env env' /\ agree_env s2 env env'.