(*s Simplified formulae: *)
Inductive CGSForm : Set :=
| CGSleq : ad -> ad -> D -> CGSForm
| CGSand : CGSForm -> CGSForm -> CGSForm
| CGSor : CGSForm -> CGSForm -> CGSForm.
Fixpoint CG_of_CGS (fs : CGSForm) : CGForm :=
match fs with
| CGSleq x y d => CGleq x y d
| CGSand fs0 fs1 => CGand (CG_of_CGS fs0) (CG_of_CGS fs1)
| CGSor fs0 fs1 => CGor (CG_of_CGS fs0) (CG_of_CGS fs1)
end.
Definition CGSeval (rho : ad -> D) (fs : CGSForm) :=
CGeval rho (CG_of_CGS fs).
(*s Decision procedure for simplified formulae *)
Section CGSSolve.
Variable anchor : ad.
Variable anchor_value : D.
(*s Is $x\leq y+d$ consistent with [cg]? *)
Definition CG_test_ineq (cg : CGraph1) (n : nat) (x y : ad)
(d : D) := Ddle (Some (Dneg d)) (ad_1_path_dist_1 cg y x (M0 unit) n).
Variable def_answer : bool.
(*s Invariants: [cg] is consistent, [|cg|<=n]. [(CGS_solve_1 cg n fsl gas)] returns [true] iff [cg /\ fsl /\ anchor=anchor_value] is consistent, where [fsl] is understood as the conjunction of all the [fs] in [fsl]; i.e. iff [cg /\ fsl] alone is consistent (lemmas [CG_anchored_then_consistent] and [CG_consistent_then_anchored)]. [gas] is intended to be [>=] the sum of sizes of all formulas in [fsl]. *)
Fixpoint CGS_solve_1 (cg : CGraph1) (n : nat) (fsl : list CGSForm)
(gas : nat) {struct gas} : bool :=
match gas with
| O => def_answer
| S gas' =>
match fsl with
| nil => true
| fs :: fsl' =>
match fs with
| CGSleq x y d =>
if CG_test_ineq cg n x y d
then
let cg' := CG_add cg x y d in CGS_solve_1 cg' (S n) fsl' gas'
else false
| CGSand fs0 fs1 => CGS_solve_1 cg n (fs0 :: fs1 :: fsl') gas'
| CGSor fs0 fs1 =>
if CGS_solve_1 cg n (fs0 :: fsl') gas'
then true
else CGS_solve_1 cg n (fs1 :: fsl') gas'
end
end
end.
(*s Size of a set of formula and of a list of formula *)
Fixpoint FSize (f : CGSForm) : nat :=
match f with
| CGSand f0 f1 => S (FSize f0 + FSize f1)
| CGSor f0 f1 => S (FSize f0 + FSize f1)
| _ => 1
end.
Fixpoint FlSize (fsl : list CGSForm) : nat :=
match fsl with
| nil => 0
| fs :: fsl' => FSize fs + FlSize fsl'
end.
Definition CGS_solve (fs : CGSForm) :=
CGS_solve_1 (M0 _) 0 (fs :: nil) (S (FSize fs)).
(*s Interpretation of a list of formula as a conjonction *)
Fixpoint CGSeval_l (rho : ad -> D) (fsl : list CGSForm) {struct fsl} :
Prop :=
match fsl with
| nil => True
| fs :: fsl' => CGSeval rho fs /\ CGSeval_l rho fsl'
end.

(* Specifications: *)
Lemma FSize_geq_1 : forall fs : CGSForm, {n : nat | FSize fs = S n}.
Lemma FlSize_is_O : forall fsl : list CGSForm, FlSize fsl = 0 -> fsl = nil.
Lemma CG_add_card_le :
forall (cg : CGraph1) (x y : ad) (d : D) (n : nat),
MapCard _ cg <= n -> MapCard _ (CG_add cg x y d) <= S n.
Lemma CGS_solve_1_correct :
forall (gas : nat) (fsl : list CGSForm) (cg : CGraph1) (n : nat),
CGconsistent cg ->
MapCard _ cg <= n ->
FlSize fsl < gas ->
CGS_solve_1 cg n fsl gas = true ->
{rho : ad -> D | CGSeval_l rho fsl /\ CGsat cg rho}.
Lemma CGS_solve_correct :
forall fs : CGSForm, CGS_solve fs = true -> {rho : ad -> D | CGSeval rho fs}.
Lemma CGS_translate_l :
forall (fs : CGSForm) (rho : ad -> D) (d : D),
CGSeval rho fs -> CGSeval (fun a : ad => Dplus d (rho a)) fs.
Lemma CGS_solve_correct_anchored :
forall fs : CGSForm,
CGS_solve fs = true ->
{rho : ad -> D | CGSeval rho fs /\ rho anchor = anchor_value}.
Lemma CGS_solve_complete_1 :
forall (gas : nat) (fsl : list CGSForm) (cg : CGraph1) (n : nat),
FlSize fsl < gas ->
MapCard _ cg <= n ->
forall rho : ad -> D,
CGsat cg rho -> CGSeval_l rho fsl -> CGS_solve_1 cg n fsl gas = true.
Lemma CGS_solve_complete :
forall (fs : CGSForm) (rho : ad -> D), CGSeval rho fs -> CGS_solve fs = true.