(*s Introducing graphs of objects in [D] *)

Definition CGraph1 := Map (Map D).Definition CGraph := option CGraph1.Definition CG_edge (x y : ad) :=
  match MapGet _ cg x with
  | Some edges =>
      match MapGet _ edges y with
      | Some d => Some d
      | _ => None
      end
  | _ => None
  end.(*s Let $\rho$ be an interpretation of adresses as elements in [D], 
    the graph [cg] is satisfied by $\rho$ if for any edge 
    from $x$ to $y$ indexed by $d$, we have $\rho(x) \leq \rho(y)+d$
   A graph is consistent if there exists an interpretation which satisfies it.
*)

Definition CGsat (rho : ad -> D) :=
  forall (x y : ad) (d : D),
  CG_edge x y = Some d -> Dle (rho x) (Dplus (rho y) d) = true.Definition CGconsistent := sig CGsat.(* [CG_path last d l] if there exists a path starting from [last] with successive 
   vertexes $l=[x0;...;xn]$ $(xn=last)$ and [d] is the sum of the weights on the 
   edges *)

Inductive CG_path (last : ad) : D -> list ad -> Set :=
  | CG_p1 : forall x : ad, x = last -> CG_path last Dz (x :: nil)
  | CG_p2 :
      forall (x y : ad) (l : list ad) (d : D),
      CG_path last d (y :: l) ->
      forall d' : D,
      CG_edge x y = Some d' -> CG_path last (Dplus d d') (x :: y :: l).(* [CG_path last d l] if there exists a path starting from [last] with successive 
   vertexes $l=[x0;...;xn]$ $(xn=last)$ and [d] is the sum of the weights on the 
   edges *)

Inductive CG_path (last : ad) : D -> list ad -> Set :=
  | CG_p1 : forall x : ad, x = last -> CG_path last Dz (x :: nil)
  | CG_p2 :
      forall (x y : ad) (l : list ad) (d : D),
      CG_path last d (y :: l) ->
      forall d' : D,
      CG_edge x y = Some d' -> CG_path last (Dplus d d') (x :: y :: l).(* [CG_path last d l] if there exists a path starting from [last] with successive 
   vertexes $l=[x0;...;xn]$ $(xn=last)$ and [d] is the sum of the weights on the 
   edges *)

Inductive CG_path (last : ad) : D -> list ad -> Set :=
  | CG_p1 : forall x : ad, x = last -> CG_path last Dz (x :: nil)
  | CG_p2 :
      forall (x y : ad) (l : list ad) (d : D),
      CG_path last d (y :: l) ->
      forall d' : D,
      CG_edge x y = Some d' -> CG_path last (Dplus d d') (x :: y :: l).(* If $\rho$ satisfies the graph and there is a path from [last] to [x] of 
   weight d then $\rho(x) \leq \rho(last)+d$
*)

Definition first (l : list ad) : ad :=
  match l with
  | nil => N0
  | x :: _ => x
  end.

(* Specifications: *)
Lemma CG_path_head : forall (l : list ad) (last : ad) (d : D), CG_path last d l -> forall rho : ad -> D, CGsat rho -> Dle (rho (first l)) (Dplus (rho last) d) = true.
Lemma CG_path_correct : forall (l : list ad) (x last : ad) (d : D), CG_path last d (x :: l) -> forall rho : ad -> D, CGsat rho -> Dle (rho x) (Dplus (rho last) d) = true.
Theorem CG_circuit_correct : forall (x : ad) (d : D) (l : list ad), CG_path x d (x :: l) -> Dle Dz d = false -> CGconsistent -> False.
Lemma CG_circuits_non_negative_weight : forall (x : ad) (d : D) (l : list ad), CG_path x d (x :: l) -> Dle Dz d = true.
Lemma CG_edge_in_cg_1 : forall (x y : ad) (d : D), CG_edge x y = Some d -> in_FSet x (MapDom _ cg) = true.
Lemma CG_path_in_cg_1 : forall (l : list ad) (last : ad) (d : D), CG_path last d l -> MapSubset _ _ (Elems l) (MapPut _ (MapDom _ cg) last tt).
Lemma CG_path_last : forall (l : list ad) (last : ad) (d : D), CG_path last d l -> {l' : list ad | l = l' ++ last :: nil}.
Lemma ad_simple_path_bounded_card : forall (l : list ad) (last x : ad) (d : D), CG_path last d (x :: l) -> ad_list_stutters (x :: l) = false -> length (x :: l) <= S (MapCard _ cg).
Lemma CG_path_app_1 : forall (l1 l2 : list ad) (last x : ad) (d1 d2 : D), CG_path last d2 (x :: l2) -> CG_path x d1 l1 -> CG_path last (Dplus d2 d1) (l1 ++ l2).
Lemma CG_path_app_2 : forall (l1 l2 : list ad) (last x : ad) (d : D), CG_path last d (l1 ++ x :: l2) -> {d2 : D & CG_path last d2 (x :: l2)}.
Lemma CG_path_app_3 : forall (l1 l2 : list ad) (last x : ad) (d : D), CG_path last d (l1 ++ x :: l2) -> {d1 : D & CG_path x d1 (l1 ++ x :: nil)}.
Lemma CG_path_weight_and_last_unique : forall (l : list ad) (last last' : ad) (d d' : D), CG_path last d l -> CG_path last' d' l -> d = d' /\ last = last'.