(*s Simplified formulae: *)
Inductive CGSForm : Set :=
  | CGSleq : ad -> ad -> D -> CGSForm
  | CGSand : CGSForm -> CGSForm -> CGSForm
  | CGSor : CGSForm -> CGSForm -> CGSForm.(*s Simplified formulae: *)
Inductive CGSForm : Set :=
  | CGSleq : ad -> ad -> D -> CGSForm
  | CGSand : CGSForm -> CGSForm -> CGSForm
  | CGSor : CGSForm -> CGSForm -> CGSForm.(*s Simplified formulae: *)
Inductive CGSForm : Set :=
  | CGSleq : ad -> ad -> D -> CGSForm
  | CGSand : CGSForm -> CGSForm -> CGSForm
  | CGSor : CGSForm -> CGSForm -> CGSForm.(*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 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).(*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_complete : forall (fs : CGSForm) (rho : ad -> D), CGSeval rho fs -> CGS_solve fs = true.