(*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.

Lemma CGS_solve_correct :
forall fs : CGSForm, CGS_solve fs = true -> {rho : ad -> D | CGSeval rho fs}.