diff options
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/graphs/cgraph.v | 2744 | ||||
-rw-r--r-- | contrib/graphs/zcgraph.v | 417 |
2 files changed, 3161 insertions, 0 deletions
diff --git a/contrib/graphs/cgraph.v b/contrib/graphs/cgraph.v new file mode 100644 index 000000000..3f7203339 --- /dev/null +++ b/contrib/graphs/cgraph.v @@ -0,0 +1,2744 @@ + +(*s Decision procedure for arithmetic formulas by looking + for negative cycles in a graph *) + +Require Allmaps. +Require Arith. +Require ZArith. +Require Bool. +Require Sumbool. +Require PolyList. +Require Wf_nat. + +Section ConstraintGraphs. + +(*s Axiomatisation of the domain of interpretation [D] *) + + Variable D : Set. + + Variable Dz : D. + Variable Dplus : D -> D -> D. + Variable Dneg : D -> D. + Variable Dle : D -> D -> bool. + + Variable Dplus_d_z : (d:D) (Dplus d Dz)=d. + Variable Dplus_z_d : (d:D) (Dplus Dz d)=d. + Variable Dplus_assoc : + (d,d',d'':D) (Dplus (Dplus d d') d'')=(Dplus d (Dplus d' d'')). + + Variable Dplus_neg : (d:D) (Dplus d (Dneg d))=Dz. + + Variable Dle_refl : (d:D) (Dle d d)=true. + Variable Dle_antisym : (d,d':D) (Dle d d')=true -> (Dle d' d)=true -> d=d'. + Variable Dle_trans : + (d,d',d'':D) (Dle d d')=true -> (Dle d' d'')=true -> (Dle d d'')=true. + Variable Dle_total : (d,d':D) {(Dle d d')=true}+{(Dle d' d)=true}. + + Variable Dle_plus_mono : + (d,d',d'',d''':D) (Dle d d')=true -> (Dle d'' d''')=true -> + (Dle (Dplus d d'') (Dplus d' d'''))=true. + +(*s Properties of [Dle] *) + +Lemma Dle_true_permut : + (d,d':D) (Dle d d')=true -> {(Dle d' d)=false}+{d=d'}. + Intros; Case (sumbool_of_bool (Dle d' d)); Intro; Auto. + Save. + +(*s Definition of the minimum function *) + +Definition Dmin := [d,d':D] if (Dle d d') then d else d'. + +Lemma Dle_true_Dmin : (d,d':D)(Dle d d')=true -> (Dmin d d')=d. + Unfold Dmin; Intros d d' H; Rewrite H; Trivial. + Save. + +Lemma Dle_inv_Dmin : (d,d':D)(Dle d' d)=true -> (Dmin d d')=d'. + Unfold Dmin; Intros d d' H. + Case (sumbool_of_bool (Dle d d')); Intro H'; Rewrite H'; Auto. + Save. + +Hints Resolve Dle_true_Dmin Dle_inv_Dmin. + +Lemma Dmin_idempotent : (d:D) (Dmin d d)=d. + Proof. + Auto. + Qed. + +Lemma Dmin_comm : (d,d':D) (Dmin d d')=(Dmin d' d). + Proof. + Intros d d'; Case (Dle_total d d'); Intro H. + Rewrite Dle_true_Dmin with 1:= H. + Rewrite Dle_inv_Dmin with 1:= H; Trivial. + Rewrite Dle_true_Dmin with 1:= H. + Rewrite Dle_inv_Dmin with 1:= H; Trivial. + Save. + +Lemma Dmin_assoc + : (d,d',d'':D) (Dmin (Dmin d d') d'')=(Dmin d (Dmin d' d'')). + Proof. + Intros d d' d''; Case (Dle_total d d'); Intro H. + Rewrite Dle_true_Dmin with 1:= H. + Case (Dle_total d' d''); Intro H'. + Rewrite Dle_true_Dmin with 1:= H'. + Rewrite Dle_true_Dmin with 1:= H. + Rewrite (Dle_true_Dmin d d''); EAuto. + Rewrite Dle_inv_Dmin with 1:= H'; Trivial. + Rewrite Dle_inv_Dmin with 1:= H. + Case (Dle_total d' d''); Intro H'. + Rewrite Dle_true_Dmin with 1:= H'. + Rewrite Dle_inv_Dmin with 1:= H; Trivial. + Rewrite Dle_inv_Dmin with 1:= H'. + Rewrite (Dle_inv_Dmin d d''); EAuto. +Save. + +Lemma Dmin_le_1 : (d,d':D) (Dle (Dmin d d') d)=true. + Proof. + Intros. Case (Dle_total d d'); Intro H. + Rewrite Dle_true_Dmin with 1:= H; Auto. + Rewrite Dle_inv_Dmin with 1:= H; Auto. + Qed. + +Lemma Dmin_le_2 : (d,d':D) (Dle (Dmin d d') d')=true. + Proof. + Intros. Rewrite (Dmin_comm d d'). Apply Dmin_le_1. + Qed. + +Lemma Dmin_le_3 : (d,d',d'':D) (Dle d (Dmin d' d''))=true -> (Dle d d')=true. + Proof. + Intros d d' d''; Elim (Dle_total d' d''); Intro H0. + Rewrite Dle_true_Dmin with 1:=H0; Trivial. + Rewrite Dle_inv_Dmin with 1:=H0; EAuto. + Qed. + +Lemma Dmin_le_4 : (d,d',d'':D) (Dle d (Dmin d' d''))=true -> (Dle d d'')=true. + Proof. + Intros. Rewrite (Dmin_comm d' d'') in H. Exact (Dmin_le_3 ? ? ? H). + Qed. + +Lemma Dmin_le_5 : (d,d',d'':D) (Dle d d')=true -> (Dle d d'')=true -> + (Dle d (Dmin d' d''))=true. + Proof. + Intros. Unfold Dmin. Case (Dle d' d''); Assumption. + Qed. + +(*s Properties of [Dneg] *) + +Lemma Dneg_Dz : (Dneg Dz)=Dz. + Proof. + Rewrite <- (Dplus_z_d (Dneg Dz)). Apply Dplus_neg. + Qed. + +Lemma Dneg_neg : (d:D) (Dneg (Dneg d))=d. + Proof. + Intro. Rewrite <- (Dplus_z_d (Dneg (Dneg d))). Rewrite <- (Dplus_neg d). + Rewrite Dplus_assoc. Rewrite Dplus_neg. Apply Dplus_d_z. + Qed. + +Lemma Dplus_neg_2 : (d:D) (Dplus (Dneg d) d)=Dz. + Proof. + Intro. Cut (Dplus (Dneg d) (Dneg (Dneg d)))=Dz. Rewrite Dneg_neg. Trivial. + Apply Dplus_neg. + Qed. + +(*s Properties of [Dplus] *) + +Lemma Dplus_reg_l + : (d,d',d'':D) (Dle (Dplus d'' d) (Dplus d'' d'))=true + -> (Dle d d')=true. + Proof. + Intros. Rewrite <- (Dplus_z_d d). Rewrite <- (Dplus_z_d d'). Rewrite <- (Dplus_neg_2 d''). + Rewrite (Dplus_assoc (Dneg d'') d'' d). Rewrite (Dplus_assoc (Dneg d'') d'' d'). + Apply Dle_plus_mono. Apply Dle_refl. + Assumption. + Qed. + +Lemma Dplus_reg_r + : (d,d',d'':D) (Dle (Dplus d d'') (Dplus d' d''))=true -> (Dle d d')=true. + Proof. + Intros. Rewrite <- (Dplus_d_z d). Rewrite <- (Dplus_d_z d'). Rewrite <- (Dplus_neg d''). + Rewrite <- (Dplus_assoc d d'' (Dneg d'')). Rewrite <- (Dplus_assoc d' d'' (Dneg d'')). + Apply Dle_plus_mono. Assumption. + Apply Dle_refl. + Qed. + +Lemma Dmin_plus_l + : (d,d',d'':D) (Dplus (Dmin d d') d'')=(Dmin (Dplus d d'') (Dplus d' d'')). + Proof. + Intros d d' d''; Case (Dle_total d d'); Intro H. + Rewrite Dle_true_Dmin with 1:=H. + Rewrite (Dle_true_Dmin (Dplus d d'')); Auto. + Rewrite Dle_inv_Dmin with 1:=H. + Rewrite (Dle_inv_Dmin (Dplus d d'')); Auto. + Qed. + +Lemma Dmin_plus_r + : (d,d',d'':D) (Dplus d'' (Dmin d d'))=(Dmin (Dplus d'' d) (Dplus d'' d')). + Proof. + Intros d d' d''; Case (Dle_total d d'); Intro H. + Rewrite Dle_true_Dmin with 1:=H. + Rewrite (Dle_true_Dmin (Dplus d'' d)); Auto. + Rewrite Dle_inv_Dmin with 1:=H. + Rewrite (Dle_inv_Dmin (Dplus d'' d)); Auto. + Qed. + +Lemma Dle_neg : (d:D) (Dle Dz d)=true -> (Dle (Dneg d) Dz)=true. + Proof. + Intros. Cut (Dle (Dplus Dz (Dneg d)) (Dplus d (Dneg d)))=true. Intro. + Rewrite (Dplus_z_d (Dneg d)) in H0. Rewrite (Dplus_neg d) in H0. Assumption. + Exact (Dle_plus_mono ? ? ? ? H (Dle_refl ?)). + Qed. + +Lemma Dle_neg_2 : (d:D) (Dle d Dz)=true -> (Dle Dz (Dneg d))=true. + Proof. + Intros. Cut (Dle (Dplus d (Dneg d)) (Dplus Dz (Dneg d)))=true. Intro. + Rewrite (Dplus_neg d) in H0. Rewrite (Dplus_z_d (Dneg d)) in H0. Assumption. + Exact (Dle_plus_mono ? ? ? ? H (Dle_refl ?)). + Qed. + +Lemma Dnotle_not_eq : (d,d':D)(Dle d d')=false ->~d=d'. + Red; Intros. + Apply diff_true_false. + Rewrite H0 in H. + Rewrite (Dle_refl d') in H; Trivial. + Save. + +Hints Immediate Dnotle_not_eq. + +Lemma Dnotle_not_eq_sym : (d,d':D) (Dle d d')=false -> ~d'=d. + Proof. + Intros; Apply sym_not_eq; Auto. + Qed. + +Hints Immediate Dnotle_not_eq_sym. + +(*s Equality on [D] is decidable *) + +Lemma D_dec : (d,d':D) {d=d'}+{~d=d'}. + Proof. + Intros d d'; Case (sumbool_of_bool (Dle d d')); Intro H; Auto. + Case (sumbool_of_bool (Dle d' d)); Intro H0; Auto. + Qed. + +Lemma Dnotle_3_cases + : (d,d':D) {(Dle d d')=false}+{d=d'}+{(Dle d' d)=false}. + Proof. + Intros d d'; Case (sumbool_of_bool (Dle d d')); Intro H; Auto. + Case (sumbool_of_bool (Dle d' d)); Intro H0; Auto. + Qed. + +Lemma Dle_noteq_notle + : (d,d':D) (Dle d' d)=true -> ~d=d' -> (Dle d d')=false. + Proof. + Intros d d'; Case (sumbool_of_bool (Dle d d')); Intro H; Auto. + Intros; Absurd d=d'; Auto. + Qed. + +Lemma Dnotle_not_refl + : (d:D) ~(Dle d d)=false. + Proof. + Red; Intro; Rewrite (Dle_refl d). + Exact diff_true_false. + Qed. + + +Lemma Dnotle_elim : + (d,d':D) (Dle d' d)=false -> ((Dle d d')=true /\ ~d=d'). + Intros. + Case (Dle_total d d'); Intro H'; Auto. + Case diff_true_false. + Rewrite <- H'; Trivial. +Save. + +Lemma Dnotle_trans : (d,d',d'':D) (Dle d d')=false -> (Dle d' d'')=false -> (Dle d d'')=false. + Proof. + Intros. + Case Dnotle_elim with 1:= H; Intros. + Case Dnotle_elim with 1:= H0; Intros. + Apply Dle_noteq_notle; EAuto. + Red; Intros. + Apply diff_false_true. + Rewrite <- H0. + Rewrite <- H5; Trivial. + Save. + +Lemma Dnotle_le_1 : (d,d':D) (Dle d d')=false -> (Dle d' d)=true. + Proof. + Intros; Case Dnotle_elim with 1:= H; Trivial. + Qed. + +Lemma Dmin_le_distr_l : (d,d',d'':D) (Dle (Dmin d d') d'')=(orb (Dle d d'') (Dle d' d'')). + Proof. + Intros; Case (Dle_total d d'); Intro H. + Rewrite Dle_true_Dmin with 1:= H. + Pattern (Dle d d''); Apply bool_eq_ind; Intro H'; Simpl; Trivial. + Pattern (Dle d' d''); Apply bool_eq_ind; Intro H''; Simpl; Trivial. + Rewrite <- H'; EAuto. + Rewrite Dle_inv_Dmin with 1:= H. + Pattern (Dle d d''); Apply bool_eq_ind; Intro H'; Simpl; EAuto. + Save. + +Lemma Dmin_choice : (d,d':D) {(Dmin d d')=d}+{(Dmin d d')=d'}. + Proof. + Unfold Dmin. Intros. Elim (sumbool_of_bool (Dle d d')). Intro H. Left . Rewrite H. Reflexivity. + Intro H. Right . Rewrite H. Reflexivity. + Qed. + +Lemma Dnotle_noteq : (d,d':D) (Dle d d')=false -> ~d=d'. + Proof. + Unfold not. Intros. Rewrite H0 in H. Rewrite (Dle_refl d') in H. Discriminate H. + Qed. + +Lemma Dneg_plus : (d,d':D) (Dneg (Dplus d d'))=(Dplus (Dneg d') (Dneg d)). + Proof. + Intros. Cut (Dplus (Dplus d d') (Dplus (Dneg d') (Dneg d)))=Dz. Intro. + Rewrite <- (Dplus_d_z (Dneg (Dplus d d'))). Rewrite <- H. Rewrite <- Dplus_assoc. + Rewrite Dplus_neg_2. Rewrite Dplus_z_d. Reflexivity. + Rewrite Dplus_assoc. Rewrite <- (Dplus_assoc d' (Dneg d') (Dneg d)). Rewrite Dplus_neg. + Rewrite Dplus_z_d. Apply Dplus_neg. + Qed. + +Lemma Dneg_le : (d,d':D) (Dle d d')=true -> (Dle (Dneg d') (Dneg d))=true. + Proof. + Intros. Apply Dplus_reg_l with d'':=d'. Rewrite Dplus_neg. Rewrite <- (Dneg_neg d'). + Rewrite <- Dneg_plus. Apply Dle_neg_2. Rewrite <- (Dplus_neg d'). + Exact (Dle_plus_mono ? ? ? ? H (Dle_refl ?)). + Qed. + +Lemma Dnotle_plus_mono_1 : (d,d',d'',d''':D) (Dle d' d)=true -> (Dle d'' d''')=false + -> (Dle (Dplus d d'') (Dplus d' d'''))=false. + Proof. + Intros. Apply Dle_noteq_notle. Apply Dle_plus_mono. Assumption. + Apply Dnotle_le_1. Assumption. + Unfold not. Intro H1. + Cut (Dle (Dplus (Dneg d) (Dplus d d'')) (Dplus (Dneg d') (Dplus d' d''')))=true. + Rewrite <- (Dplus_assoc (Dneg d) d d''). Rewrite Dplus_neg_2. Rewrite Dplus_z_d. + Rewrite <- Dplus_assoc. Rewrite Dplus_neg_2. Rewrite Dplus_z_d. Rewrite H0. + Intro H2. Discriminate H2. + Apply Dle_plus_mono. Apply Dneg_le. Assumption. + Rewrite H1. Apply Dle_refl. + Qed. + +Lemma Dnotle_plus_mono : (d,d',d'',d''':D) (Dle d d')=false -> (Dle d'' d''')=false + -> (Dle (Dplus d d'') (Dplus d' d'''))=false. + Proof. + Intros. (Apply Dnotle_plus_mono_1; Try Assumption). (Apply Dnotle_le_1; Assumption). + Qed. + +(*s Extending D with an element NONE representing infinity *) + +Definition Ddmin := [dd,dd':(option D)] Cases dd dd' of + NONE _ => dd' + | _ NONE => dd + | (SOME d) (SOME d') => (SOME D (Dmin d d')) + end. + +Lemma Ddmin_idempotent : (dd:(option D)) (Ddmin dd dd)=dd. + Proof. + Induction dd. Trivial. + Intro. Simpl. Rewrite Dmin_idempotent. Reflexivity. + Qed. + +Lemma Ddmin_comm : (dd,dd':(option D)) (Ddmin dd dd')=(Ddmin dd' dd). + Proof. + Induction dd. Intro. (Case dd'; Reflexivity). + Intro d. Induction dd'. Reflexivity. + Intro d'. Simpl. Rewrite Dmin_comm. Reflexivity. + Qed. + +Lemma Ddmin_assoc : (dd,dd',dd'':(option D)) + (Ddmin (Ddmin dd dd') dd'')=(Ddmin dd (Ddmin dd' dd'')). + Proof. + Intros. Case dd. Simpl. Case dd'. Simpl. (Case dd''; Reflexivity). + Intro. Simpl. (Case dd''; Reflexivity). + Intro. Simpl. Case dd'. Simpl. (Case dd''; Reflexivity). + Intro d'. Simpl. Case dd''. Reflexivity. + Intro d''. Rewrite Dmin_assoc. Reflexivity. + Qed. + +(*s The order [Dle] extended to $D_{\infty}$ *) +Definition Ddle + := [dd,dd':(option D)] Cases dd dd' of + _ NONE => true + | NONE _ => false + | (SOME d) (SOME d') => (Dle d d') + end. + +Lemma Ddle_refl : (dd:(option D)) (Ddle dd dd)=true. + Proof. + Intro. Case dd. Reflexivity. + Intro. Exact (Dle_refl d). + Qed. + +Lemma Ddle_antisym + : (dd,dd':(option D)) (Ddle dd dd')=true -> (Ddle dd' dd)=true -> dd=dd'. + Proof. + Intros dd dd'. Case dd. Case dd'. Trivial. + Intros. Discriminate H. + Case dd'. Intros. Discriminate H0. + Intros. Rewrite (Dle_antisym ? ? H0 H). Reflexivity. + Qed. + +Lemma Ddle_trans + : (dd,dd',dd'':(option D)) + (Ddle dd dd')=true -> (Ddle dd' dd'')=true -> (Ddle dd dd'')=true. + Proof. + Intros dd dd' dd''. Case dd''. (Case dd; Trivial). + Intro d''. Case dd'. Intros. Discriminate H0. + Intro d'. Case dd. Intro. Discriminate H. + Intros d H H0. Exact (Dle_trans ? ? ? H H0). + Qed. + +Lemma Ddle_d_none : (dd:(option D)) (Ddle dd (NONE D))=true. + Proof. + Induction dd; Trivial. + Qed. + +Lemma Ddmin_le_1 : (dd,dd':(option D)) (Ddle (Ddmin dd dd') dd)=true. + Proof. + Intros. Case dd. (Case dd'; Reflexivity). + Intro d. Case dd'. Apply Ddle_refl. + Exact (Dmin_le_1 d). + Qed. + +Lemma Ddmin_le_2 : (dd,dd':(option D)) (Ddle (Ddmin dd dd') dd')=true. + Proof. + Intros. Rewrite (Ddmin_comm dd dd'). Apply Ddmin_le_1. + Qed. + +Lemma Ddmin_le_3 + : (dd,dd',dd'':(option D)) + (Ddle dd (Ddmin dd' dd''))=true -> (Ddle dd dd')=true. + Proof. + Intros dd dd' dd''. Case dd'. (Case dd; Trivial). + Intro d'. Case dd. Case dd''. Intro. Discriminate H. + Intros d'' H. Discriminate H. + Intro d. Case dd''. Trivial. + Exact (Dmin_le_3 d d'). + Qed. + +Lemma Ddmin_le_4 : (dd,dd',dd'':(option D)) (Ddle dd (Ddmin dd' dd''))=true -> + (Ddle dd dd'')=true. + Proof. + Intros. Rewrite (Ddmin_comm dd' dd'') in H. Exact (Ddmin_le_3 ? ? ? H). + Qed. + +Lemma Ddmin_le_distr_l + : (dd,dd',dd'':(option D)) + (Ddle (Ddmin dd dd') dd'')=(orb (Ddle dd dd'') (Ddle dd' dd'')). + Proof. + Induction dd. Induction dd'. (Induction dd''; Trivial). + Intro d. (Induction dd''; Trivial). + Intro d. Induction dd'. (Induction dd''; Trivial). + Simpl. Intro d'. Rewrite orb_b_false. Reflexivity. + Intro d'. (Induction dd''; Trivial). Simpl. Exact (Dmin_le_distr_l d d'). + Qed. + +Lemma Ddmin_choice + : (dd,dd':(option D)) {(Ddmin dd dd')=dd}+{(Ddmin dd dd')=dd'}. + Proof. + Induction dd. Intro. Right . Simpl. (Case dd'; Reflexivity). + Intro d. Induction dd'. Left . Reflexivity. + Intro d'. Simpl. Elim (Dmin_choice d d'). Intro H. Left . Rewrite H. Reflexivity. + Intro H. Right . Rewrite H. Reflexivity. + Qed. + +(*s Operation [Ddplus] on $D_{\infty}$ *) + +Definition Ddplus := [dd:(option D)][d':D] + Cases dd of + (SOME d) => (SOME ? (Dplus d d')) + | _ => dd + end. + +Lemma Ddmin_plus_l + : (dd,dd':(option D)) (d'':D) + (Ddplus (Ddmin dd dd') d'')=(Ddmin (Ddplus dd d'') (Ddplus dd' d'')). + Proof. + Induction dd. Induction dd'. Trivial. + Trivial. + Intro d. Induction dd'. Trivial. + Intros d' d''. Simpl. Rewrite Dmin_plus_l. Reflexivity. + Qed. + +Lemma Ddle_plus_mono + : (dd,dd':(option D)) (d,d':D) + (Ddle dd dd')=true -> (Dle d d')=true -> + (Ddle (Ddplus dd d) (Ddplus dd' d'))=true. + Proof. + Induction dd. Induction dd'. Intros. Trivial. + Simpl. Intros. Assumption. + Intro d0. Induction dd'. Trivial. + Simpl. Exact (Dle_plus_mono d0). + Qed. + +Lemma Ddplus_reg_r + : (dd,dd':(option D)) (d'':D) + (Ddle (Ddplus dd d'') (Ddplus dd' d''))=true->(Ddle dd dd')=true. + Proof. + Induction dd. Induction dd'. Trivial. + Simpl. Trivial. + Intro d. Induction dd'. Trivial. + Intros d' d'' H. Exact (Dplus_reg_r d d' d'' H). + Qed. + +(*s Introducing graphs of objects in [D] *) + +Definition CGraph1 := (Map (Map D)). + +Definition CGraph := (option CGraph1). + +Section CGDist. + + Variable cg : CGraph1. + +Definition CG_edge := [x,y:ad] + Cases (MapGet ? cg x) of + (SOME edges) => Cases (MapGet ? edges y) of + (SOME d) => (SOME D d) + | _ => (NONE D) + end + | _ => (NONE D) + 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] + (x,y:ad) (d:D) + (CG_edge x y)=(SOME D 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 : (x:ad) x=last -> (CG_path last Dz (cons x (nil ?))) + | CG_p2 : (x,y:ad) (l:(list ad)) (d:D) (CG_path last d (cons y l)) -> + (d':D) (CG_edge x y)=(SOME D d') -> + (CG_path last (Dplus d d') (cons x (cons 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 : (list ad) -> ad := [l]Cases l of nil => ad_z | (cons x _) => x end. + +Lemma CG_path_head + : (l:(list ad)) (last:ad) (d:D) (CG_path last d l) -> + (rho:ad->D) (CGsat rho) -> (Dle (rho (first l)) (Dplus (rho last) d))=true. + Proof. + Intros; Elim H; Simpl; Intros. + Rewrite e; Rewrite Dplus_d_z; Auto. + Apply Dle_trans with (Dplus (rho y) d'); Auto. + Rewrite <- Dplus_assoc; Auto. + Save. + +Lemma CG_path_correct + : (l:(list ad)) (x,last:ad) (d:D) (CG_path last d (cons x l)) -> + (rho:ad->D) (CGsat rho) -> (Dle (rho x) (Dplus (rho last) d))=true. + Proof. + Intros; Apply (CG_path_head (cons x l) last d); Trivial. + Save. + +(*s If there is a circuit [(cons x l)] with negative weight [d], then [cg] is inconsistent: *) + +Theorem CG_circuit_correct + : (x:ad) (d:D) (l:(list ad)) + (CG_path x d (cons x l)) -> (Dle Dz d)=false -> CGconsistent -> False. + Proof. + Intros. Unfold CGconsistent in H1. Elim H1. Intros rho H2. + Cut (Dle (Dplus (rho x) Dz) (Dplus (rho x) d))=true. Intro H3. + Rewrite (Dplus_reg_l ? ? ? H3) in H0. Discriminate H0. + Rewrite Dplus_d_z. Exact (CG_path_correct l x x d H rho H2). + Qed. + +Section CGConsistent. + + Variable P : CGconsistent. + +(*s Assuming that [cg] is consistent, we can build a distance d(x,y) as follows: + d(x,y) is the length of the shortest path from x to y (or +infty if none). *) + +Lemma CG_circuits_non_negative_weight + : (x:ad) (d:D) (l:(list ad)) (CG_path x d (cons x l)) -> (Dle Dz d)=true. + Proof. + Intros. Elim (sumbool_of_bool (Dle Dz d)). Trivial. + Intro H0. Elim (CG_circuit_correct x d l H H0 P). + Qed. + +End CGConsistent. + +(*s We assume that any cycle has a positive weight *) + +Section CGNoBadCycles. + + Variable no_bad_cycles : (x:ad) (d:D) (l:(list ad)) + (CG_path x d (cons x l)) -> (Dle Dz d)=true. + +(*s The edges are in the domain of the graph *) + +Lemma CG_edge_in_cg_1 + : (x,y:ad) (d:D) (CG_edge x y)=(SOME D d) -> (in_FSet x (MapDom ? cg))=true. + Proof. + Unfold CG_edge. Intros x y d. + Elim (option_sum ? (MapGet (Map D) cg x)). Intro H. + Elim H. Intros edges H0. Rewrite H0. Intros. + Exact (MapDom_semantics_1 ? cg x edges H0). + Intros H H0. Rewrite H in H0. Discriminate H0. + Qed. + + +(*s The elements of a path are in the domain of the graph extended with + the last element *) +Lemma CG_path_in_cg_1 + : (l:(list ad)) (last:ad) (d:D) + (CG_path last d l) -> (MapSubset ? ? (Elems l) + (MapPut ? (MapDom ? cg) last tt)). + Proof. + + Induction 1. + Unfold MapSubset; Unfold Elems; Simpl; Intros. + Rewrite in_dom_put. + Rewrite in_dom_M1 in H0. + Rewrite <- e. + Rewrite (ad_eq_comm a x). + Rewrite H0; Simpl; Trivial. + Unfold MapSubset. + Intros; Rewrite in_dom_put. + Change (in_dom unit a + (MapPut unit (Elems (cons y l0)) x tt))=true in H1. + Rewrite in_dom_put in H1. + Case orb_prop with 1:=H1; Intro. + Rewrite (ad_eq_complete ? ? H2). + Change + (orb (ad_eq x last) (in_FSet x (MapDom (Map D) cg)))=true. + Rewrite CG_edge_in_cg_1 with 1:=e; Auto with bool. + LetTac H3:=(H0 a H2). + Rewrite in_dom_put in H3. + Trivial. +Save. + +Lemma CG_path_last + : (l:(list ad)) (last:ad) (d:D) + (CG_path last d l) -> {l':(list ad) | l=(app l' (cons last (nil ad)))}. + Proof. + Induction 1; Intros. + Exists (nil ad); Simpl; Rewrite e; Trivial. + Case H0; Intros l' H1. + Exists (cons x l'); Simpl. + Rewrite H1; Auto. + Qed. + +(*s The length of a path without repetition is less than the + cardinal of the map representing the graph *) + +Lemma ad_simple_path_bounded_card + : (l:(list ad)) (last,x:ad) (d:D) + (CG_path last d (cons x l)) -> (ad_list_stutters (cons x l))=false + -> (le (length (cons x l)) (S (MapCard ? cg))). + Proof. + Intros. Apply le_trans with m:=(MapCard ? (MapPut ? (MapDom ? cg) last tt)). + Rewrite (ad_list_not_stutters_card (cons x l) H0). Apply MapSubset_Card_le. + Apply CG_path_in_cg_1 with 1:=H; Trivial. + Rewrite (MapCard_Dom ? cg). Apply MapCard_Put_ub. + Qed. + +Lemma CG_path_app_1 : (l1,l2:(list ad)) (last,x:ad) (d1,d2:D) + (CG_path last d2 (cons x l2)) -> (CG_path x d1 l1) -> + (CG_path last (Dplus d2 d1) (app l1 l2)). + Proof. + Intros. + Elim H0; Intros. + Simpl; Rewrite Dplus_d_z; Rewrite e; Trivial. + Rewrite <- Dplus_assoc. + Simpl; Constructor; Auto. + Save. + +Lemma CG_path_app_2 : (l1,l2:(list ad)) (last,x:ad) (d:D) + (CG_path last d (app l1 (cons x l2))) -> + {d2 : D & (CG_path last d2 (cons x l2))}. + Proof. + Induction l1. Simpl. Intros. Split with d. Assumption. + Simpl. Induction l. Intros. Simpl in H0. Inversion H0. Split with d0. Assumption. + Intros. Simpl in H1. Inversion H1. Exact (H0 l2 last x d0 H5). + Qed. + +Lemma CG_path_app_3 : (l1,l2:(list ad)) (last,x:ad) (d:D) + (CG_path last d (app l1 (cons x l2))) -> + {d1 : D & (CG_path x d1 (app l1 (cons x (nil ad))))}. + Proof. + Induction l1. Simpl. Intros. Split with Dz. Apply CG_p1. Reflexivity. + Induction l. Simpl. Intros. Inversion H0. Split with d'. Rewrite <- (Dplus_z_d d'). + Apply CG_p2. Apply CG_p1. Reflexivity. + Assumption. + Simpl. Intros. Inversion H1. Elim (H0 ? ? ? ? H5). Intros d1 H9. Split with (Dplus d1 d'). + Apply CG_p2. Assumption. + Assumption. + Qed. + +Lemma CG_path_weight_and_last_unique + : (l:(list ad)) (last,last':ad) (d,d':D) + (CG_path last d l) -> (CG_path last' d' l) -> d=d' /\ last=last'. + Proof. + Intros l last last' d d' H; Generalize d'. + Elim H; Intros. + Inversion H0. + Split; Trivial. Transitivity x; Auto. + Inversion H1. + Case H0 with 1:=H5; Split; Intros; Trivial. + Rewrite H8. + Replace d'0 with d'2; Auto. + Cut (SOME D d'2)=(SOME D d'0). + Intro E; Injection E; Trivial. + Transitivity (CG_edge x y); Auto. + Qed. + + Inductive and_sp [A:Set; B:Prop] : Set := conj_sp : A -> B -> (and_sp A B). + +(*s Given a path, one may find a shortest path withour repetition *) + +Lemma ad_path_then_simple_path : + (l:(list ad)) (last:ad) (d:D) + (CG_path last d l) -> + {sl:(list ad) & {d0:D & + (and_sp (CG_path last d0 (cons (first l) sl)) + ((ad_list_stutters (cons (first l) sl))=false /\ + (Dle d0 d)=true))}}. + Proof. + Induction 1; Unfold first; Intros. + Exists (nil ad); Exists Dz; Split; Auto. + Constructor; Auto. + Case H0; Clear H0; Intros sl (d1,(H1,(H2,H3))). + Elim (sumbool_of_bool (ad_in_list x (cons y sl))); Intro. + Case (ad_in_list_forms_circuit x (cons y sl) a); Intros. + Case s; Clear a s; Intros l2 H4. + Case (CG_path_app_2 x0 l2 last x d1). + Rewrite <- H4; Trivial. + Intros d2 H5; Exists l2; Exists d2. + Split; Trivial. + Split. + Apply (ad_list_stutters_app_conv_r x0). + Rewrite <- H4; Trivial. + Apply Dle_trans with (Dplus d1 d'). + Case (CG_path_app_3 (cons x x0) l2 last x (Dplus d1 d')). + Simpl; Rewrite <- H4; Constructor; Trivial. + Intros d3 H6. + Replace (Dplus d1 d') with (Dplus d2 d3). + Apply Dle_trans with (Dplus d2 Dz). + Rewrite Dplus_d_z; Auto. + Apply Dle_plus_mono; Trivial. + Apply (no_bad_cycles x d3 (app x0 (cons x (nil ad)))); Auto. + Case (CG_path_weight_and_last_unique + (app (app (cons x x0) (cons x (nil ad))) l2) + last last (Dplus d2 d3) (Dplus d1 d')); Auto. + Apply CG_path_app_1 with x; Trivial. + Replace (app (app (cons x x0) (cons x (nil ad))) l2) + with (cons x (cons y sl)); Auto. + Constructor; Auto. + Rewrite H4; Rewrite <- ass_app; Simpl; Trivial. + Apply Dle_plus_mono; Trivial. + Exists (cons y sl); Exists (Dplus d1 d'); Repeat Split; Auto. + Constructor; Auto. + Change (orb (ad_in_list x (cons y sl)) (ad_list_stutters (cons y sl))) = false. + Apply orb_false_intro; Trivial. + Qed. + +Lemma CG_path_app_4 : (l1,l2:(list ad)) (last,x:ad) (d:D) + (CG_path last d (app l1 (cons x l2))) -> + {d1 : D & {d2 : D & + (and_sp (CG_path x d1 (app l1 (cons x (nil ad)))) * + (CG_path last d2 (cons x l2)) + d=(Dplus d2 d1))}}. + Proof. + Intros. Elim (CG_path_app_2 l1 l2 last x d). Intros d1 H0. + Elim (CG_path_app_3 l1 l2 last x d). Intros d2 H1. Split with d2. Split with d1. + Split. Exact (H1,H0). + Cut (app l1 (cons x l2))=(app (app l1 (cons x (nil ad))) l2). + Intro. Rewrite H2 in H. + Elim (CG_path_weight_and_last_unique ? ? ? ? ? H + (CG_path_app_1 (app l1 (cons x (nil ad))) l2 last x d2 d1 H0 H1)). + Trivial. + Exact (ass_app l1 (cons x (nil ad)) l2). + Assumption. + Assumption. + Qed. + +(*s [(ad_simple_path_naive_search x y prefix n)] is true when + there esists a path [x::l] from [y] to [x] of length less than + [n] with edges not in prefix +*) + +Fixpoint ad_simple_path_naive_search [x,y:ad; l:(list ad); n:nat] : bool := + (orb (ad_eq x y) + Cases n of + O => false + | (S n') => Cases (MapGet ? cg x) of + NONE => false + | (SOME edges) => + let l'=(cons x l) in (* builds reverse path *) + Cases (MapSweep D + [z:ad][d:D] if (ad_in_list z l') + then false + else (ad_simple_path_naive_search z y l' n') + edges) of + NONE => false + | (SOME _) => true + end + end + end). + +Lemma ad_simple_path_naive_search_correct_1 + : (n:nat) (x,y:ad) (l:(list ad)) (d:D) + (le (length l) n) -> (CG_path y d (cons x l)) -> + (prefix:(list ad)) + (ad_list_stutters (app (rev prefix) (cons x l)))=false -> + (ad_simple_path_naive_search x y prefix n)=true. + Proof. + Induction n. Intros x y l. Case l. Intros. Inversion H0. + Rewrite H4. Simpl. + Rewrite (ad_eq_correct y). Reflexivity. + Intros. Elim (le_Sn_O ? H). + Intros n0 H x y l. Case l. Intros. Inversion H1. Rewrite H5. Simpl. + Rewrite (ad_eq_correct y). Reflexivity. + Intros. Simpl. Elim (sumbool_of_bool (ad_eq x y)). Intro H3. Rewrite H3. Reflexivity. + Intro H3. Rewrite H3. Simpl. Elim (option_sum ? (MapGet ? cg x)). Intro H4. Elim H4. + Clear H4. Intros edges H4. Rewrite H4. Inversion_clear H1. Unfold CG_edge in H6. + Rewrite H4 in H6. Elim (option_sum ? (MapGet D edges a)). Intro H7. Elim H7. Clear H7. + Intros d'' H7. Rewrite H7 in H6. + Cut (if (ad_in_list a (cons x prefix)) + then false + else (ad_simple_path_naive_search a y (cons x prefix) n0))=true. + Intro. Elim (MapSweep_semantics_4 D [z:ad] [_:D] + (if (orb (ad_eq z x) (ad_in_list z prefix)) + then false + else (ad_simple_path_naive_search z y (cons x prefix) n0)) + edges a d'' H7 H1). + Intros a' H8. Elim H8. Intros d1 H9. Rewrite H9. Reflexivity. + Rewrite (ad_list_app_rev prefix (cons a l0) x) in H2. + Rewrite <- (ad_in_list_rev (cons x prefix) a). + Rewrite (ad_list_stutters_prev_conv_l ? ? ? H2). + Exact (H a y l0 d0 (le_S_n ? ? H0) H5 (cons x prefix) H2). + Intro H7. Rewrite H7 in H6. Discriminate H6. + Intro H4. Inversion_clear H1. Unfold CG_edge in H6. Rewrite H4 in H6. Discriminate H6. + Qed. + +Lemma ad_simple_path_naive_search_correct + : (n:nat) (x,y:ad) (l:(list ad)) (d:D) + (le (length l) n) -> (CG_path y d (cons x l)) + -> (ad_list_stutters (cons x l))=false + -> (ad_simple_path_naive_search x y (nil ad) n)=true. + Proof. + Intros. Exact (ad_simple_path_naive_search_correct_1 n x y l d H H0 (nil ad) H1). + Qed. + +Lemma ad_simple_path_naive_search_complete_1 + : (n:nat) (x,y:ad) (prefix:(list ad)) + (d':D) (CG_path x d' (rev (cons x prefix))) -> + (ad_list_stutters (cons x prefix))=false -> + (ad_simple_path_naive_search x y prefix n)=true -> + {d:D & {l:(list ad) & (and_sp (CG_path y d (app (rev (cons x prefix)) l)) + (ad_list_stutters (app (rev (cons x prefix)) l)) + =false)}}. + Proof. + Induction n. Intros. Split with d'. Split with (nil ad). Simpl in H1. + Rewrite (orb_b_false (ad_eq x y)) in H1. Rewrite <- (ad_eq_complete ? ? H1). + Rewrite <- app_nil_end. Split. Assumption. + Rewrite ad_list_stutters_rev. Assumption. + Intros. Simpl in H2. Elim (orb_true_elim ? ? H2). Intro H3. + Rewrite <- (ad_eq_complete ? ? H3). Split with d'. Split with (nil ad). + Rewrite <- app_nil_end. Split. Assumption. + Rewrite ad_list_stutters_rev. Assumption. + Intro H3. Clear H2. Elim (option_sum ? (MapGet ? cg x)). Intro H4. Elim H4. + Intros edges H5. Rewrite H5 in H3. + Elim (option_sum ? (MapSweep D [z:ad] [_:D] + (if (orb (ad_eq z x) (ad_in_list z prefix)) + then false + else (ad_simple_path_naive_search z y (cons x prefix) n0)) edges)). + Intro H2. Elim H2. Intro r. Elim r. Intros x0 d0 H6. + Cut (if (ad_in_list x0 (cons x prefix)) + then false + else (ad_simple_path_naive_search x0 y (cons x prefix) n0))=true. + Intro. Elim (sumbool_of_bool (ad_in_list x0 (cons x prefix))). Intro H8. + Rewrite H8 in H7. Discriminate H7. + Intro H8. Rewrite H8 in H7. Clear H2 H3. Elim (H x0 y (cons x prefix) (Dplus d0 d')). + Intros d1 H9. Elim H9. Intros l H10. Elim H10. Intros H11 H12. + Rewrite <- (ad_list_app_rev (cons x prefix) l x0) in H11. + Rewrite <- (ad_list_app_rev (cons x prefix) l x0) in H12. Split with d1. + Split with (cons x0 l). Split. Assumption. + Assumption. + Change (CG_path x0 (Dplus d0 d') (app (rev (cons x prefix)) (cons x0 (nil ad)))). + Apply CG_path_app_1 with x:=x. Rewrite <- (Dplus_z_d d0). Apply CG_p2. Apply CG_p1. + Reflexivity. + Unfold CG_edge. Rewrite H5. Rewrite (MapSweep_semantics_2 ? ? edges x0 d0 H6). + Reflexivity. + Assumption. + Simpl. Simpl in H1. Rewrite H1. Simpl in H8. Rewrite H8. Reflexivity. + Assumption. + Exact (MapSweep_semantics_1 ? ? ? x0 d0 H6). + Intro H2. Rewrite H2 in H3. Discriminate H3. + Intro H4. Rewrite H4 in H3. Discriminate H3. + Qed. + +Lemma ad_simple_path_naive_search_complete : (n:nat) (x,y:ad) + (ad_simple_path_naive_search x y (nil ad) n)=true -> + {d:D & {l:(list ad) & (and_sp (CG_path y d (cons x l)) + (ad_list_stutters (cons x l))=false)}}. + Proof. + Intros. Exact (ad_simple_path_naive_search_complete_1 n x y (nil ad) Dz + (CG_p1 x x (refl_equal ? ?)) (refl_equal ? false) H). + Qed. + +(*s Definition of simple paths : paths without repetition *) + +Definition CG_simple_path := [last:ad] [d:D] [l:(list ad)] + (and_sp (CG_path last d l) (ad_list_stutters l)=false). + +(*s Between two vertexes, there exists a simple path or there exists no path *) +Lemma ad_simple_path_dec : (x,y:ad) + {l:(list ad) & {d:D & (CG_simple_path y d (cons x l))}}+ + {(l:(list ad)) (d:D) (CG_simple_path y d (cons x l)) -> False}. + Proof. + Intros. Elim (sumbool_of_bool (ad_simple_path_naive_search x y (nil ad) (MapCard ? cg))). + Intro H. Left . Elim (ad_simple_path_naive_search_complete ? ? ? H). Intros d H0. + Elim H0. Intros l H1. Split with l. Split with d. Exact H1. + Intro H. Right . Intros l d H0. Unfold CG_simple_path in H0. Elim H0. Intros H1 H2. + Rewrite (ad_simple_path_naive_search_correct ? x y l d + (le_S_n ? ? (ad_simple_path_bounded_card ? ? ? ? H1 H2)) H1 H2) in H. + Discriminate H. + Qed. + +(*s Computing the minimum of edges in a Map *) + +Definition all_min := [f:ad->D->(option D)] (MapFold ? ? (NONE D) Ddmin f). + +Lemma all_min_le_1 : (f:ad->D->(option D)) (m:(Map D)) + (a:ad) (d:D) (MapGet ? m a)=(SOME ? d) -> + (Ddle (all_min f m) (f a d))=true. + Proof. + Intros. Elim (option_sum ? (f a d)). Intro H0. Elim H0. Intros d' H1. Rewrite H1. + Unfold all_min. Cut ([a:(option D)][b:D](Ddle a (SOME D b)) + (MapFold D (option D) (NONE D) Ddmin f m) d') + =(MapFold D bool false orb + [a:ad] [y:D]([a0:(option D)][b:D](Ddle a0 (SOME D b)) (f a y) d') m). + Intro. Rewrite H2. Rewrite MapFold_orb. + Elim (MapSweep_semantics_4 D [a:ad][y:D](Ddle (f a y) (SOME D d')) m a d H). + Intros a' H3. Elim H3. Intros d'' H4. Rewrite H4. Reflexivity. + Rewrite H1. Simpl. Apply Dle_refl. + Exact (MapFold_distr_r D ? (NONE D) Ddmin bool false orb D + [a:(option D)][b:D](Ddle a (SOME D b)) + [c:D](refl_equal ? false) + [a,b:(option D)][c:D](Ddmin_le_distr_l a b (SOME ? c)) f m d'). + Intro H0. Rewrite H0. (Case (all_min f m); Reflexivity). + Qed. + +Lemma all_min_le_2_1 : (f:ad->D->(option D)) (m:(Map D)) (pf:ad->ad) + (d:D) (MapFold1 ? ? (NONE D) Ddmin f pf m)=(SOME ? d) -> + {a:ad & {d':D | (MapGet ? m a)=(SOME ? d') /\ (f (pf a) d')=(SOME ? d)}}. + Proof. + Induction m. Intros. Discriminate H. + Intros a y pf d H. Simpl in H. Split with a. Split with y. Split. Apply M1_semantics_1. + Assumption. + Intros. Simpl in H1. + Elim (Ddmin_choice + (MapFold1 D (option D) (NONE D) Ddmin f [a0:ad](pf (ad_double a0)) m0) + (MapFold1 D (option D) (NONE D) Ddmin f [a0:ad](pf (ad_double_plus_un a0)) m1)). + Intro H2. Rewrite H2 in H1. Elim (H [a0:ad](pf (ad_double a0)) d H1). Intros a0 H3. + Elim H3. Intros d' H4. Split with (ad_double a0). Split with d'. Split. + Rewrite MapGet_M2_bit_0_0. Rewrite ad_double_div_2. (Elim H4; Trivial). + Apply ad_double_bit_0. + (Elim H4; Trivial). + Intro H2. Rewrite H2 in H1. Elim (H0 [a0:ad](pf (ad_double_plus_un a0)) d H1). + Intros a0 H3. Elim H3. Intros d' H4. Split with (ad_double_plus_un a0). Split with d'. + Split. Rewrite MapGet_M2_bit_0_1. Rewrite ad_double_plus_un_div_2. (Elim H4; Trivial). + Apply ad_double_plus_un_bit_0. + (Elim H4; Trivial). + Qed. + +Lemma all_min_le_2 : (f:ad->D->(option D)) (m:(Map D)) + (d:D) (all_min f m)=(SOME ? d) -> + {a:ad & {d':D | (MapGet ? m a)=(SOME ? d') /\ (f a d')=(SOME ? d)}}. + Proof. + Intros. Exact (all_min_le_2_1 f m [a:ad]a d H). + Qed. + +Lemma all_min_le_3 : (f,g:ad->D->(option D)) (m:(Map D)) + ((a:ad) (d:D) (MapGet ? m a)=(SOME ? d) -> (Ddle (f a d) (g a d))=true) -> + (Ddle (all_min f m) (all_min g m))=true. + Proof. + Intros. Elim (option_sum ? (all_min g m)). Intro H0. Elim H0. Intros d H1. + Elim (all_min_le_2 g m d H1). Intros a H2. Elim H2. Intros d' H3. Elim H3. Intros H4 H5. + Apply Ddle_trans with (f a d'). Apply all_min_le_1. Assumption. + Rewrite H1. Rewrite <- H5. Apply H. Assumption. + Intro H0. Rewrite H0. Apply Ddle_d_none. + Qed. + +(*s [(ad_simple_path_dist_1 x y l n)] computes the minimum weight of a path + from [x] to [y] of maximal length [n] which does not contain vertexes + from [l] *) + +Fixpoint ad_simple_path_dist_1 [x,y:ad; l:(list ad); n:nat] : (option D) := + if (ad_eq x y) + then (SOME ? Dz) + else + Cases n of + O => (NONE ?) + | (S n') => Cases (MapGet ? cg x) of + NONE => (NONE ?) + | (SOME edges) => + let l'=(cons x l) in (* builds reverse path *) + (all_min [z:ad][d:D] + if (ad_in_list z l') + then (NONE D) + else (Ddplus (ad_simple_path_dist_1 z y l' n') d) + edges) + end + end. + +Lemma ad_simple_path_dist_1_correct_1 : (n:nat) (x,y:ad) (l:(list ad)) (d:D) + (le (length l) n) -> (CG_path y d (cons x l)) -> + (prefix:(list ad)) + (ad_list_stutters (app (rev prefix) (cons x l)))=false -> + (Ddle (ad_simple_path_dist_1 x y prefix n) (SOME ? d))=true. + Proof. + Induction n. Intros x y l. Case l. Intros. Inversion H0. + Rewrite H4. Simpl. + Rewrite (ad_eq_correct y). Rewrite H3. Apply Ddle_refl. + Intros. Elim (le_Sn_O ? H). + Intros n0 H x y l. Case l. Intros. Inversion H1. + Rewrite H5. Simpl. + Rewrite (ad_eq_correct y). Rewrite H4. Apply Ddle_refl. + Intros. Simpl. Elim (sumbool_of_bool (ad_eq x y)). Intro H3. Rewrite H3. + Rewrite (ad_eq_complete ? ? H3) in H1. Exact (no_bad_cycles ? ? ? H1). + Intro H3. Rewrite H3. Elim (option_sum ? (MapGet ? cg x)). Intro H4. Elim H4. + Intros edges H5. Rewrite H5. Inversion_clear H1. + Apply Ddle_trans with dd':=Case (ad_in_list a (cons x prefix)) of + (NONE D) + (Ddplus (ad_simple_path_dist_1 a y (cons x prefix) n0) d') + end. + Cut (MapGet ? edges a)=(SOME ? d'). Intro. + Exact (all_min_le_1 [z:ad] [d:D] + Case (orb (ad_eq z x) (ad_in_list z prefix)) of + (NONE D) + (Ddplus (ad_simple_path_dist_1 z y (cons x prefix) n0) d) + end edges a d' H1). + Unfold CG_edge in H7. Rewrite H5 in H7. Elim (option_sum ? (MapGet D edges a)). Intro H8. + Elim H8. Intros d1 H9. Rewrite H9 in H7. Rewrite H9. Inversion_clear H7. Reflexivity. + Intro H8. Rewrite H8 in H7. Discriminate H7. + Rewrite (ad_list_app_rev prefix (cons a l0) x) in H2. + Rewrite <- (ad_in_list_rev (cons x prefix) a). + Rewrite (ad_list_stutters_prev_conv_l ? ? ? H2). + Apply (Ddle_plus_mono (ad_simple_path_dist_1 a y (cons x prefix) n0) (SOME D d0) d' d'). + Exact (H a y l0 d0 (le_S_n ? ? H0) H6 (cons x prefix) H2). + Apply Dle_refl. + Intro H4. Inversion H1. Unfold CG_edge in H10. + Rewrite H4 in H10. Discriminate H10. + Qed. + +Lemma ad_simple_path_dist_1_correct_2 : (n:nat) (x,y:ad) (l:(list ad)) (d:D) + (le (length l) n) -> (CG_path y d (cons x l)) -> + (ad_list_stutters (cons x l))=false -> + (Ddle (ad_simple_path_dist_1 x y (nil ad) n) (SOME ? d))=true. + Proof. + Intros. Exact (ad_simple_path_dist_1_correct_1 n x y l d H H0 (nil ad) H1). + Qed. + +(*s [(ad_simple_path_dist x y)] computes the minimum path from x to y *) +Definition ad_simple_path_dist := [x,y:ad] + (ad_simple_path_dist_1 x y (nil ad) (MapCard ? cg)). + +Lemma ad_simple_path_dist_correct_1 : (x,y:ad) (l:(list ad)) (d:D) + (CG_path y d (cons x l)) -> + (ad_list_stutters (cons x l))=false -> + (Ddle (ad_simple_path_dist x y) (SOME ? d))=true. + Proof. + Intros. Unfold ad_simple_path_dist. + (Apply ad_simple_path_dist_1_correct_2 with l:=l; Try Assumption). + Exact (le_S_n ? ? (ad_simple_path_bounded_card l y x d H H0)). + Qed. + +Lemma ad_simple_path_dist_correct : (x,y:ad) (l:(list ad)) (d:D) + (CG_path y d (cons x l)) -> + (Ddle (ad_simple_path_dist x y) (SOME ? d))=true. + Proof. + Intros. Elim ad_path_then_simple_path with 1:= H. + Intros l0 H0. + Elim H0. Intros d0 H1. Elim H1. Intros H2 H3. Elim H3. Intros H4 H5. + Apply Ddle_trans with dd':=(SOME D d0). + Exact (ad_simple_path_dist_correct_1 x y l0 d0 H2 H4). + Exact H5. + Qed. + +Lemma ad_simple_path_dist_1_complete_1 : (n:nat) (x,y:ad) (prefix:(list ad)) + (d':D) (CG_path x d' (rev (cons x prefix))) -> + (ad_list_stutters (cons x prefix))=false -> + (d0:D) + (ad_simple_path_dist_1 x y prefix n)=(SOME D d0) -> + {l:(list ad) & (and_sp (CG_path y (Dplus d0 d') (app (rev (cons x prefix)) l)) + (ad_list_stutters (app (rev (cons x prefix)) l))=false /\ + (le (length l) n) )}. + Proof. + Induction n. Intros. Split with (nil ad). Split. Unfold ad_simple_path_dist_1 in H1. + Elim (sumbool_of_bool (ad_eq x y)). Intro H2. Rewrite H2 in H1. Inversion H1. + Rewrite <- H4. Rewrite Dplus_z_d. Rewrite <- app_nil_end. + Rewrite <- (ad_eq_complete ? ? H2). Assumption. + Intro H2. Rewrite H2 in H1. Discriminate H1. + Split. Rewrite <- app_nil_end. Rewrite ad_list_stutters_rev. Assumption. + Apply le_n. + Intros. Simpl in H2. Elim (sumbool_of_bool (ad_eq x y)). Intro H3. Rewrite H3 in H2. + Inversion H2. Split with (nil ad). Split. Rewrite <- H5. Rewrite Dplus_z_d. + Rewrite <- app_nil_end. Rewrite <- (ad_eq_complete ? ? H3). Assumption. + Split. Rewrite <- app_nil_end. Rewrite ad_list_stutters_rev. Assumption. + Apply le_O_n. + Intro H3. Rewrite H3 in H2. Elim (option_sum ? (MapGet ? cg x)). Intro H4. Elim H4. + Intros edges H5. Rewrite H5 in H2. Elim (all_min_le_2 ? edges d0 H2). Intros a H6. + Elim H6. Intros d1 H7. Elim H7. Intros H8 H9. Clear H2 H6 H7. + Cut (ad_in_list a (cons x prefix))=false. Intro. + Elim (option_sum ? (ad_simple_path_dist_1 a y (cons x prefix) n0)). Intro H6. Elim H6. + Intros d2 H7. Clear H6. Rewrite H7 in H9. Cut (Dplus d2 d1)=d0. Intro. + Cut (CG_path a (Dplus d1 d') (rev (cons a (cons x prefix)))). Intro. + Cut (ad_list_stutters (cons a (cons x prefix)))=false. Intro. + Elim (H a y (cons x prefix) ? H10 H11 d2 H7). Intros l0 H12. Elim H12. Intros H13 H14. + Elim H14. Intros H15 H16. Split with (cons a l0). Split. Rewrite ad_list_app_rev. + Rewrite <- H6. Rewrite Dplus_assoc. Assumption. + Split. Rewrite ad_list_app_rev. Assumption. + Exact (le_n_S ? ? H16). + Simpl. Simpl in H2. Rewrite H2. Simpl in H1. Rewrite H1. Reflexivity. + Apply (CG_path_app_1 (rev (cons x prefix)) (cons a (nil ad)) a x). + Rewrite <- (Dplus_z_d d1). Apply CG_p2. Apply CG_p1. Reflexivity. + Unfold CG_edge. Rewrite H5. Rewrite H8. Reflexivity. + Assumption. + Elim (sumbool_of_bool (orb (ad_eq a x) (ad_in_list a prefix))). Intro H10. + Rewrite H10 in H9. Discriminate H9. + Intro H10. Rewrite H10 in H9. Simpl in H9. Inversion H9. Reflexivity. + Intro H6. Rewrite H6 in H9. Generalize H9. + Case (orb (ad_eq a x) (ad_in_list a prefix)); Intro H10; Discriminate H10. + Elim (sumbool_of_bool (ad_in_list a (cons x prefix))). Intro H10. Simpl in H10. + Rewrite H10 in H9. Discriminate H9. + Trivial. + Intro H4. Rewrite H4 in H2. Discriminate H2. + Qed. + +Lemma ad_simple_path_dist_1_complete : (n:nat) (x,y:ad) (d:D) + (ad_simple_path_dist_1 x y (nil ad) n)=(SOME D d) -> + {l:(list ad) & (and_sp (CG_path y d (cons x l)) + (ad_list_stutters (cons x l))=false)}. + Proof. + Intros. Elim (ad_simple_path_dist_1_complete_1 n x y (nil ad) Dz + (CG_p1 x x (refl_equal ? ?)) (refl_equal ? ?) d H). + Intros l H0. Split with l. Elim H0. Intros H1 H2. Elim H2. Intros H3 H4. Split. + Rewrite (Dplus_d_z d) in H1. Assumption. + Exact H3. + Qed. + +Lemma ad_simple_path_dist_complete : (x,y:ad) (d:D) + (ad_simple_path_dist x y)=(SOME D d) -> + {l:(list ad) & (and_sp (CG_path y d (cons x l)) + (ad_list_stutters (cons x l))=false)}. + Proof. + Intros. Exact (ad_simple_path_dist_1_complete (MapCard ? cg) x y d H). + Qed. + +Lemma ad_simple_path_dist_complete_2 : (x,y:ad) (d:D) + (ad_simple_path_dist x y)=(SOME D d) -> + {l:(list ad) & (CG_path y d (cons x l))}. + Proof. + Intros. Elim (ad_simple_path_dist_complete x y d H). Intros l H0. Split with l. + (Elim H0; Trivial). + Qed. + +Lemma ad_simple_path_dist_complete_3 : (x,y:ad) (dd:(option D)) + ((l:(list ad)) (d:D) (CG_path y d (cons x l)) -> (Ddle dd (SOME ? d))=true) -> + (Ddle dd (ad_simple_path_dist x y))=true. + Proof. + Intros x y dd. Case dd. Intros. Elim (option_sum ? (ad_simple_path_dist x y)). Intro H0. + Elim H0. Intros d H1. Elim (ad_simple_path_dist_complete_2 x y d H1). Intros l H2. + Simpl in H. Rewrite <- (H l d H2). Rewrite H1. Reflexivity. + Intro H0. Rewrite H0. Reflexivity. + Intros. Elim (option_sum ? (ad_simple_path_dist x y)). Intro H0. Elim H0. Intros d0 H1. + Rewrite H1. Elim (ad_simple_path_dist_complete_2 x y d0 H1). Intros l H2. + Exact (H l d0 H2). + Intro H0. Rewrite H0. Reflexivity. + Qed. + +Lemma ad_simple_path_dist_d_1 : (x:ad) (ad_simple_path_dist x x)=(SOME ? Dz). + Proof. + Unfold ad_simple_path_dist. (Elim (MapCard ? cg); Simpl). Intro. + Rewrite (ad_eq_correct x). Reflexivity. + Intros. Rewrite (ad_eq_correct x). Reflexivity. + Qed. + +Lemma ad_simple_path_dist_d_2 : (x,y,z:ad) (d,d':D) + (ad_simple_path_dist x y)=(SOME ? d) -> (ad_simple_path_dist y z)=(SOME ? d') -> + (Ddle (ad_simple_path_dist x z) (SOME ? (Dplus d' d)))=true. + Proof. + Intros. Elim (ad_simple_path_dist_complete_2 x y d H). + Elim (ad_simple_path_dist_complete_2 y z d' H0). Intros l1 H1 l2 H2. + Apply (ad_simple_path_dist_correct x z (app l2 l1)). + Exact (CG_path_app_1 (cons x l2) l1 z y d d' H1 H2). + Qed. + +Lemma ad_simple_path_dist_d_3 : (x,y,z:ad) (d,d':D) + (Ddle (ad_simple_path_dist x y) (SOME ? d))=true -> + (Ddle (ad_simple_path_dist y z) (SOME ? d'))=true -> + (Ddle (ad_simple_path_dist x z) (SOME ? (Dplus d' d)))=true. + Proof. + Intros. Elim (option_sum ? (ad_simple_path_dist x y)). Intro H1. Elim H1. Intros d0 H2. + Elim (option_sum ? (ad_simple_path_dist y z)). Intro H3. Elim H3. Intros d'0 H4. + Apply Ddle_trans with dd':=(SOME D (Dplus d'0 d0)). + Exact (ad_simple_path_dist_d_2 x y z d0 d'0 H2 H4). + Rewrite H2 in H. Simpl in H. Rewrite H4 in H0. Simpl in H0. Simpl. + Exact (Dle_plus_mono ? ? ? ? H0 H). + Intro H3. Rewrite H3 in H0. Discriminate H0. + Intro H1. Rewrite H1 in H. Discriminate H. + Qed. + +(*s [(CG_leq x y)] is true when there is a path from [x] to [y] *) + +Definition CG_leq := [x,y:ad] Cases (ad_simple_path_dist x y) of + (SOME _) => true + | _ => false + end. + +Lemma CG_leq_refl : (x:ad) (CG_leq x x)=true. + Proof. + Unfold CG_leq. Intros. Rewrite (ad_simple_path_dist_d_1 x). Reflexivity. + Qed. + +Lemma CG_leq_trans : (x,y,z:ad) (CG_leq x y)=true -> (CG_leq y z)=true -> (CG_leq x z)=true. + Proof. + Unfold CG_leq. Intros. Elim (option_sum ? (ad_simple_path_dist x y)). Intro H1. + Elim H1. Intros d1 H2. Elim (option_sum ? (ad_simple_path_dist y z)). Intro H3. + Elim H3. Intros d2 H4. Cut (Ddle (ad_simple_path_dist x z) (SOME D (Dplus d2 d1)))=true. + Intro. Elim (option_sum ? (ad_simple_path_dist x z)). Intro H6. Elim H6. Intros d3 H7. + Rewrite H7. Reflexivity. + Intro H6. Rewrite H6 in H5. Discriminate H5. + Exact (ad_simple_path_dist_d_2 ? ? ? ? ? H2 H4). + Intro H3. Rewrite H3 in H0. Discriminate H0. + Intro H1. Rewrite H1 in H. Discriminate H. + Qed. + +(*s [(CG_standard_rho root d0 others x)] computes [d0-d] when + [root] and [x] are connected by a path of minimal + length [d] and [(others x)] when there are not connected +*) + +Definition CG_standard_rho + := [root:ad] [d0:D] [others:ad->D] [x:ad] + Cases (ad_simple_path_dist root x) of + (SOME d) => (Dplus d0 (Dneg d)) + | NONE => (others x) (* dummy *) + end. + +Lemma CG_standard_rho_root : (root:ad) (d0:D) (others:ad->D) + (CG_standard_rho root d0 others root)=d0. + Proof. + Unfold CG_standard_rho. Intros. Rewrite (ad_simple_path_dist_d_1 root). + Rewrite Dneg_Dz. Apply Dplus_d_z. + Qed. + +(*s If there is a root such that all the nodes ae connected to + this root, then [CG_standard_rho] gives a correct valuation +*) +Lemma CG_rooted_sat_1 : (root:ad) (d0:D) (others:ad->D) + ((x:ad) (in_dom ? x cg)=true -> (CG_leq root x)=true) -> + (CGsat (CG_standard_rho root d0 others)). + Proof. + Unfold CG_standard_rho. Intros. Unfold CGsat. Intros. + Elim (option_sum ? (ad_simple_path_dist root x)). Intro H1. Elim H1. Intros d1 H2. + Rewrite H2. Cut (Ddle (ad_simple_path_dist root y) (SOME D (Dplus d d1)))=true. Intro. + Elim (option_sum ? (ad_simple_path_dist root y)). Intro H4. Elim H4. Intros d2 H5. + Rewrite H5. Rewrite Dplus_assoc. Apply Dle_plus_mono. Apply Dle_refl. + Apply Dplus_reg_l with d'':=d2. Rewrite <- Dplus_assoc. Rewrite Dplus_neg. + Rewrite Dplus_z_d. Apply Dplus_reg_r with d'':=d1. Rewrite Dplus_assoc. + Rewrite Dplus_neg_2. Rewrite Dplus_d_z. Rewrite H5 in H3. Exact H3. + Intro H4. Rewrite H4 in H3. Discriminate H3. + Elim (ad_simple_path_dist_complete_2 root x d1 H2). Intros l H3. + Apply (ad_simple_path_dist_correct root y (app l (cons y (nil ad))) (Dplus d d1)). + Change (CG_path y (Dplus d d1) (app (cons root l) (cons y (nil ad)))). + Apply CG_path_app_1 with last:=y x:=x. Rewrite <- (Dplus_z_d d). Apply CG_p2. + Apply CG_p1. Reflexivity. + Assumption. + Assumption. + Intro H1. Cut (CG_leq root x)=true. + Unfold CG_leq. Rewrite H1. Intro. Discriminate H2. + Apply H. Rewrite MapDom_Dom. Exact (CG_edge_in_cg_1 ? ? ? H0). + Qed. + +Lemma CG_rooted_sat : (root:ad) (d0:D) + ((x:ad) (in_dom ? x cg)=true -> (CG_leq root x)=true) -> + {rho:ad->D | (CGsat rho) /\ (rho root)=d0}. + Proof. + Intros. Split with (CG_standard_rho root d0 [x:ad]d0). Split. + Exact (CG_rooted_sat_1 root d0 [x:ad]d0 H). + Apply CG_standard_rho_root. + Qed. + +(*s The [CG_standard_rho] valuation is the minimal one *) +Lemma CG_standard_rho_minimal : (root:ad) (d0:D) (others:ad->D) + (rho:ad->D) (CGsat rho) -> (Dle d0 (rho root))=true -> + (x:ad) (CG_leq root x)=true -> + (Dle (CG_standard_rho root d0 others x) (rho x))=true. + Proof. + Unfold CG_leq CG_standard_rho. Intros. Elim (option_sum ? (ad_simple_path_dist root x)). + Intro H2. Elim H2. Intros d H3. Rewrite H3. + Elim (ad_simple_path_dist_complete_2 root x d H3). Intros l H4. + Apply Dplus_reg_r with d'':=d. Rewrite Dplus_assoc. Rewrite Dplus_neg_2. + Rewrite Dplus_d_z. Apply Dle_trans with d':=(rho root). Exact H0. + Exact (CG_path_correct l root x d H4 rho H). + Intro H2. Rewrite H2 in H1. Discriminate H1. + Qed. + +Lemma CG_sat_add_1 : (x,y:ad) (d:D) + (rho:ad->D) (CGsat rho) -> (Dle (rho x) (Dplus (rho y) d))=true -> + (Ddle (SOME ? (Dneg d)) (ad_simple_path_dist y x))=true. + Proof. + Intros. Apply ad_simple_path_dist_complete_3. Intros. Simpl. + Apply Dplus_reg_r with d'':=d. Rewrite Dplus_neg_2. Apply Dplus_reg_l with d'':=(rho x). + Rewrite Dplus_d_z. Apply Dle_trans with d':=(Dplus (rho y) d); Try Assumption. + Apply Dle_trans with d':=(Dplus (Dplus (rho x) d0) d). Apply Dle_plus_mono. + Exact (CG_path_correct l y x d0 H1 rho H). + Apply Dle_refl. + Rewrite Dplus_assoc. Apply Dle_refl. + Qed. + + End CGNoBadCycles. + +(*s [(CG_add x y d)] adds the edge (x,y) of weight d to G, + in case an edge already exists, only the minimal one is kept +*) + +Definition CG_add := [x,y:ad; d:D] + Cases (MapGet ? cg x) of + NONE => (MapPut ? cg x (M1 ? y d)) + | (SOME edges) => Cases (MapGet ? edges y) of + NONE => (MapPut ? cg x (MapPut ? edges y d)) + | (SOME d0) => (MapPut ? cg x (MapPut ? edges y (Dmin d d0))) + end + end. + +End CGDist. + +(*s Properties of [CG_add] *) +Section CGAdd. + + Variable cg1 : CGraph1. + + Variable x,y : ad. + Variable d:D. + +Definition cg2 := (CG_add cg1 x y d). + +Lemma CG_add_edge_1 : (x0,y0:ad) (CG_edge cg2 x0 y0)= + (if (andb (ad_eq x x0) (ad_eq y y0)) + then (Ddmin (SOME ? d) (CG_edge cg1 x0 y0)) + else (CG_edge cg1 x0 y0)). + Proof. + Unfold cg2 CG_add. Intros. Elim (sumbool_of_bool (andb (ad_eq x x0) (ad_eq y y0))). + Intro H. Elim (andb_prop ? ? H). Intros H0 H1. Rewrite H. + Rewrite <- (ad_eq_complete ? ? H0). Rewrite <- (ad_eq_complete ? ? H1). + Elim (option_sum ? (MapGet ? cg1 x)). Intro H2. Elim H2. Intros edges H3. Rewrite H3. + Elim (option_sum ? (MapGet D edges y)). Intro H4. Elim H4. Intros d0 H5. Rewrite H5. + Unfold CG_edge. Rewrite (MapPut_semantics ? cg1 x (MapPut D edges y (Dmin d d0)) x). + Rewrite (ad_eq_correct x). Rewrite (MapPut_semantics ? edges y (Dmin d d0) y). + Rewrite (ad_eq_correct y). Rewrite H3. Rewrite H5. Reflexivity. + Intro H4. Rewrite H4. Unfold CG_edge. + Rewrite (MapPut_semantics ? cg1 x (MapPut D edges y d) x). Rewrite (ad_eq_correct x). + Rewrite H3. Rewrite H4. Rewrite (MapPut_semantics ? edges y d y). + Rewrite (ad_eq_correct y). Reflexivity. + Intro H2. Rewrite H2. Unfold CG_edge. Rewrite (MapPut_semantics ? cg1 x (M1 D y d) x). + Rewrite (ad_eq_correct x). Rewrite H2. Rewrite (M1_semantics_1 ? y d). Reflexivity. + Intro H. Rewrite H. Elim (andb_false_elim ? ? H). Intro H0. + Elim (option_sum ? (MapGet ? cg1 x)). Intro H1. Elim H1. Intros edges H2. Rewrite H2. + Elim (option_sum ? (MapGet ? edges y)). Intro H3. Elim H3. Intros d0 H4. Rewrite H4. + Unfold CG_edge. Rewrite (MapPut_semantics ? cg1 x (MapPut D edges y (Dmin d d0)) x0). + Rewrite H0. Reflexivity. + Intro H3. Rewrite H3. Unfold CG_edge. + Rewrite (MapPut_semantics ? cg1 x (MapPut D edges y d) x0). Rewrite H0. Reflexivity. + Intro H1. Rewrite H1. Unfold CG_edge. Rewrite (MapPut_semantics ? cg1 x (M1 D y d) x0). + Rewrite H0. Reflexivity. + Intro H0. Elim (option_sum ? (MapGet ? cg1 x)). Intro H1. Elim H1. Intros edges H2. + Rewrite H2. Elim (option_sum ? (MapGet ? edges y)). Intro H3. Elim H3. Intros d0 H4. + Rewrite H4. Unfold CG_edge. + Rewrite (MapPut_semantics ? cg1 x (MapPut D edges y (Dmin d d0)) x0). + Elim (sumbool_of_bool (ad_eq x x0)). Intro H5. Rewrite H5. + Rewrite (MapPut_semantics ? edges y (Dmin d d0) y0). Rewrite H0. + Rewrite <- (ad_eq_complete ? ? H5). Rewrite H2. Reflexivity. + Intro H5. Rewrite H5. Reflexivity. + Intro H3. Rewrite H3. Unfold CG_edge. + Rewrite (MapPut_semantics ? cg1 x (MapPut D edges y d) x0). + Elim (sumbool_of_bool (ad_eq x x0)). Intro H4. Rewrite H4. + Rewrite <- (ad_eq_complete ? ? H4). Rewrite H2. + Rewrite (MapPut_semantics ? edges y d y0). Rewrite H0. Reflexivity. + Intro H4. Rewrite H4. Reflexivity. + Intro H1. Rewrite H1. Unfold CG_edge. Rewrite (MapPut_semantics ? cg1 x (M1 D y d) x0). + Elim (sumbool_of_bool (ad_eq x x0)). Intro H2. Rewrite H2. + Rewrite (M1_semantics_2 ? y y0 d H0). Rewrite <- (ad_eq_complete ? ? H2). + Rewrite H1. Reflexivity. + Intro H2. Rewrite H2. Reflexivity. + Qed. + +Lemma CG_add_edge_2 : (x0,y0:ad) (Ddle (CG_edge cg2 x0 y0) (CG_edge cg1 x0 y0))=true. + Proof. + Intros. Rewrite (CG_add_edge_1 x0 y0). + Elim (sumbool_of_bool (andb (ad_eq x x0) (ad_eq y y0))). Intro H. Rewrite H. + Apply Ddmin_le_2. + Intro H. Rewrite H. Apply Ddle_refl. + Qed. + +Lemma CG_add_1 : (rho:ad->D) + (CGsat cg1 rho) -> (Dle (rho x) (Dplus (rho y) d))=true + -> (CGsat cg2 rho). + Proof. + Unfold CGsat. Intros. Rewrite (CG_add_edge_1 x0 y0) in H1. + Elim (sumbool_of_bool (andb (ad_eq x x0) (ad_eq y y0))). Intro H2. + Elim (andb_prop ? ? H2). Intros H3 H4. Rewrite H2 in H1. + Rewrite <- (ad_eq_complete ? ? H3). Rewrite <- (ad_eq_complete ? ? H4). + Elim (option_sum ? (CG_edge cg1 x0 y0)). Intro H5. Elim H5. Intros d1 H6. + Rewrite H6 in H1. Simpl in H1. Inversion H1. Rewrite Dmin_plus_r. Apply Dmin_le_5. + Assumption. + Apply H. Rewrite (ad_eq_complete ? ? H3). Rewrite (ad_eq_complete ? ? H4). Assumption. + Intro H5. Rewrite H5 in H1. Simpl in H1. Inversion H1. Rewrite <- H7. Assumption. + Intro H2. Rewrite H2 in H1. Apply H. Assumption. + Qed. + +Lemma CG_add_2 : (rho:ad->D) (CGsat cg2 rho) -> (CGsat cg1 rho). + Proof. + Unfold CGsat. Intros. Elim (option_sum ? (CG_edge cg2 x0 y0)). Intro H1. Elim H1. + Intros d1 H2. Cut (Dle d1 d0)=true. Intro H3. + Apply Dle_trans with d':=(Dplus (rho y0) d1). Apply H. Assumption. + Apply Dle_plus_mono. Apply Dle_refl. + Assumption. + Change (Ddle (SOME ? d1) (SOME ? d0))=true. Rewrite <- H2. Rewrite <- H0. + Apply CG_add_edge_2. + Intro H1. Cut (Ddle (NONE ?) (SOME ? d0))=true. Intro H2. Discriminate H2. + Rewrite <- H1. Rewrite <- H0. Apply CG_add_edge_2. + Qed. + +Lemma CG_add_3 : (rho:ad->D) (CGsat cg2 rho) -> (Dle (rho x) (Dplus (rho y) d))=true. + Proof. + Unfold CGsat. Intros. Elim (option_sum ? (CG_edge cg2 x y)). Intro H0. Elim H0. + Intros d0 H1. Apply Dle_trans with d':=(Dplus (rho y) d0). Apply H. Assumption. + Apply Dle_plus_mono. Apply Dle_refl. + Rewrite (CG_add_edge_1 x y) in H1. Rewrite (ad_eq_correct x) in H1. + Rewrite (ad_eq_correct y) in H1. Simpl in H1. Elim (option_sum ? (CG_edge cg1 x y)). + Intro H2. Elim H2. Intros d1 H3. Rewrite H3 in H1. Inversion H1. Apply Dmin_le_1. + Intro H2. Rewrite H2 in H1. Inversion H1. Apply Dle_refl. + Intro H0. Rewrite (CG_add_edge_1 x y) in H0. Rewrite (ad_eq_correct x) in H0. + Rewrite (ad_eq_correct y) in H0. Simpl in H0. Generalize H0. + (Case (CG_edge cg1 x y); Intro H1). Discriminate H1. + Intro H2. Discriminate H2. + Qed. + +(*s Every path in the new graph [cg2] either goes through the new edge from [x] to [y], + or is a path in the old graph cg1: +*) +Lemma CG_add_4_1 : (l:(list ad)) (x0,y0:ad) (d0:D) (CG_path cg2 y0 d0 (cons x0 l)) -> + {l0:(list ad) & {l1:(list ad) | (cons x0 l)=(app l0 (cons x (cons y l1)))}}+ + (CG_path cg1 y0 d0 (cons x0 l)). + Proof. + Induction l. Intros. Inversion H. Right . Rewrite H2. + Rewrite <- H1. Apply CG_p1. + Reflexivity. + Intros. Inversion H0. Rewrite (CG_add_edge_1 x0 a) in H6. + Elim (sumbool_of_bool (andb (ad_eq x x0) (ad_eq y a))). Intro H8. Left . + Split with (nil ad). Split with l0. Elim (andb_prop ? ? H8). Intros H9 H10. + Rewrite (ad_eq_complete ? ? H9). Rewrite (ad_eq_complete ? ? H10). Reflexivity. + Intro H8. Elim (H ? ? ? H4). Intro H9. Elim H9. Intros l2 H10. Elim H10. Intros l3 H11. + Left . Split with (cons x0 l2). Split with l3. Rewrite H11. Reflexivity. + Intro H9. Right . Apply CG_p2. Assumption. + Rewrite H8 in H6. Assumption. + Qed. + +Lemma CG_add_4_2 : (l:(list ad)) (last:ad) (d0:D) + (CG_path cg2 last d0 l) -> (ad_in_list y l)=false -> (CG_path cg1 last d0 l). + Proof. + Induction l. Intros. Inversion H. + Intros a l0. Case l0. Intros. Inversion H0. Rewrite <- H3. Apply CG_p1. Assumption. + Intros. Inversion H0. Rewrite (CG_add_edge_1 a a0) in H7. Elim (orb_false_elim ? ? H1). + Intros H9 H10. Elim (orb_false_elim ? ? H10). + Intros H11 H12. Rewrite H11 in H7. + Rewrite (andb_b_false (ad_eq x a)) in H7. Apply CG_p2. Apply H. Assumption. + Exact H10. + Assumption. + Qed. + +Lemma CG_add_4_3 : (x0:ad) (d0:D) (l:(list ad)) + (ad_list_stutters (cons y l))=false -> + (CG_path cg2 x0 d0 (cons y l)) -> (CG_path cg1 x0 d0 (cons y l)). + Proof. + Intros x0 d0 l. Elim l. Intros. Inversion H0. + Rewrite <- H2. Apply CG_p1. Assumption. + Intros. Inversion H1. Apply CG_p2. Apply CG_add_4_2. + Assumption. + Elim (orb_false_elim ? ? H0). Trivial. + Rewrite (CG_add_edge_1 y a) in H7. + Elim (orb_false_elim ? ? H0). Intros. + Elim (orb_false_elim ? ? H8). Intros. Rewrite H10 in H7. + Rewrite (andb_b_false (ad_eq x y)) in H7. Assumption. + Qed. + +Lemma CG_add_4_4 : (l:(list ad)) (last:ad) (d0:D) + (CG_path cg2 last d0 l) -> (ad_in_list x l)=false -> (CG_path cg1 last d0 l). + Proof. + Induction l. Intros. Inversion H. + Intros a l0. Case l0. Intros. Inversion H0. Rewrite <- H3. Apply CG_p1. Assumption. + Intros. Inversion H0. Apply CG_p2. Apply H. Assumption. + Elim (orb_false_elim ? ? H1). Trivial. + Rewrite (CG_add_edge_1 a a0) in H7. Elim (orb_false_elim ? ? H1). Intros. + Rewrite H8 in H7. Exact H7. + Qed. + +Lemma CG_add_4_5 : (d0:D) (l:(list ad)) + (ad_list_stutters (app l (cons x (nil ad))))=false -> + (CG_path cg2 x d0 (app l (cons x (nil ad)))) -> + (CG_path cg1 x d0 (app l (cons x (nil ad)))). + Proof. + Intros d0 l. Cut {l0:(list ad) & {y0:ad | l=(app l0 (cons y0 (nil ad)))}}+{l=(nil ad)}. + Intro. Elim H. Intro H0. Elim H0. Intros l0 H1. Elim H1. Intros y0 H2 H3 H4. + Rewrite H2 in H4. Rewrite (app_ass l0 (cons y0 (nil ad)) (cons x (nil ad))) in H4. + Simpl in H4. Elim (CG_path_app_3 cg2 l0 (cons x (nil ad)) x y0 d0 H4). Intros d1 H5. + Rewrite H2. Rewrite (app_ass l0 (cons y0 (nil ad)) (cons x (nil ad))). Simpl. + Elim (CG_path_app_2 cg2 l0 (cons x (nil ad)) x y0 d0 H4). Intros d2 H6. + Cut d0=(Dplus d2 d1). Intro. Rewrite H7. + Change (CG_path cg1 x (Dplus d2 d1) (app l0 (app (cons y0 (nil ad)) (cons x (nil ad))))). + Rewrite <- (app_ass l0 (cons y0 (nil ad)) (cons x (nil ad))). + Apply CG_path_app_1 with last:=x x:=y0. Inversion H6. + Inversion H11. Apply CG_p2. + Rewrite <- H15. Apply CG_p1. Assumption. + Rewrite (CG_add_edge_1 y0 x) in H13. Rewrite H2 in H3. + Rewrite (app_ass l0 (cons y0 (nil ad)) (cons x (nil ad))) in H3. Simpl in H3. + Elim (orb_false_elim ? ? (ad_list_stutters_app_conv_r ? ? H3)). Intros. + Elim (orb_false_elim ? ? H17). Intros. + Rewrite (ad_eq_comm y0 x) in H19. + Rewrite H19 in H13. + Rewrite (andb_false_b (ad_eq y x)) in H13. Assumption. + Apply CG_add_4_4. Assumption. + Rewrite H2 in H3. Apply ad_list_stutters_prev_conv_l with l':=(nil ad). Assumption. + Elim (CG_path_weight_and_last_unique cg2 + (app l0 (cons y0 (cons x (nil ad)))) x x d0 (Dplus d2 d1)). + Trivial. + Assumption. + Change (CG_path cg2 x (Dplus d2 d1) (app l0 (app (cons y0 (nil ad)) (cons x (nil ad))))). + Rewrite <- (app_ass l0 (cons y0 (nil ad)) (cons x (nil ad))). + Apply CG_path_app_1 with x:=y0. Assumption. + Assumption. + Intro H0. Rewrite H0. Simpl. Intros. Inversion H2. + Rewrite <- H4. Apply CG_p1. + Assumption. + Elim l. Right . Reflexivity. + Intros. Elim H. Intro H0. Elim H0. Intros l1 H1. Elim H1. Intros a0 H2. Rewrite H2. + Left . Split with (cons a l1). Split with a0. Reflexivity. + Intro H0. Rewrite H0. Left . Split with (nil ad). Split with a. Reflexivity. + Qed. + +(*s If there is no cycle of negative weight in the old graph [cg1], and the distance + from [y] to [x] is $\geq -d$, then there is no simple cycle of negative weight in + the new graph [cg2] either: *) + +Lemma CG_add_4 : + ((x0:ad) (d0:D) (l:(list ad)) (CG_path cg1 x0 d0 (cons x0 l)) -> (Dle Dz d0)=true) -> + (Ddle (SOME ? (Dneg d)) (ad_simple_path_dist cg1 y x))=true -> + (x0:ad) (d0:D) (l:(list ad)) (CG_path cg2 x0 d0 (cons x0 l)) -> + (ad_list_stutters l)=false -> (Dle Dz d0)=true. + Proof. + Intros. Elim (CG_add_4_1 ? ? ? ? H1). Intro H3. Elim H3. Intros l0 H4. Elim H4. + Intros l1 H5. Rewrite H5 in H1. + Change (CG_path cg2 x0 d0 (app l0 (app (cons x (nil ad)) (cons y l1)))) in H1. + Elim (CG_path_app_4 cg2 ? ? ? ? ? H1). Intros d1 H6. Elim H6. Intros d2 H7. + Elim H7. Intros H8 H9. Elim H8. Intros H10 H11. Clear H3 H6 H7 H8. Rewrite H9. + Inversion_clear H11. Rewrite (CG_add_edge_1 x y) in H6. Rewrite (ad_eq_correct x) in H6. + Rewrite (ad_eq_correct y) in H6. Simpl in H6. Apply Dplus_reg_r with d'':=(Dneg d1). + Rewrite Dplus_assoc. Rewrite Dplus_neg. Rewrite Dplus_d_z. Rewrite Dplus_z_d. + Apply Dplus_reg_l with d'':=d1. Rewrite Dplus_neg. Rewrite <- Dplus_assoc. + Change (cons x0 l)=(app l0 (app (cons x (nil ad)) (cons y l1))) in H5. + Rewrite (ass_app l0 (cons x (nil ad)) (cons y l1)) in H5. + Cut {l'0:(list ad) | (app l0 (cons x (nil ad)))=(cons x0 l'0)}. Intro H7. Elim H7. + Intros l'0 H8. Clear H4 H7. Rewrite H8 in H5. Simpl in H5. Inversion H5. Rewrite H8 in H10. + Cut (CG_path cg1 x (Dplus d1 d3) (cons y (app l1 l'0))). Intro. + Elim (option_sum ? (CG_edge cg1 x y)). Intro H11. Elim H11. Intros d'0 H12. + Rewrite H12 in H6. Inversion_clear H6. Elim (Dmin_choice d d'0). Intro H13. Rewrite H13. + Apply Dplus_reg_r with d'':=(Dneg d). Rewrite Dplus_assoc. Rewrite Dplus_neg. + Rewrite Dplus_d_z. Rewrite Dplus_z_d. + Change (Ddle (SOME D (Dneg d)) (SOME D (Dplus d1 d3)))=true. + Apply Ddle_trans with dd':=(ad_simple_path_dist cg1 y x). Assumption. + Exact (ad_simple_path_dist_correct cg1 H y x ? ? H4). + Intro H13. Rewrite H13. Apply (H x (Dplus (Dplus d1 d3) d'0) (cons y (app l1 l'0))). + Apply (CG_path_app_1 cg1 (cons x (cons y (nil ad))) (app l1 l'0) x y). Assumption. + Rewrite <- (Dplus_z_d d'0). Apply CG_p2. Apply CG_p1. Reflexivity. + Assumption. + Intro H11. Rewrite H11 in H6. Inversion H6. Rewrite <- H13. + Apply Dplus_reg_r with d'':=(Dneg d). Rewrite Dplus_assoc. Rewrite Dplus_neg. + Rewrite Dplus_d_z. Rewrite Dplus_z_d. + Change (Ddle (SOME D (Dneg d)) (SOME D (Dplus d1 d3)))=true. + Apply Ddle_trans with dd':=(ad_simple_path_dist cg1 y x). Assumption. + Exact (ad_simple_path_dist_correct cg1 H y x ? ? H4). + Apply (CG_path_app_1 cg1 (cons y l1) l'0 x x0). Rewrite <- H8. Apply CG_add_4_5. + Rewrite H8. Elim (CG_path_last cg2 ? ? ? H3). Intros l'1 H11. Rewrite H7 in H2. + Simpl. Rewrite (ad_list_stutters_app_conv_l ? ? H2). Rewrite H11 in H2. + Rewrite (ass_app l'0 l'1 (cons x0 (nil ad))) in H2. + Elim (sumbool_of_bool (ad_in_list x0 l'0)). Intro H12. + Rewrite (ad_list_stutters_prev_l ? (nil ad) ? (ad_in_list_l l'0 l'1 x0 H12)) in H2. + Discriminate H2. + Intro H12. Rewrite H12. Reflexivity. + Rewrite H8. Assumption. + Apply CG_add_4_3. Rewrite H7 in H2. Exact (ad_list_stutters_app_conv_r l'0 (cons y l1) H2). + Assumption. + Generalize H5. Elim l0. Simpl. Intro H7. Exists (nil ad). Inversion_clear H7. Reflexivity. + Intros. Rewrite (app_ass (cons a l2) (cons x (nil ad)) (cons y l1)) in H8. Simpl in H8. + Exists (app l2 (cons x (nil ad))). Inversion_clear H8. Reflexivity. + Intro H3. Exact (H x0 d0 l H3). + Qed. + +Lemma CG_add_5_1 : (n:nat) + ((x0:ad) (d0:D) (l:(list ad)) (CG_path cg1 x0 d0 (cons x0 l)) -> (Dle Dz d0)=true) -> + (Ddle (SOME ? (Dneg d)) (ad_simple_path_dist cg1 y x))=true -> + (x0:ad) (d0:D) (l:(list ad)) (CG_path cg2 x0 d0 (cons x0 l)) -> + (le (length l) n) -> (Dle Dz d0)=true. + Proof. + Induction n. Induction l. Intros. Inversion H1. Apply Dle_refl. + Intros. Elim (le_Sn_O ? H3). + Intros. Elim (sumbool_of_bool (ad_list_stutters l)). Intros H4. + Elim (ad_list_stutters_has_circuit l H4). Intros y0 H5. Elim H5. Intros l0 H6. Elim H6. + Intros l1 H7. Elim H7. Intros l2 H8. Rewrite H8 in H2. + Elim (CG_path_app_4 cg2 (cons x0 l0) (app l1 (cons y0 l2)) x0 y0 d0 H2). Intros d1 H9. + Elim H9. Intros d2 H10. Elim H10. Intros H11 H12. Elim H11. Intros H13 H14. + Clear H5 H6 H7 H9 H10 H11. Elim (CG_path_app_4 cg2 (cons y0 l1) l2 x0 y0 d2 H14). + Intros d3 H5. Elim H5. Intros d4 H6. Elim H6. Intros H7 H9. Elim H7. Intros H10 H11. + Clear H5 H6 H7 H14. Rewrite H12. Rewrite H9. Apply Dle_trans with d':=(Dplus d4 d1). + Apply (H H0 H1 x0 (Dplus d4 d1) (app l0 (cons y0 l2))). + Cut (cons x0 (app l0 (cons y0 l2)))=(app (app (cons x0 l0) (cons y0 (nil ad))) l2). + Intro. Rewrite H5. Exact (CG_path_app_1 cg2 ? ? ? ? ? ? H11 H13). + Exact (ass_app (cons x0 l0) (cons y0 (nil ad)) l2). + Rewrite ad_list_app_length. Apply le_S_n. Apply le_trans with m:=(length l). + Rewrite H8. Rewrite ad_list_app_length. Simpl. Rewrite ad_list_app_length. Simpl. + Rewrite <- plus_Snm_nSm. Rewrite <- plus_Snm_nSm. Rewrite <- plus_Snm_nSm. Simpl. + Rewrite <- plus_Snm_nSm. Simpl. Apply le_n_S. Apply le_n_S. Apply le_reg_l. + Apply le_plus_r. Assumption. + Apply Dle_plus_mono. Apply Dle_trans with (Dplus d4 Dz). Rewrite Dplus_d_z. Apply Dle_refl. + Apply Dle_plus_mono. Apply Dle_refl. + Apply (H H0 H1 y0 d3 (app l1 (cons y0 (nil ad))) H10). Rewrite ad_list_app_length. Simpl. + Apply le_S_n. Apply le_trans with m:=(length l). Rewrite H8. Rewrite ad_list_app_length. + Simpl. Rewrite ad_list_app_length. Simpl. Rewrite <- plus_Snm_nSm. Rewrite <- plus_Snm_nSm. + Rewrite <- plus_Snm_nSm. Simpl. Rewrite <- plus_Snm_nSm. Simpl. Apply le_n_S. Apply le_n_S. + Apply le_trans with m:=(plus (length l1) (length l2)). Apply le_plus_plus. Apply le_n. + Apply le_O_n. Apply le_plus_r. Assumption. + Apply Dle_refl. + Intro H4. Exact (CG_add_4 H0 H1 x0 d0 l H2 H4). + Qed. + +Lemma CG_add_5 : + ((x0:ad) (d0:D) (l:(list ad)) (CG_path cg1 x0 d0 (cons x0 l)) -> (Dle Dz d0)=true) -> + (Ddle (SOME ? (Dneg d)) (ad_simple_path_dist cg1 y x))=true -> + (x0:ad) (d0:D) (l:(list ad)) (CG_path cg2 x0 d0 (cons x0 l)) -> (Dle Dz d0)=true. + Proof. + Intros. Exact (CG_add_5_1 (length l) H H0 x0 d0 l H1 (le_n ?)). + Qed. + + End CGAdd. + +(*s Properties of the range of the graph *) + +Definition cg_range := (DMerge D). + +Lemma cg_range_1 + : (cg:CGraph1) (x,y:ad) (d:D) + (CG_edge cg x y)=(SOME ? d) -> (in_dom D y (cg_range cg))=true. + Proof. + Unfold cg_range CG_edge. Intros. Elim (option_sum ? (MapGet ? cg x)). Intro H0. Elim H0. + Intros edges H1. Rewrite H1 in H. Apply in_dom_DMerge_3 with a:=x m0:=edges. Assumption. + Unfold in_dom. Generalize H. Case (MapGet D edges y). Intro H2. Discriminate H2. + Trivial. + Intro H0. Rewrite H0 in H. Discriminate H. + Qed. + +Lemma cg_range_2 + : (cg:CGraph1) (y:ad) (in_dom D y (cg_range cg))=true -> + {x:ad & {d:D | (CG_edge cg x y)=(SOME ? d)}}. + Proof. + Intros. Elim (in_dom_DMerge_2 ? cg y H). Intros x H0. Elim H0. Intros edges H1. Elim H1. + Intros H2 H3. Split with x. Elim (in_dom_some ? edges y H3). Intros d H4. Split with d. + Unfold CG_edge. Rewrite H2. Rewrite H4. Reflexivity. + Qed. + +Lemma cg_range_4 : (cg:CGraph1) (x,y:ad) (d:D) (a:ad) + (in_dom D a (cg_range (CG_add cg x y d)))=(orb (ad_eq a y) (in_dom D a (cg_range cg))). + Proof. + Intros. Elim (sumbool_of_bool (in_dom D a (cg_range (CG_add cg x y d)))). Intro H. + Elim (cg_range_2 ? ? H). Intros a0 H0. Elim H0. Intros d0 H1. Clear H0. + Change (CG_edge (cg2 cg x y d) a0 a)=(SOME D d0) in H1. + Rewrite (CG_add_edge_1 cg x y d a0 a) in H1. Rewrite H. + Elim (sumbool_of_bool (andb (ad_eq x a0) (ad_eq y a))). Intro H2. Elim (andb_prop ? ? H2). + Intros H3 H4. Rewrite (ad_eq_comm y a) in H4. Rewrite H4. Reflexivity. + Intro H2. Rewrite H2 in H1. Rewrite (cg_range_1 ? ? ? ? H1). Apply sym_eq. Apply orb_b_true. + Intro H. Rewrite H. Elim (sumbool_of_bool (ad_eq a y)). Intro H0. + Rewrite (ad_eq_complete ? ? H0) in H. Cut {d0:D | (CG_edge (cg2 cg x y d) x y)=(SOME ? d0)}. + Intro H1. Elim H1. Intros d0 H2. Unfold cg2 in H2. Rewrite (cg_range_1 ? ? ? ? H2) in H. + Discriminate H. + Rewrite (CG_add_edge_1 cg x y d x y). Rewrite (ad_eq_correct x). Rewrite (ad_eq_correct y). + Case (CG_edge cg x y). Split with d. Reflexivity. + Intro d0. Split with (Dmin d d0). Reflexivity. + Intro H0. Rewrite H0. Elim (sumbool_of_bool (in_dom D a (cg_range cg))). Intro H1. + Elim (cg_range_2 ? ? H1). Intros a0 H2. Elim H2. Intros d0 H3. + Cut {d1:D | (CG_edge (cg2 cg x y d) a0 a)=(SOME ? d1)}. Intro H4. Elim H4. Intros d1 H5. + Unfold cg2 in H5. Rewrite (cg_range_1 ? ? ? ? H5) in H. Discriminate H. + Rewrite (CG_add_edge_1 cg x y d a0 a). Rewrite (ad_eq_comm a y) in H0. Rewrite H0. + Rewrite (andb_b_false (ad_eq x a0)). Split with d0. Assumption. + Intro H1. Rewrite H1. Reflexivity. + Qed. + +Lemma cg_out_of_range_1 : (cg:CGraph1) (y:ad) (in_dom D y (cg_range cg))=false -> + (x:ad) (CG_edge cg x y)=(NONE D). + Proof. + Intros. Elim (option_sum ? (CG_edge cg x y)). Intro H0. Elim H0. Intros d H1. + Rewrite (cg_range_1 cg x y d H1) in H. Discriminate H. + Trivial. + Qed. + +Lemma cg_out_of_range_2 : (cg:CGraph1) (y:ad) (in_dom D y (cg_range cg))=false -> + (x:ad) (ad_eq x y)=false -> (ad_simple_path_dist cg x y)=(NONE D). + Proof. + Intros. Elim (option_sum ? (ad_simple_path_dist cg x y)). Intro H1. Elim H1. Intros d H2. + Elim (ad_simple_path_dist_complete_2 cg x y d H2). Intros l H3. + Cut {a:ad & {d':D | (CG_edge cg a y)=(SOME ? d')}}. Intro H4. Elim H4. Intros a H5. Elim H5. + Intros d' H6. Rewrite (cg_out_of_range_1 cg y H a) in H6. Discriminate H6. + Generalize x H0 d H3. Elim l. Intros. Inversion H5. + Rewrite H8 in H4. + Rewrite (ad_eq_correct y) in H4. Discriminate H4. + Intros. Inversion H6. Elim (sumbool_of_bool (ad_eq a y)). + Intro H14. Split with x0. + Split with d'. Rewrite <- (ad_eq_complete ? ? H14). Assumption. + Intro H14. Exact (H4 a H14 ? H10). + Trivial. + Qed. + +Lemma cg_out_of_range_3 : (cg:CGraph1) (y:ad) (in_dom D y (cg_range cg))=false -> + (x:ad) (ad_eq x y)=false -> (CG_leq cg x y)=false. + Proof. + Intros. Unfold CG_leq. Rewrite (cg_out_of_range_2 cg y H x H0). Reflexivity. + Qed. + +Lemma cg_add_out_of_range_1 : (cg:(CGraph1)) (x,y:ad) (d:D) + ((x0:ad) (d0:D) (l:(list ad)) (CG_path cg x0 d0 (cons x0 l)) -> (Dle Dz d0)=true) -> + (in_dom D x (cg_range cg))=false -> + (ad_eq y x)=false -> + (x0:ad) (d0:D) (l:(list ad)) (CG_path (CG_add cg x y d) x0 d0 (cons x0 l)) -> + (Dle Dz d0)=true. + Proof. + Intros. Apply (CG_add_5 cg x y d H) with x0:=x0 l:=l. + Rewrite (cg_out_of_range_2 cg x H0 y H1). Reflexivity. + Assumption. + Qed. + + +Lemma cg_add_dom_subset : (cg:CGraph1) (x,y:ad) (d:D) + (MapSubset ? ? (MapDom ? cg) (MapDom ? (CG_add cg x y d))). + Proof. + Unfold CG_add. Intros. Elim (option_sum ? (MapGet ? cg x)). Intro H. Elim H. Intros edges H0. + Rewrite H0. Elim (option_sum ? (MapGet D edges y)). Intro H1. Elim H1. Intros d0 H2. + Rewrite H2. Apply MapSubset_Dom_1. Apply MapSubset_Put. + Intro H1. Rewrite H1. Apply MapSubset_Dom_1. Apply MapSubset_Put. + Intro H. Rewrite H. Apply MapSubset_Dom_1. Apply MapSubset_Put. + Qed. + +(*s Adding a lis of adresses connected to [root] with weight $0$ *) + +Fixpoint CG_add_root [root:ad; cg:CGraph1; l:(list ad)] : CGraph1 := + Cases l of + nil => cg + | (cons x l') => (CG_add_root root (CG_add cg root x Dz) l') + end. + +Lemma CG_add_root_out_of_range : (l:(list ad)) (cg:CGraph1) (root:ad) + ((x0:ad) (d0:D) (l:(list ad)) (CG_path cg x0 d0 (cons x0 l)) -> (Dle Dz d0)=true) -> + (MapSubset ? ? (Elems l) (MapDom ? cg)) -> + (ad_in_list root l)=false -> + (in_dom ? root (cg_range cg))=false -> + (x0:ad) (d0:D) (l0:(list ad)) (CG_path (CG_add_root root cg l) x0 d0 (cons x0 l0)) -> + (Dle Dz d0)=true. + Proof. + Induction l. Trivial. + Simpl. Intros. Apply (H (CG_add cg root a Dz) root) with x0:=x0 d0:=d0 l1:=l1. Intros. + Apply (cg_add_out_of_range_1 cg root a Dz) with x0:=x1 d0:=d1 l:=l2. Intros. + Exact (H0 ? ? ? H6). + Assumption. + Elim (orb_false_elim ? ? H2). Intros. Rewrite ad_eq_comm. Assumption. + Assumption. + Apply MapSubset_trans with m':=(MapPut unit (Elems l0) a tt). Apply MapSubset_Put. + Apply MapSubset_trans with m':=(MapDom ? cg). Assumption. + Apply cg_add_dom_subset. + Elim (orb_false_elim ? ? H2). Trivial. + Rewrite cg_range_4. Elim (orb_false_elim ? ? H2). Intros H5 H6. Rewrite H5. Rewrite H3. + Reflexivity. + Assumption. + Qed. + +Lemma CG_add_rooted_1 : (cg:CGraph1) (root,a:ad) (d:D) + (CG_edge cg root a)=(NONE D) -> + (CG_edge (CG_add cg root a d) root a)=(SOME D d). + Proof. + Intros. Change (CG_edge (cg2 cg root a d) root a)=(SOME D d). Rewrite CG_add_edge_1. + Rewrite (ad_eq_correct root). Rewrite (ad_eq_correct a). Rewrite H. Reflexivity. + Qed. + +Lemma CG_add_root_rooted_1 : (l:(list ad)) (cg:CGraph1) (root,a:ad) + (ad_list_stutters l)=false -> + (ad_in_list a l)=false -> (d:D) (CG_edge cg root a)=(SOME D d) -> + (CG_edge (CG_add_root root cg l) root a)=(SOME D d). + Proof. + Induction l. Trivial. + Simpl. Intros. Elim (orb_false_elim ? ? H0). Intros. Elim (orb_false_elim ? ? H1). + Intros. Apply H. Assumption. + Assumption. + Change (CG_edge (cg2 cg root a Dz) root a0)=(SOME D d). Rewrite CG_add_edge_1. + Rewrite (ad_eq_comm a a0). Rewrite H5. Rewrite (andb_b_false (ad_eq root root)). Assumption. + Qed. + +Lemma CG_add_root_rooted_2 : (l:(list ad)) (cg:CGraph1) (root:ad) + (ad_list_stutters l)=false -> + ((a0:ad) (ad_in_list a0 l)=true -> (CG_edge cg root a0)=(NONE D)) -> + (a:ad) (ad_in_list a l)=true -> + (CG_edge (CG_add_root root cg l) root a)=(SOME ? Dz). + Proof. + Induction l. Intros. Discriminate H1. + Simpl. Intros. Elim (orb_false_elim ? ? H0). Intros. Elim (sumbool_of_bool (ad_eq a0 a)). + Intro H5. Rewrite (ad_eq_complete ? ? H5). Apply CG_add_root_rooted_1. Assumption. + Assumption. + Apply CG_add_rooted_1. Apply H1. Rewrite (ad_eq_correct a). Reflexivity. + Intro H5. Rewrite H5 in H2. Simpl in H2. Apply H. Assumption. + Intros. Change (CG_edge (cg2 cg root a Dz) root a1)=(NONE D). Rewrite CG_add_edge_1. + Elim (sumbool_of_bool (ad_eq a a1)). Intro H7. Rewrite (ad_eq_complete ? ? H7) in H3. + Rewrite H6 in H3. Discriminate H3. + Intro H7. Rewrite H7. Rewrite (andb_b_false (ad_eq root root)). + Apply H1. Rewrite H6. Apply orb_b_true. + Assumption. + Qed. + +Lemma CG_add_root_rooted_3 : (cg:CGraph1) (root:ad) + (in_dom ? root cg)=false -> + (a:ad) (in_dom ? a cg)=true -> + (CG_edge (CG_add_root root cg (ad_list_of_dom ? cg)) root a)=(SOME ? Dz). + Proof. + Intros. Apply CG_add_root_rooted_2. Apply ad_list_of_dom_not_stutters. + Intros. Unfold CG_edge. Rewrite (in_dom_none ? ? ? H). Reflexivity. + Rewrite ad_in_list_of_dom_in_dom. Assumption. + Qed. + +Lemma CG_add_root_rooted_4 : (l:(list ad)) (cg:CGraph1) (root:ad) (a:ad) + (in_dom ? a (CG_add_root root cg l))=true -> {a=root}+{(in_dom ? a cg)=true}. + Proof. + Induction l. Intros. Right . Exact H. + Simpl. Intros. Elim (H (CG_add cg root a Dz) root a0 H0). Intro H1. Left . Assumption. + Intro H1. Unfold in_dom CG_add in H1. Elim (option_sum ? (MapGet ? cg root)). Intro H2. + Elim H2. Intros edges H3. Rewrite H3 in H1. Elim (option_sum ? (MapGet D edges a)). Intro H4. + Elim H4. Intros d H5. Rewrite H5 in H1. + Rewrite (MapPut_semantics ? cg root (MapPut D edges a (Dmin Dz d)) a0) in H1. + Elim (sumbool_of_bool (ad_eq root a0)). Intro H6. Left . Rewrite (ad_eq_complete ? ? H6). + Reflexivity. + Intro H6. Rewrite H6 in H1. Right . Exact H1. + Intro H4. Rewrite H4 in H1. + Rewrite (MapPut_semantics ? cg root (MapPut D edges a Dz) a0) in H1. + Elim (sumbool_of_bool (ad_eq root a0)). Intro H5. Left . Rewrite (ad_eq_complete ? ? H5). + Reflexivity. + Intro H5. Rewrite H5 in H1. Right . Exact H1. + Intro H2. Rewrite H2 in H1. Rewrite (MapPut_semantics ? cg root (M1 D a Dz) a0) in H1. + Elim (sumbool_of_bool (ad_eq root a0)). Intro H3. Left . Rewrite (ad_eq_complete ? ? H3). + Reflexivity. + Intro H3. Rewrite H3 in H1. Right . Exact H1. + Qed. + +Lemma CG_edge_dist_some_1 : (n:nat) (cg:CGraph1) (x,y:ad) (d:D) (prefix:(list ad)) + (CG_edge cg x y)=(SOME D d) -> (ad_in_list y prefix)=false -> + {d':D | (Ddle (ad_simple_path_dist_1 cg x y prefix (S n)) (SOME ? d'))=true}. + Proof. + Unfold CG_edge. Intros. Simpl. Elim (sumbool_of_bool (ad_eq x y)). Intro H1. Rewrite H1. + Split with Dz. Simpl. Apply Dle_refl. + Intro H1. Rewrite H1. Elim (option_sum ? (MapGet ? cg x)). Intro H2. Elim H2. + Intros edges H3. Rewrite H3 in H. Rewrite H3. Elim (option_sum ? (MapGet D edges y)). + Intro H4. Elim H4. Intros d0 H5. Rewrite H5 in H. Inversion H. Split with (Dplus Dz d). + Rewrite H7 in H5. Apply Ddle_trans with dd':=([z:ad] [d0:D] + Case (orb (ad_eq z x) (ad_in_list z prefix)) of + (NONE D) + (Ddplus + (ad_simple_path_dist_1 cg z y (cons x prefix) n) d0) + end y d). + Apply all_min_le_1 with f:=[z:ad] [d0:D] + Case (orb (ad_eq z x) (ad_in_list z prefix)) of + (NONE D) + (Ddplus (ad_simple_path_dist_1 cg z y (cons x prefix) n) + d0) + end. + Assumption. + Rewrite (ad_eq_comm y x). Rewrite H1. Rewrite H0. Simpl. Case n. Simpl. + Rewrite (ad_eq_correct y). Apply Ddle_refl. + Intro. Simpl. Rewrite (ad_eq_correct y). Apply Ddle_refl. + Intro H4. Rewrite H4 in H. Discriminate H. + Intro H2. Rewrite H2 in H. Discriminate H. + Qed. + +Lemma CG_edge_dist_some : (cg:CGraph1) (x,y:ad) (d:D) + (CG_edge cg x y)=(SOME D d) -> {d':D | (ad_simple_path_dist cg x y)=(SOME ? d')}. + Proof. + Intros. Elim (option_sum ? (ad_simple_path_dist cg x y)). Trivial. + Unfold ad_simple_path_dist. Intro H0. Elim (option_sum ? (MapGet ? cg x)). Intro H1. Elim H1. + Intros edges H2. Elim (MapCard_is_not_O ? cg x edges H2). Intros n H3. + Elim (CG_edge_dist_some_1 n cg x y d (nil ad) H (refl_equal ? ?)). Intros d0 H4. + Rewrite H3 in H0. Rewrite H0 in H4. Discriminate H4. + Intro H1. Unfold CG_edge in H. Rewrite H1 in H. Discriminate H. + Qed. + +Lemma CG_add_root_rooted : (cg:CGraph1) (root:ad) + ((x:ad) (d:D) (l:(list ad)) (CG_path cg x d (cons x l)) -> (Dle Dz d)=true) -> + (in_dom ? root cg)=false -> + (a:ad) (in_dom ? a (CG_add_root root cg (ad_list_of_dom ? cg)))=true -> + (CG_leq (CG_add_root root cg (ad_list_of_dom ? cg)) root a)=true. + Proof. + Intros. Elim (CG_add_root_rooted_4 ? ? ? ? H1). Intro H2. Rewrite H2. Apply CG_leq_refl. + Intro H2. Elim (CG_edge_dist_some ? root a Dz (CG_add_root_rooted_3 cg root H0 a H2)). + Intros d H3. Unfold CG_leq. Rewrite H3. Reflexivity. + Qed. + +Lemma CG_add_sat : (cg:CGraph1) (root,a:ad) (d:D) (rho:ad->D) + (CGsat (cg2 cg root a d) rho) -> (CGsat cg rho). + Proof. + Unfold CGsat. Intros. Elim (sumbool_of_bool (andb (ad_eq root x) (ad_eq a y))). Intro H1. + Apply Dle_trans with d':=(Dplus (rho y) (Dmin d d0)). Apply H. Rewrite CG_add_edge_1. + Rewrite H1. Rewrite H0. Reflexivity. + Apply Dle_plus_mono. Apply Dle_refl. + Apply Dmin_le_2. + Intro H1. Apply H. Rewrite CG_add_edge_1. Rewrite H1. Assumption. + Qed. + +Lemma CG_add_root_sat : (l:(list ad)) (cg:CGraph1) (root:ad) (rho:ad->D) + (CGsat (CG_add_root root cg l) rho) -> (CGsat cg rho). + Proof. + Induction l. Trivial. + Simpl. Intros. Apply (CG_add_sat cg root a Dz rho). Unfold cg2. Exact (H ? ? ? H0). + Qed. + +Lemma CG_add_root_consistent : (l:(list ad)) (cg:CGraph1) (root:ad) + (CGconsistent (CG_add_root root cg l)) -> (CGconsistent cg). + Proof. + Unfold CGconsistent. Intros. Elim H. Intros rho H0. Split with rho. + Exact (CG_add_root_sat l cg root rho H0). + Qed. + +Lemma CG_circuit_complete_1 : (cg:CGraph1) + ((x:ad)(d:D)(l:(list ad)) + (CG_path cg x d (cons x l)) -> (Dle Dz d)=true) -> + (root:ad) + root=(ad_alloc_opt unit (FSetUnion (MapDom ? cg) (MapDom ? (cg_range cg)))) -> + (cg':CGraph1) cg'=(CG_add_root root cg (ad_list_of_dom ? cg)) + -> (CGconsistent cg). + Proof. + Intros. Apply (CG_add_root_consistent (ad_list_of_dom (Map D) cg) cg root). Rewrite <- H1. + Cut (orb (in_dom ? root cg) (in_dom ? root (cg_range cg)))=false. Intro H2. + Elim (orb_false_elim ? ? H2). Intros. Elim CG_rooted_sat with cg:=cg' root:=root d0:=Dz. + Intros rho H5. Elim H5. Unfold CGconsistent. Intros H6 H7. Split with rho. Assumption. + Rewrite H1. Intros. + Apply CG_add_root_out_of_range with l:=(ad_list_of_dom (Map D) cg) cg:=cg root:=root + x0:=x d0:=d l0:=l. + Assumption. + Apply MapSubset_2_imp. Unfold MapSubset_2. + Apply eqmap_trans with m':=(MapDomRestrBy unit unit (MapDom (Map D) cg) (MapDom (Map D) cg)). + Apply MapDomRestrBy_ext. Apply Elems_of_list_of_dom. + Apply eqmap_refl. + Apply MapDomRestrBy_m_m_1. + Rewrite ad_in_list_of_dom_in_dom. Assumption. + Assumption. + Assumption. + Intros. Rewrite H1. Apply CG_add_root_rooted. Assumption. + Assumption. + Rewrite <- H1. Assumption. + Rewrite MapDom_Dom. Rewrite MapDom_Dom. Rewrite <- in_FSet_union. Rewrite H0. + Unfold in_FSet. Apply ad_alloc_opt_allocates. + Qed. + +(*s If there is no circuit [(cons x l)] with negative weight [d], then [cg] is consistent: *) + +Theorem CG_circuit_complete : (cg:CGraph1) + ((x:ad) (d:D) (l:(list ad)) (CG_path cg x d (cons x l)) -> (Dle Dz d)=true) -> + (CGconsistent cg). + Proof. + Intros. EApply CG_circuit_complete_1. Assumption. + Reflexivity. + Reflexivity. + Qed. + +Lemma CG_translate_l : (cg:CGraph1) (rho:ad->D) (d:D) (CGsat cg rho) -> + (CGsat cg [a:ad] (Dplus d (rho a))). + Proof. + Unfold CGsat. Intros. Rewrite Dplus_assoc. Apply Dle_plus_mono. Apply Dle_refl. + Apply H. Assumption. + Qed. + +(*s [(CGconsistent_anchored cg a d)] if there exists a valuation $\rho$ which + satisfies [cg] and such that $\rho(a)=d$ +*) + +Definition CGconsistent_anchored := + [cg:CGraph1][a:ad][d0:D] {rho:ad->D | (CGsat cg rho) /\ (rho a)=d0}. + +Lemma CGconsistent_then_anchored + : (cg:CGraph1) (CGconsistent cg) -> + (a:ad) (d0:D) (CGconsistent_anchored cg a d0). + Proof. + Unfold CGconsistent CGconsistent_anchored. Intros. Elim H. Intros rho H0. + Split with [a0:ad](Dplus (Dplus d0 (Dneg (rho a))) (rho a0)). Split. + Apply CG_translate_l. Assumption. + Rewrite Dplus_assoc. Rewrite Dplus_neg_2. Apply Dplus_d_z. + Qed. + +Lemma CGanchored_then_consistent : (cg:CGraph1) (a:ad) (d0:D) (CGconsistent_anchored cg a d0) -> + (CGconsistent cg). + Proof. + Unfold CGconsistent CGconsistent_anchored. Intros. Elim H. Intros rho H0. Elim H0. Intros. + Split with rho. Assumption. + Qed. + +(*s Definition of [ad_0_path_dist_1] + a more efficient version of [ad_simple_path_dist]: *) + +Section CGDist1. + + Variable cg : CGraph1. + +Fixpoint ad_0_path_dist_1 [x,y:ad; l:(list ad); n:nat] : (option D) := + if (ad_eq x y) + then (SOME ? Dz) + else + Cases n of + O => (NONE ?) + | (S n') => Cases (MapGet ? cg x) of + NONE => (NONE ?) + | (SOME edges) => + if (ad_in_list x l) + then (NONE D) + else let l'=(cons x l) in (* builds reverse path *) + (all_min [z:ad][d:D] + if (ad_in_list z l') + then (NONE D) + else (Ddplus (ad_0_path_dist_1 z y l' n') d) + edges) + end + end. + +Definition ad_0_path_dist := [x,y:ad] + (ad_0_path_dist_1 x y (nil ad) (MapCard ? cg)). + +Lemma ad_0_path_dist_1_ge : (n:nat) (l:(list ad)) (x,y:ad) + (Ddle (ad_simple_path_dist_1 cg x y l n) (ad_0_path_dist_1 x y l n))=true. + Proof. + Induction n. Simpl. Intros. Apply Ddle_refl. + Simpl. Intros. Case (ad_eq x y). Apply Ddle_refl. + Case (MapGet ? cg x). Apply Ddle_refl. + Intro. Case (ad_in_list x l). Apply Ddle_d_none. + Apply all_min_le_3. Intros. Case (orb (ad_eq a x) (ad_in_list a l)). Apply Ddle_refl. + Apply Ddle_plus_mono. Apply H. + Apply Dle_refl. + Qed. + +Lemma ad_0_path_dist_1_correct_1 : + ((x:ad) (d:D) (l:(list ad)) (CG_path cg x d (cons x l)) -> (Dle Dz d)=true) -> + (n:nat) (x,y:ad) (l:(list ad)) (d:D) + (le (length l) n) -> (CG_path cg y d (cons x l)) -> + (prefix:(list ad)) + (ad_list_stutters (app (rev prefix) (cons x l)))=false -> + (Ddle (ad_0_path_dist_1 x y prefix n) (SOME ? d))=true. + Proof. + Induction n. Intros x y l. Case l. Intros. Simpl. + Inversion H1. Rewrite H5. + Rewrite (ad_eq_correct y). Apply Ddle_refl. + Intros. Elim (le_Sn_O ? H0). + Intros n0 H0 x y l. Case l. Intros. Inversion H2. + Rewrite H6. Simpl. + Rewrite (ad_eq_correct y). Rewrite H5. Apply Ddle_refl. + Intros. Simpl. Elim (sumbool_of_bool (ad_eq x y)). Intro H4. Rewrite H4. + Rewrite (ad_eq_complete ? ? H4) in H2. Exact (H ? ? ? H2). + + Intro H4. Rewrite H4. Elim (option_sum ? (MapGet ? cg x)). Intro H5. Elim H5. + Intros edges H6. Rewrite H6. Inversion_clear H2. Apply Ddle_trans + with dd':=Case (ad_in_list a (cons x prefix)) of + (NONE D) + (Ddplus (ad_0_path_dist_1 a y (cons x prefix) n0) d') + end. + Cut (MapGet ? edges a)=(SOME ? d'). Intro. Cut (ad_in_list x prefix)=false. Intro H9. + Rewrite H9. Exact (all_min_le_1 [z:ad] [d:D] + Case (orb (ad_eq z x) (ad_in_list z prefix)) of + (NONE D) + (Ddplus (ad_0_path_dist_1 z y (cons x prefix) n0) d) + end edges a d' H2). + Rewrite <- ad_in_list_rev. Exact (ad_list_stutters_prev_conv_l ? ? ? H3). + Unfold CG_edge in H8. Rewrite H6 in H8. Elim (option_sum ? (MapGet D edges a)). + Intro H9. Elim H9. Intros d1 H10. Rewrite H10 in H8. Rewrite H10. Assumption. + Intro H9. Rewrite H9 in H8. Discriminate H8. + Rewrite (ad_list_app_rev prefix (cons a l0) x) in H3. + Rewrite <- (ad_in_list_rev (cons x prefix) a). + Rewrite (ad_list_stutters_prev_conv_l ? ? ? H3). + Apply (Ddle_plus_mono (ad_0_path_dist_1 a y (cons x prefix) n0) (SOME D d0) d' d'). + Exact (H0 a y l0 d0 (le_S_n ? ? H1) H7 (cons x prefix) H3). + Apply Dle_refl. + Intro H5. Inversion H2. + Unfold CG_edge in H11. Rewrite H5 in H11. Discriminate H11. + Qed. + +Lemma ad_0_path_dist_1_le : + ((x:ad) (d:D) (l:(list ad)) (CG_path cg x d (cons x l)) -> (Dle Dz d)=true) -> + (n:nat) (x,y:ad) + (Ddle (ad_0_path_dist_1 x y (nil ad) n) (ad_simple_path_dist_1 cg x y (nil ad) n))=true. + Proof. + Intros. Elim (option_sum ? (ad_simple_path_dist_1 cg x y (nil ad) n)). Intro H0. Elim H0. + Intros d H1. Rewrite H1. + Elim (ad_simple_path_dist_1_complete_1 cg n x y (nil ad) Dz) with d0:=d. Intros l H2. + Elim H2. Intros H3 H4. Apply (ad_0_path_dist_1_correct_1 H n x y l). Exact (proj2 ? ? H4). + Rewrite (Dplus_d_z d) in H3. Exact H3. + Exact (proj1 ? ? H4). + Simpl. Apply CG_p1. Reflexivity. + Reflexivity. + Assumption. + Intro H0. Rewrite H0. Apply Ddle_d_none. + Qed. + +Lemma ad_0_path_dist_correct_1 : + (CGconsistent cg) -> + (x,y:ad) (n:nat) + (ad_0_path_dist_1 x y (nil ad) n)=(ad_simple_path_dist_1 cg x y (nil ad) n). + Proof. + Intros. Apply Ddle_antisym. Apply ad_0_path_dist_1_le. + Exact (CG_circuits_non_negative_weight cg H). + Apply ad_0_path_dist_1_ge. + Qed. + +Lemma ad_0_path_dist_correct : (CGconsistent cg) -> + (x,y:ad) (ad_0_path_dist x y)=(ad_simple_path_dist cg x y). + Proof. + Intros. Exact (ad_0_path_dist_correct_1 H x y (MapCard ? cg)). + Qed. + +(*s Uses a set [s] of already visited nodes *) + +Fixpoint ad_1_path_dist_1 [x,y:ad; s:FSet; n:nat] : (option D) := + if (ad_eq x y) + then (SOME ? Dz) + else + Cases n of + O => (NONE ?) + | (S n') => Cases (MapGet ? cg x) of + NONE => (NONE ?) + | (SOME edges) => + Cases (MapGet ? s x) of + (SOME _) => (NONE ?) + | NONE => let s'=(MapPut unit s x tt) in + (all_min [z:ad][d:D] + Cases (MapGet ? s' z) of + (SOME _) => (NONE D) + | NONE => (Ddplus (ad_1_path_dist_1 z y s' n') d) + end + edges) + end + end + end. + +Definition ad_1_path_dist := [x,y:ad] + (ad_1_path_dist_1 x y (M0 unit) (MapCard ? cg)). + +Lemma ad_1_path_dist_correct_1 : (n:nat) (x,y:ad) (l:(list ad)) + (ad_1_path_dist_1 x y (Elems l) n)=(ad_0_path_dist_1 x y l n). + Proof. + Induction n. Trivial. + Simpl. Intros. Case (ad_eq x y). Reflexivity. + Case (MapGet ? cg x). Reflexivity. + Intro. Unfold all_min. Elim (sumbool_of_bool (ad_in_list x l)). Intro H0. Rewrite H0. + Rewrite <- (ad_in_elems_in_list l x) in H0. Elim (in_dom_some ? ? ? H0). Intros t H1. + Rewrite H1. Reflexivity. + Intro H0. Rewrite H0. Rewrite <- (ad_in_elems_in_list l x) in H0. + Rewrite (in_dom_none ? ? ? H0). Apply MapFold_ext_f. Intros. + Elim (sumbool_of_bool (ad_in_list a (cons x l))). Intro H2. + Rewrite <- (ad_in_elems_in_list (cons x l) a) in H2. Elim (in_dom_some ? ? ? H2). Simpl. + Intro t. Elim t. Intro H3. Rewrite H3. Rewrite (ad_in_elems_in_list (cons x l) a) in H2. + Simpl in H2. Rewrite H2. Reflexivity. + Intro H2. Cut (orb (ad_eq a x) (ad_in_list a l))=false. Intro H3. Rewrite H3. + Rewrite <- (ad_in_elems_in_list (cons x l) a) in H2. Simpl in H2. + Rewrite (in_dom_none ? ? ? H2). Rewrite <- (H a y (cons x l)). Reflexivity. + Assumption. + Qed. + +Lemma ad_1_path_dist_correct_2 : (x,y:ad) (ad_1_path_dist x y)=(ad_0_path_dist x y). + Proof. + Intros. Exact (ad_1_path_dist_correct_1 (MapCard ? cg) x y (nil ad)). + Qed. + +Lemma ad_1_path_dist_correct_3 : (CGconsistent cg) -> + (n:nat) (x,y:ad) + (ad_1_path_dist_1 x y (M0 unit) n)=(ad_simple_path_dist_1 cg x y (nil ad) n). + Proof. + Intros. Rewrite <- (ad_0_path_dist_correct_1 H x y n). + Exact (ad_1_path_dist_correct_1 n x y (nil ad)). + Qed. + +Lemma ad_1_path_dist_correct : (CGconsistent cg) -> + (x,y:ad) (ad_1_path_dist x y)=(ad_simple_path_dist cg x y). + Proof. + Intros. Rewrite ad_1_path_dist_correct_2. Apply ad_0_path_dist_correct. Assumption. + Qed. + +Lemma ad_1_path_dist_big_enough_1 : (n:nat) (s:FSet) + (MapSubset ? ? s (MapDom ? cg)) -> + (le (MapCard ? cg) (plus n (MapCard ? s))) -> + (x,y:ad) (ad_1_path_dist_1 x y s n)=(ad_1_path_dist_1 x y s (S n)). + Proof. + Induction n. Intros. Simpl. Case (ad_eq x y). Reflexivity. + Elim (sumbool_of_bool (in_dom ? x cg)). Intro H1. Elim (in_dom_some ? ? ? H1). + Intros edges H2. Rewrite H2. Elim (sumbool_of_bool (in_dom ? x s)). Intro H3. + Elim (in_dom_some ? ? ? H3). Intros t H4. Rewrite H4. Reflexivity. + Intro H3. Simpl in H0. Rewrite (MapCard_Dom ? cg) in H0. Rewrite (MapDom_Dom ? s x) in H3. + Cut (MapGet ? (MapDom unit s) x)=(NONE ?). Rewrite (MapSubset_card_eq ? ? ? ? H H0 x). + Rewrite (FSet_Dom (MapDom ? cg)). + Elim (in_dom_some ? ? ? (MapDom_semantics_1 ? cg x edges H2)). Intros t H4 H5. + Rewrite H4 in H5. Discriminate H5. + Exact (in_dom_none ? ? ? H3). + Intro H1. Rewrite (in_dom_none ? ? ? H1). Reflexivity. + Intros. Cut (m:nat) m=(S n0)->(ad_1_path_dist_1 x y s (S n0))=(ad_1_path_dist_1 x y s (S m)). + Intro. Exact (H2 (S n0) (refl_equal ? ?)). + Intros. Simpl. Case (ad_eq x y). Reflexivity. + Elim (option_sum ? (MapGet ? cg x)). Intro H'. Elim H'. Intros edges H'0. Rewrite H'0. + Elim (option_sum ? (MapGet ? s x)). Intro H3. Elim H3. Intros t H4. Rewrite H4. Reflexivity. + Intro H3. Rewrite H3. Unfold all_min. Apply MapFold_ext_f. Intros. + Rewrite (MapPut_semantics unit s x tt a). Elim (sumbool_of_bool (ad_eq x a)). Intro H5. + Rewrite H5. Reflexivity. + Intro H5. Rewrite H5. Case (MapGet ? s a). Rewrite H2. Rewrite H. Reflexivity. + Unfold MapSubset. Intros. Elim (in_dom_some ? ? ? H6). Intro. + Rewrite (MapPut_semantics unit s x tt a0). Elim (sumbool_of_bool (ad_eq x a0)). Intro H7. + Rewrite H7. Intro H8. Rewrite <- (ad_eq_complete ? ? H7). Fold (in_FSet x (MapDom ? cg)). + Rewrite <- (MapDom_Dom ? cg x). Unfold in_dom. Rewrite H'0. Reflexivity. + Intro H7. Rewrite H7. Intro H8. Apply (H0 a0). Unfold in_dom. Rewrite H8. Reflexivity. + Rewrite MapCard_Put_2_conv. Rewrite <- plus_Snm_nSm. Exact H1. + Assumption. + Trivial. + Intro H3. Rewrite H3. Reflexivity. + Qed. + +Lemma ad_1_path_dist_big_enough_2 : (n:nat) + (x,y:ad) (ad_1_path_dist x y)=(ad_1_path_dist_1 x y (M0 unit) (plus n (MapCard ? cg))). + Proof. + Induction n. Trivial. + Intros. Unfold plus. Fold (plus n0 (MapCard ? cg)). Rewrite <- ad_1_path_dist_big_enough_1. + Apply H. + Unfold MapSubset. Intros. Discriminate H0. + Simpl. Rewrite <- plus_n_O. Apply le_plus_r. + Qed. + +Lemma ad_1_path_dist_big_enough : (n:nat) (le (MapCard ? cg) n) -> + (x,y:ad) (ad_1_path_dist x y)=(ad_1_path_dist_1 x y (M0 unit) n). + Proof. + Intros. Cut (EX m:nat | n=(plus m (MapCard ? cg))). Intro H0. Elim H0. Intros m H1. + Rewrite H1. Apply ad_1_path_dist_big_enough_2. + Elim H. Split with O. Reflexivity. + Intros. Elim H1. Intros m' H2. Split with (S m'). Rewrite H2. Reflexivity. + Qed. + +End CGDist1. + +(*s Definition of concrete formulas : + [(CGleq x y d)] means $x\leq y+d$, [(CGeq x y d)] means $x=y+d$ + *) + +Inductive CGForm : Set := + CGleq : ad -> ad -> D -> CGForm + | CGeq : ad -> ad -> D -> CGForm + | CGand : CGForm -> CGForm -> CGForm + | CGor : CGForm -> CGForm -> CGForm + | CGimp : CGForm -> CGForm -> CGForm + | CGnot : CGForm -> CGForm. + +(*s Interpretation of concrete formulas as proposition *) + +Fixpoint CGeval [rho:ad->D; f:CGForm] : Prop := + Cases f of + (CGleq x y d) => (Dle (rho x) (Dplus (rho y) d))=true + | (CGeq x y d) => (rho x)=(Dplus (rho y) d) + | (CGand f0 f1) => (CGeval rho f0) /\ (CGeval rho f1) + | (CGor f0 f1) => (CGeval rho f0) \/ (CGeval rho f1) + | (CGimp f0 f1) => (CGeval rho f0) -> (CGeval rho f1) + | (CGnot f0) => ~(CGeval rho f0) + end. + +(*s Decidability of satisfaction *) + +Lemma CGeval_dec : (f:CGForm) (rho:ad->D) {(CGeval rho f)}+{~(CGeval rho f)}. + Proof. + Induction f. + Intros. Simpl. Elim (sumbool_of_bool (Dle (rho a) (Dplus (rho a0) d))). + Intro H. Left . Assumption. + Intro H. Right . Unfold not. Rewrite H. Intro H0. Discriminate H0. + Simpl. Intros. Apply D_dec. + Simpl. Intros. Elim (H rho). Intro H1. Elim (H0 rho). Intro H2. Left . (Split; Assumption). + Unfold not. Intro H2. Right . Intro. Elim H3. Intro. Assumption. + Unfold not. Intro H1. Right . Intro H2. Elim H2. Intros. Apply (H1 H3). + Simpl. Intros. Elim (H rho). Intro H1. Left . Left . Assumption. + Elim (H0 rho). Intros H1 H2. Left . Right . Assumption. + Unfold not. Intros H1 H2. Right . Intro H3. (Elim H3; Assumption). + Simpl. Intros. Elim (H0 rho). Intro H1. Left . Intro H2. Assumption. + Elim (H rho). Unfold not. Intros H1 H2. Right . Intro H3. Apply H2. Apply H3. Assumption. + Unfold not. Intros H1 H2. Left . Intro H3. Elim (H1 H3). + Intros. Simpl. Elim (H rho). Intro H0. Right . Unfold not. Intros. Exact (H1 H0). + Intro H0. Left . Assumption. + Qed. + +(*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 := + Cases fs of + (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] : bool := + Cases gas of + O => def_answer + | (S gas') => + Cases fsl of + nil => true + | (cons fs fsl') => + Cases fs of + (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 (cons fs0 (cons fs1 fsl')) gas') + | (CGSor fs0 fs1) => if (CGS_solve_1 cg n (cons fs0 fsl') gas') + then true + else (CGS_solve_1 cg n (cons fs1 fsl') gas') + end + end + end. + +(*s Size of a set of formula and of a list of formula *) + +Fixpoint FSize [f:CGSForm] : nat := + Cases f of + (CGSand f0 f1) => (S (plus (FSize f0) (FSize f1))) + | (CGSor f0 f1) => (S (plus (FSize f0) (FSize f1))) + | _ => (1) + end. + +Fixpoint FlSize [fsl:(list CGSForm)] : nat := + Cases fsl of + nil => O + | (cons fs fsl') => (plus (FSize fs) (FlSize fsl')) + end. + + +Definition CGS_solve := [fs:CGSForm] (CGS_solve_1 (M0 ?) O (cons fs (nil ?)) (S (FSize fs))). + +(*s Interpretation of a list of formula as a conjonction *) + +Fixpoint CGSeval_l [rho:ad->D; fsl:(list CGSForm)] : Prop := + Cases fsl of + nil => True + | (cons fs fsl') => (CGSeval rho fs) /\ (CGSeval_l rho fsl') + end. + +Lemma FSize_geq_1 : (fs:CGSForm) {n:nat | (FSize fs)=(S n)}. + Proof. + Induction fs. Simpl. Intros. Split with O. Reflexivity. + Intros. Simpl. Split with (plus (FSize c) (FSize c0)). Reflexivity. + Intros. Simpl. Split with (plus (FSize c) (FSize c0)). Reflexivity. + Qed. + +Lemma FlSize_is_O : (fsl:(list CGSForm)) (FlSize fsl)=O -> fsl=(nil ?). + Proof. + Induction fsl. Trivial. + Intros. Simpl in H0. Elim (FSize_geq_1 a). Intros n H1. Rewrite H1 in H0. Discriminate H0. + Qed. + +Lemma CG_add_card_le : (cg:CGraph1) (x,y:ad) (d:D) (n:nat) + (le (MapCard ? cg) n) -> (le (MapCard ? (CG_add cg x y d)) (S n)). + Proof. + Intros. Unfold CG_add. Case (MapGet ? cg x). + Apply (le_trans ? ? (S n) (MapCard_Put_ub ? cg x (M1 D y d))). Apply le_n_S. Assumption. + Intro. Case (MapGet ? m y). + Apply (le_trans ? ? (S n) (MapCard_Put_ub ? cg x (MapPut D m y d))). Apply le_n_S. + Assumption. + Intro. Apply (le_trans ? ? (S n) (MapCard_Put_ub ? cg x (MapPut D m y (Dmin d d0)))). + Apply le_n_S. Assumption. + Qed. + +Lemma CGS_solve_1_correct : (gas:nat) (fsl:(list CGSForm)) (cg:CGraph1) (n:nat) + (CGconsistent cg) -> + (le (MapCard ? cg) n) -> + (lt (FlSize fsl) gas) -> + (CGS_solve_1 cg n fsl gas)=true -> + {rho:ad->D | (CGSeval_l rho fsl) /\ (CGsat cg rho)}. + Proof. + Induction gas. Intros. Elim (lt_n_O ? H1). + Simpl. Intros n H fsl. Case fsl. Intros. Elim H0. Intros rho H4. Split with rho. + Split. Exact I. + Assumption. + Intro fs. Case fs. Intros. Elim (sumbool_of_bool (CG_test_ineq cg n0 a a0 d)). Intro H4. + Rewrite H4 in H3. Unfold CG_test_ineq in H4. Elim (H l (CG_add cg a a0 d) (S n0)). + Intros rho H5. Split with rho. Elim H5. Intros. Split. Simpl. Split. Unfold CGSeval. + Simpl. Exact (CG_add_3 cg a a0 d rho H7). + Assumption. + Exact (CG_add_2 cg a a0 d rho H7). + Apply CG_circuit_complete. + Rewrite <- (ad_1_path_dist_big_enough cg n0 H1 a0 a) in H4. + Rewrite (ad_1_path_dist_correct cg H0 a0 a) in H4. + Exact (CG_add_5 cg a a0 d (CG_circuits_non_negative_weight cg H0) H4). + Apply CG_add_card_le. Assumption. + Exact (lt_S_n ? ? H2). + Assumption. + Intro H4. Rewrite H4 in H3. Discriminate H3. + Intros. Elim (H (cons c (cons c0 l)) cg n0 H0). Simpl. Intros rho H4. Split with rho. + Elim H4. Intros. Split; Try Assumption. Elim H5. Intros. Elim H8. Intros. + Split; Try Assumption. Exact (conj ? ? H7 H9). + Assumption. + Simpl. Simpl in H2. Rewrite plus_assoc_l. Apply lt_S_n. Assumption. + Assumption. + Intros. Elim (sumbool_of_bool (CGS_solve_1 cg n0 (cons c l) n)). Intro H4. + Elim (H (cons c l) cg n0 H0 H1). Intros rho H5. Split with rho. Elim H5. Intros. Simpl. + Split; Try Assumption. Split; Try Assumption. Unfold CGSeval. Simpl. Left . Simpl in H6. + Exact (proj1 ? ? H6). + Exact (proj2 ? ? H6). + Simpl. Simpl in H2. Apply le_lt_trans with m:=(plus (plus (FSize c) (FSize c0)) (FlSize l)). + Apply le_reg_r. Apply le_plus_l. + Apply lt_S_n. Assumption. + Assumption. + Intro H4. Rewrite H4 in H3. Elim (H (cons c0 l) cg n0 H0). Intros rho H5. Elim H5. + Intros. Split with rho. Split; Try Assumption. Simpl. Simpl in H6. Elim H6. Intros. + Split; Try Assumption. Unfold CGSeval. Simpl. Right . Assumption. + Assumption. + Simpl. Simpl in H2. Apply le_lt_trans with m:=(plus (plus (FSize c) (FSize c0)) (FlSize l)). + Apply le_reg_r. Apply le_plus_r. + Apply lt_S_n. Assumption. + Assumption. + Qed. + +Lemma CGS_solve_correct : (fs:CGSForm) (CGS_solve fs)=true -> + {rho:ad->D | (CGSeval rho fs)}. + Proof. + Intros. Elim (CGS_solve_1_correct (S (FSize fs)) (cons fs (nil ?)) (M0 ?) O). Intros rho H0. + Simpl in H0. Elim H0. Intros. Elim H1. Intros. Split with rho. Assumption. + Split with [x:ad]Dz. Unfold CGsat. Unfold CG_edge. Simpl. Intros. Discriminate H0. + Apply le_n. + Simpl. Rewrite <- plus_n_O. Unfold lt. Apply le_n. + Exact H. + Qed. + +Lemma CGS_translate_l : (fs:CGSForm) (rho:ad->D) (d:D) (CGSeval rho fs) -> + (CGSeval [a:ad] (Dplus d (rho a)) fs). + Proof. + Induction fs. Unfold CGSeval. Simpl. Intros. Rewrite Dplus_assoc. Apply Dle_plus_mono. + Apply Dle_refl. + Assumption. + Unfold CGSeval. Simpl. Intros. Elim H1. Intros. Split. Apply H. Assumption. + Apply H0. Assumption. + Unfold CGSeval. Simpl. Intros. Elim H1. Intro. Left . Apply H. Assumption. + Intro. Right . Apply H0. Assumption. + Qed. + +Lemma CGS_solve_correct_anchored : (fs:CGSForm) (CGS_solve fs)=true -> + {rho:ad->D | (CGSeval rho fs) /\ (rho anchor)=anchor_value}. + Proof. + Intros. Elim (CGS_solve_correct fs H). Intros rho H0. + Split with [a:ad](Dplus (Dplus anchor_value (Dneg (rho anchor))) (rho a)). Split. + Apply CGS_translate_l. Assumption. + Rewrite Dplus_assoc. Rewrite Dplus_neg_2. Apply Dplus_d_z. + Qed. + +Lemma CGS_solve_complete_1 : (gas:nat) (fsl:(list CGSForm)) (cg:CGraph1) (n:nat) + (lt (FlSize fsl) gas) -> (le (MapCard ? cg) n) -> + (rho:ad->D) (CGsat cg rho) -> (CGSeval_l rho fsl) -> (CGS_solve_1 cg n fsl gas)=true. + Proof. + Induction gas. Intros. Elim (lt_n_O ? H). + Intros n H fsl. Case fsl. Trivial. + Intro fs. Case fs. Simpl. Intros. Unfold CG_test_ineq. + Rewrite <- (ad_1_path_dist_big_enough cg n0 H1 a0 a). Cut (CGconsistent cg). Intro H4. + Rewrite (ad_1_path_dist_correct cg H4 a0 a). Elim H3. Intros. + Rewrite (CG_sat_add_1 cg a a0 d rho H2 H5). Apply H with rho:=rho. Apply lt_S_n. Assumption. + Apply CG_add_card_le. Assumption. + Fold (cg2 cg a a0 d). Apply CG_add_1. Assumption. + Exact H5. + Assumption. + Split with rho. Assumption. + Simpl. Intros. Apply H with rho:=rho. Simpl. Rewrite plus_assoc_l. Apply lt_S_n. Assumption. + Assumption. + Assumption. + Elim H3. Intros. Simpl. Elim H4. Intros. Split; Try Assumption. Split; Assumption. + Simpl. Intros. Elim H3. Intros. Elim H4. Intro. Cut (CGS_solve_1 cg n0 (cons c l) n)=true. + Intro H7. Rewrite H7. Reflexivity. + Apply H with rho:=rho. Simpl. + Apply le_lt_trans with m:=(plus (plus (FSize c) (FSize c0)) (FlSize l)). Apply le_reg_r. + Apply le_plus_l. + Apply lt_S_n. Assumption. + Assumption. + Assumption. + Split; Assumption. + Intro H6. Cut (CGS_solve_1 cg n0 (cons c0 l) n)=true. Intro H7. + Case (CGS_solve_1 cg n0 (cons c l) n); Trivial. + Apply H with rho:=rho. Simpl. + Apply le_lt_trans with m:=(plus (plus (FSize c) (FSize c0)) (FlSize l)). Apply le_reg_r. + Apply le_plus_r. + Apply lt_S_n. Assumption. + Assumption. + Assumption. + Split; Assumption. + Qed. + +Lemma CGS_solve_complete : (fs:CGSForm) (rho:ad->D) + (CGSeval rho fs) -> (CGS_solve fs)=true. + Proof. + Intros. Apply (CGS_solve_complete_1 (S (FSize fs)) (cons fs (nil ?)) (M0 ?) O) with rho:=rho. + Simpl. Rewrite <- plus_n_O. Unfold lt. Apply le_n. + Apply le_n. + Unfold CGsat. Intros. Unfold CG_edge in H0. Discriminate H0. + Simpl. Split; Trivial. + Qed. + +Definition CGSeq := [x,y:ad] [d:D] (CGSand (CGSleq x y d) (CGSleq y x (Dneg d))). + +Lemma CGSeq_correct : (x,y:ad) (d:D) (rho:ad->D) + (CGSeval rho (CGSeq x y d)) -> (rho x)=(Dplus (rho y) d). + Proof. + Intros. Unfold CGSeq CGSeval in H. Simpl in H. Elim H. Intros. Apply Dle_antisym. Assumption. + Apply Dplus_reg_r with d'':=(Dneg d). Rewrite Dplus_assoc. Rewrite Dplus_neg. + Rewrite Dplus_d_z. Assumption. + Qed. + +Lemma CGSeq_complete : (x,y:ad) (d:D) (rho:ad->D) + (rho x)=(Dplus (rho y) d) -> (CGSeval rho (CGSeq x y d)). + Proof. + Intros. Unfold CGSeq CGSeval. Simpl. Rewrite H. Split. Apply Dle_refl. + Rewrite Dplus_assoc. Rewrite Dplus_neg. Rewrite Dplus_d_z. Apply Dle_refl. + Qed. + +End CGSSolve. + +Section CGWithOne. + + Variable Done : D. + Variable Done_pos : (Dle Done Dz)=false. + Variable Done_min_pos : (d:D) (Dle d Dz)=false -> (Dle Done d)=true. + +(*s Defining the negation of a formula : + $\neg x \leq y+d \Leftrightarrow x>y+d \Leftrightarrow x \geq y+d+1$ + *) +Fixpoint CGSnot [fs:CGSForm] : CGSForm := + Cases fs of + (CGSleq x y d) => (CGSleq y x (Dneg (Dplus d Done))) + + | (CGSand f0 f1) => (CGSor (CGSnot f0) (CGSnot f1)) + | (CGSor f0 f1) => (CGSand (CGSnot f0) (CGSnot f1)) + end. + +Lemma Dmone_neg : (Dle Dz (Dneg Done))=false. + Proof. + Elim (sumbool_of_bool (Dle Dz (Dneg Done))). Intro H. + Rewrite <- (Dneg_neg Done) in Done_pos. + Rewrite (Dle_neg ? H) in Done_pos. Discriminate Done_pos. + Trivial. + Qed. + +Lemma Dminus_one_1 : (d:D) (Dle d (Dplus d (Dneg Done)))=false. + Proof. + Intro. Elim (sumbool_of_bool (Dle d (Dplus d (Dneg Done)))). Intro H. + Cut (Dle Dz (Dneg Done))=true. Intro. Rewrite Dmone_neg in H0. Discriminate H0. + Apply Dplus_reg_l with d'':=d. Rewrite Dplus_d_z. Assumption. + Trivial. + Qed. + +Lemma Dle_lt_1 : (d,d':D) (Dle d' d)=false -> (Dle d (Dplus d' (Dneg Done)))=true. + Proof. + Intros. Apply Dplus_reg_r with d'':=Done. Rewrite Dplus_assoc. Rewrite Dplus_neg_2. + Rewrite Dplus_d_z. Apply Dplus_reg_l with d'':=(Dneg d). Rewrite <- Dplus_assoc. + Rewrite Dplus_neg_2. Rewrite Dplus_z_d. Apply Done_min_pos. + Elim (sumbool_of_bool (Dle (Dplus (Dneg d) d') Dz)). Intro H0. Cut (Dle d' d)=true. + Rewrite H. Intro. Discriminate H1. + Apply Dplus_reg_l with d'':=(Dneg d). Rewrite Dplus_neg_2. Assumption. + Trivial. + Qed. + +Lemma Dle_lt_2 : (d,d':D) (Dle d (Dplus d' (Dneg Done)))=true -> (Dle d' d)=false. + Proof. + Intros. Elim (sumbool_of_bool (Dle d' d)). Intro H0. Cut (Dle d (Dplus d (Dneg Done)))=true. + Rewrite Dminus_one_1. Intro. Discriminate H1. + Apply Dle_trans with d':=(Dplus d' (Dneg Done)). Assumption. + Apply Dle_plus_mono. Assumption. + Apply Dle_refl. + Trivial. + Qed. + +Lemma CGSnot_correct : (fs:CGSForm) (rho:ad->D) (CGSeval rho fs) -> ~(CGSeval rho (CGSnot fs)). + Proof. + Unfold not. Induction fs. Simpl. Unfold CGSeval. Simpl. Intros. + Cut (Dle (rho a) (Dplus (rho a) (Dneg Done)))=true. Rewrite Dminus_one_1. Intro. + Discriminate H1. + Rewrite <- (Dplus_d_z (Dneg Done)). Rewrite <- (Dplus_neg_2 d). + Rewrite <- (Dplus_assoc (Dneg Done)). Rewrite <- Dneg_plus. + Apply Dle_trans with d':=(Dplus (rho a0) d). Assumption. + Rewrite <- Dplus_assoc. Apply Dle_plus_mono. Assumption. + Apply Dle_refl. + Unfold CGSeval. Simpl. Intros. Elim H1. Intros. Elim H2. Intro. Exact (H rho H3 H5). + Intro. Exact (H0 rho H4 H5). + Unfold CGSeval. Simpl. Intros. Elim H2. Intros. Elim H1. Intro. Exact (H rho H5 H3). + Intro. Exact (H0 rho H5 H4). + Qed. + +Lemma CGSnot_complete : (fs:CGSForm) (rho:ad->D) + ~(CGSeval rho (CGSnot fs)) -> (CGSeval rho fs). + Proof. + Unfold not CGSeval. Induction fs. Simpl. Intros. + Elim (sumbool_of_bool (Dle (rho a) (Dplus (rho a0) d))). Trivial. + Intro H0. Cut False. Intro. Elim H1. + Apply H. Rewrite Dneg_plus. Rewrite <- Dplus_assoc. Apply Dplus_reg_r with d'':=d. + Rewrite Dplus_assoc. Rewrite Dplus_neg_2. Rewrite Dplus_d_z. Apply Dle_lt_1. Assumption. + Simpl. Intros. Split. Apply H. Intro. Apply H1. Left . Assumption. + Apply H0. Intro. Apply H1. Right . Assumption. + Simpl. Intros. + Cut ~(CGeval rho (CG_of_CGS (CGSnot c))) \/ ~(CGeval rho (CG_of_CGS (CGSnot c0))). Intro. + Elim H2. Intro. Left . Apply H. Assumption. + Intro. Right . Apply H0. Assumption. + Elim (CGeval_dec (CG_of_CGS (CGSnot c)) rho). Intro H2. + Elim (CGeval_dec (CG_of_CGS (CGSnot c0)) rho). Intro H3. Elim (H1 (conj ? ? H2 H3)). + Intro H3. Right . Assumption. + Intro H2. Left . Assumption. + Qed. + +(*s Interpreting formula as simplified formula *) + +Fixpoint CGFormSimplify [f:CGForm] : CGSForm := + Cases f of + (CGleq x y d) => (CGSleq x y d) + | (CGeq x y d) => (CGSeq x y d) + | (CGand f0 f1) => (CGSand (CGFormSimplify f0) (CGFormSimplify f1)) + | (CGor f0 f1) => (CGSor (CGFormSimplify f0) (CGFormSimplify f1)) + | (CGimp f0 f1) => (CGSor (CGSnot (CGFormSimplify f0)) (CGFormSimplify f1)) + | (CGnot f0) => (CGSnot (CGFormSimplify f0)) + end. + +Lemma CGFormSimplify_correct : (f:CGForm) (rho:ad->D) + (CGeval rho f) <-> (CGSeval rho (CGFormSimplify f)). + Proof. + Induction f. Intros. Split; Trivial. + Intros. Unfold CGSeval. Simpl. Split. Intro H. Exact (CGSeq_complete a a0 d rho H). + Exact (CGSeq_correct a a0 d rho). + Simpl. Intros. Unfold CGSeval. Simpl. Elim (H rho). Intros. Elim (H0 rho). Intros. + Split. Intro. Elim H5. Intros. Split. Apply H1. Assumption. + Apply H3. Assumption. + Intro. Elim H5. Intros. Split. Apply H2. Assumption. + Apply H4. Assumption. + Simpl. Intros. Unfold CGSeval. Elim (H rho). Intros. Elim (H0 rho). Intros. Simpl. Split. + Intro. Elim H5. Intro. Left . Apply H1. Assumption. + Intro. Right . Apply H3. Assumption. + Intro. Elim H5. Intro. Left . Apply H2. Assumption. + Intro. Right . Apply H4. Assumption. + Simpl. Intros. Unfold CGSeval. Simpl. Elim (H rho). Intros. Elim (H0 rho). Intros. Split. + Intro. Elim (CGeval_dec c rho). Intro H6. Right . Apply H3. Apply H5. Assumption. + Intro H6. Left . Elim (CGeval_dec (CG_of_CGS (CGSnot (CGFormSimplify c))) rho). Trivial. + Intro H7. Elim (H6 (H2 (CGSnot_complete ? ? H7))). + Intro. Elim H5. Intros. Elim (CGeval_dec (CG_of_CGS (CGFormSimplify c)) rho). Intro H8. + Elim (CGSnot_correct ? ? H8 H6). + Intro H8. Elim (H8 (H1 H7)). + Intros. Apply H4. Assumption. Simpl. Intros. Unfold CGSeval. Simpl. Elim (H rho). Intros. + Split. Intro. Elim (CGeval_dec (CG_of_CGS (CGSnot (CGFormSimplify c))) rho). Trivial. + Intro H3. Elim (H2 (H1 (CGSnot_complete ? ? H3))). + Unfold not. Intros. Elim (CGSnot_correct ? ? (H0 H3) H2). + Qed. + +(*s Formula are solved by looking at their simplified form *) + +Definition CG_solve := [f:CGForm] (CGS_solve false (CGFormSimplify f)). + +Theorem CG_solve_correct : (f:CGForm) (CG_solve f)=true -> {rho:ad->D | (CGeval rho f)}. + Proof. + Intros. Elim (CGS_solve_correct ? ? H). Intros rho H0. Split with rho. + Apply (proj2 ? ? (CGFormSimplify_correct f rho)). Assumption. + Qed. + +Theorem CG_solve_correct_anchored : (anchor:ad) (anchor_value:D) + (f:CGForm) (CG_solve f)=true -> + {rho:ad->D | (CGeval rho f) /\ (rho anchor)=anchor_value}. + Proof. + Intros. Elim (CGS_solve_correct_anchored anchor anchor_value ? ? H). Intros rho H0. + Split with rho. Elim H0. Intros. Split. Apply (proj2 ? ? (CGFormSimplify_correct f rho)). + Assumption. + Assumption. + Qed. + +Theorem CG_solve_complete : (f:CGForm) (rho:ad->D) + (CGeval rho f) -> (CG_solve f)=true. + Proof. + Intros. Unfold CG_solve. Apply (CGS_solve_complete false) with rho:=rho. + Apply (proj1 ? ? (CGFormSimplify_correct f rho)). Assumption. + Qed. + +(*s A formula is proved when its negation cannot be satisfied *) + +Definition CG_prove := [f:CGForm] (negb (CG_solve (CGnot f))). + +Theorem CG_prove_correct : (f:CGForm) (CG_prove f)=true -> (rho:ad->D) (CGeval rho f). + Proof. + Unfold CG_prove CG_solve. Simpl. Intros. Apply (proj2 ? ? (CGFormSimplify_correct f rho)). + Apply CGSnot_complete. Unfold not. Intro. Rewrite (CGS_solve_complete false ? ? H0) in H. + Discriminate H. + Qed. + +Theorem CG_prove_complete : (f:CGForm) ((rho:ad->D) (CGeval rho f)) -> (CG_prove f)=true. + Proof. + Unfold CG_prove CG_solve. Simpl. Intros. + Elim (sumbool_of_bool (CGS_solve false (CGSnot (CGFormSimplify f)))). Intro H0. + Elim (CGS_solve_correct false ? H0). Intros rho H1. + Elim (CGSnot_correct ? ? (proj1 ? ? (CGFormSimplify_correct ? ?) (H rho)) H1). + Intro H0. Rewrite H0. Reflexivity. + Qed. + +Theorem CG_prove_complete_anchored : (f:CGForm) (anchor:ad) (anchor_value:D) + ((rho:ad->D) (rho anchor)=anchor_value -> (CGeval rho f)) -> (CG_prove f)=true. + Proof. + Unfold CG_prove CG_solve. Simpl. Intros. + Elim (sumbool_of_bool (CGS_solve false (CGSnot (CGFormSimplify f)))). Intro H0. + Elim (CGS_solve_correct_anchored anchor anchor_value false ? H0). Intros rho H1. + Elim H1. Intros. + Elim (CGSnot_correct ? ? (proj1 ? ? (CGFormSimplify_correct f rho) (H rho H3)) H2). + Intro H0. Rewrite H0. Reflexivity. + Qed. + + End CGWithOne. + +End ConstraintGraphs. diff --git a/contrib/graphs/zcgraph.v b/contrib/graphs/zcgraph.v new file mode 100644 index 000000000..64d1f9555 --- /dev/null +++ b/contrib/graphs/zcgraph.v @@ -0,0 +1,417 @@ + +(*s The decision procedure is instantiated for Z *) + +Require cgraph. +Require ZArith. +Require Addr. +Require Addec. + +Inductive ZCGForm : Set := + ZCGle : ad -> ad -> ZCGForm (* x<=y *) + | ZCGge : ad -> ad -> ZCGForm (* x>=y *) + | ZCGlt : ad -> ad -> ZCGForm (* x<y *) + | ZCGgt : ad -> ad -> ZCGForm (* x>y *) + | ZCGlep : ad -> ad -> Z -> ZCGForm (* x<=y+k *) + | ZCGgep : ad -> ad -> Z -> ZCGForm (* x>=y+k *) + | ZCGltp : ad -> ad -> Z -> ZCGForm (* x<y+k *) + | ZCGgtp : ad -> ad -> Z -> ZCGForm (* x>y+k *) + | ZCGlem : ad -> ad -> Z -> ZCGForm (* x+k<=y *) + | ZCGgem : ad -> ad -> Z -> ZCGForm (* x+k>=y *) + | ZCGltm : ad -> ad -> Z -> ZCGForm (* x+k<y *) + | ZCGgtm : ad -> ad -> Z -> ZCGForm (* x+k>y *) + | ZCGlepm : ad -> ad -> Z -> Z -> ZCGForm (* x+k<=y+k' *) + | ZCGgepm : ad -> ad -> Z -> Z -> ZCGForm (* x+k>=y+k' *) + | ZCGltpm : ad -> ad -> Z -> Z -> ZCGForm (* x+k<y+k' *) + | ZCGgtpm : ad -> ad -> Z -> Z -> ZCGForm (* x+k>y+k' *) + | ZCGeq : ad -> ad -> ZCGForm (* x=y *) + | ZCGeqp : ad -> ad -> Z -> ZCGForm (* x=y+k *) + | ZCGeqm : ad -> ad -> Z -> ZCGForm (* x+k=y *) + | ZCGeqpm : ad -> ad -> Z -> Z -> ZCGForm (* x+k=y+k' *) + | ZCGzylem : ad -> Z -> ZCGForm (* k<=y *) + | ZCGzygem : ad -> Z -> ZCGForm (* k>=y *) + | ZCGzyltm : ad -> Z -> ZCGForm (* k<y *) + | ZCGzygtm : ad -> Z -> ZCGForm (* k>y *) + | ZCGzylepm : ad -> Z -> Z -> ZCGForm (* k<=y+k' *) + | ZCGzygepm : ad -> Z -> Z -> ZCGForm (* k>=y+k' *) + | ZCGzyltpm : ad -> Z -> Z -> ZCGForm (* k<y+k' *) + | ZCGzygtpm : ad -> Z -> Z -> ZCGForm (* k>y+k' *) + | ZCGzyeqm : ad -> Z -> ZCGForm (* k=y *) + | ZCGzyeqpm : ad -> Z -> Z -> ZCGForm (* k=y+k' *) + | ZCGxzlep : ad -> Z -> ZCGForm (* x<=k *) + | ZCGxzgep : ad -> Z -> ZCGForm (* x>=k *) + | ZCGxzltp : ad -> Z -> ZCGForm (* x<k *) + | ZCGxzgtp : ad -> Z -> ZCGForm (* x>k *) + | ZCGxzlepm : ad -> Z -> Z -> ZCGForm (* x+k<=k' *) + | ZCGxzgepm : ad -> Z -> Z -> ZCGForm (* x+k>=k' *) + | ZCGxzltpm : ad -> Z -> Z -> ZCGForm (* x+k<k' *) + | ZCGxzgtpm : ad -> Z -> Z -> ZCGForm (* x+k>k' *) + | ZCGxzeqp : ad -> Z -> ZCGForm (* x=k *) + | ZCGxzeqpm : ad -> Z -> Z -> ZCGForm (* x+k=k' *) + | ZCGzzlep : Z -> Z -> ZCGForm (* k<=k' *) + | ZCGzzltp : Z -> Z -> ZCGForm (* k<k' *) + | ZCGzzgep : Z -> Z -> ZCGForm (* k>=k' *) + | ZCGzzgtp : Z -> Z -> ZCGForm (* k>k' *) + | ZCGzzeq : Z -> Z -> ZCGForm (* k=k' *) + | ZCGand : ZCGForm -> ZCGForm -> ZCGForm + | ZCGor : ZCGForm -> ZCGForm -> ZCGForm + | ZCGimp : ZCGForm -> ZCGForm -> ZCGForm + | ZCGnot : ZCGForm -> ZCGForm + | ZCGiff : ZCGForm -> ZCGForm -> ZCGForm. + +Definition ZCG_eval := (CGeval Z Zplus Zle_bool). + +(*s Translation of formula on Z into a constraint graph formula. + we reserve [ad_z] as the "zero" variable, + i.e., the one that is anchored at the value `0`. *) + +Fixpoint ZCGtranslate [f:ZCGForm] : (CGForm Z) := + Cases f of + (ZCGle x y) => (CGleq Z x y `0`) + | (ZCGge x y) => (CGleq Z y x `0`) + | (ZCGlt x y) => (CGleq Z x y `-1`) + | (ZCGgt x y) => (CGleq Z y x `-1`) + | (ZCGlep x y k) => (CGleq Z x y k) + | (ZCGgep x y k) => (CGleq Z y x (Zopp k)) + | (ZCGltp x y k) => (CGleq Z x y `k-1`) + | (ZCGgtp x y k) => (CGleq Z y x (Zopp `k+1`)) + | (ZCGlem x y k) => (CGleq Z x y (Zopp k)) + | (ZCGgem x y k) => (CGleq Z y x k) + | (ZCGltm x y k) => (CGleq Z x y (Zopp `k+1`)) + | (ZCGgtm x y k) => (CGleq Z y x `k-1`) + | (ZCGlepm x y k k') => (CGleq Z x y `k'-k`) + | (ZCGgepm x y k k') => (CGleq Z y x `k-k'`) + | (ZCGltpm x y k k') => (CGleq Z x y `k'-k-1`) + | (ZCGgtpm x y k k') => (CGleq Z y x `k-k'-1`) + | (ZCGeq x y) => (CGeq Z x y `0`) + | (ZCGeqp x y k) => (CGeq Z x y k) + | (ZCGeqm x y k) => (CGeq Z y x k) + | (ZCGeqpm x y k k') => (CGeq Z x y `k'-k`) + | (ZCGzylem y k) => (CGleq Z ad_z y (Zopp k)) + | (ZCGzygem y k) => (CGleq Z y ad_z k) + | (ZCGzyltm y k) => (CGleq Z ad_z y (Zopp `k+1`)) + | (ZCGzygtm y k) => (CGleq Z y ad_z `k-1`) + | (ZCGzylepm y k k') => (CGleq Z ad_z y `k'-k`) + | (ZCGzygepm y k k') => (CGleq Z y ad_z `k-k'`) + | (ZCGzyltpm y k k') => (CGleq Z ad_z y `k'-k-1`) + | (ZCGzygtpm y k k') => (CGleq Z y ad_z `k-k'-1`) + | (ZCGzyeqm y k) => (CGeq Z y ad_z k) + | (ZCGzyeqpm y k k') => (CGeq Z y ad_z `k-k'`) + | (ZCGxzlep x k) => (CGleq Z x ad_z k) + | (ZCGxzgep x k) => (CGleq Z ad_z x (Zopp k)) + | (ZCGxzltp x k) => (CGleq Z x ad_z `k-1`) + | (ZCGxzgtp x k) => (CGleq Z ad_z x (Zopp `k+1`)) + | (ZCGxzlepm x k k') => (CGleq Z x ad_z `k'-k`) + | (ZCGxzgepm x k k') => (CGleq Z ad_z x `k-k'`) + | (ZCGxzltpm x k k') => (CGleq Z x ad_z `k'-k-1`) + | (ZCGxzgtpm x k k') => (CGleq Z ad_z x `k-k'-1`) + | (ZCGxzeqp x k) => (CGeq Z x ad_z k) + | (ZCGxzeqpm x k k') => (CGeq Z x ad_z `k'-k`) + | (ZCGzzlep k k') => (CGleq Z ad_z ad_z `k'-k`) + | (ZCGzzltp k k') => (CGleq Z ad_z ad_z `k'-k-1`) + | (ZCGzzgep k k') => (CGleq Z ad_z ad_z `k-k'`) + | (ZCGzzgtp k k') => (CGleq Z ad_z ad_z `k-k'-1`) + | (ZCGzzeq k k') => (CGeq Z ad_z ad_z `k-k'`) + | (ZCGand f0 f1) => (CGand Z (ZCGtranslate f0) (ZCGtranslate f1)) + | (ZCGor f0 f1) => (CGor Z (ZCGtranslate f0) (ZCGtranslate f1)) + | (ZCGimp f0 f1) => (CGimp Z (ZCGtranslate f0) (ZCGtranslate f1)) + | (ZCGnot f0) => (CGnot Z (ZCGtranslate f0)) + | (ZCGiff f0 f1) => (CGand Z (CGimp Z (ZCGtranslate f0) (ZCGtranslate f1)) + (CGimp Z (ZCGtranslate f1) (ZCGtranslate f0))) + end. + +Section ZCGevalDef. + + Variable rho : ad -> Z. + +Fixpoint ZCGeval [f:ZCGForm] : Prop := + Cases f of + (ZCGle x y) => `(rho x)<=(rho y)` + | (ZCGge x y) => `(rho x)>=(rho y)` + | (ZCGlt x y) => `(rho x)<(rho y)` + | (ZCGgt x y) => `(rho x)>(rho y)` + | (ZCGlep x y k) => `(rho x)<=(rho y)+k` + | (ZCGgep x y k) => `(rho x)>=(rho y)+k` + | (ZCGltp x y k) => `(rho x)<(rho y)+k` + | (ZCGgtp x y k) => `(rho x)>(rho y)+k` + | (ZCGlem x y k) => `(rho x)+k<=(rho y)` + | (ZCGgem x y k) => `(rho x)+k>=(rho y)` + | (ZCGltm x y k) => `(rho x)+k<(rho y)` + | (ZCGgtm x y k) => `(rho x)+k>(rho y)` + | (ZCGlepm x y k k') => `(rho x)+k<=(rho y)+k'` + | (ZCGgepm x y k k') => `(rho x)+k>=(rho y)+k'` + | (ZCGltpm x y k k') => `(rho x)+k<(rho y)+k'` + | (ZCGgtpm x y k k') => `(rho x)+k>(rho y)+k'` + | (ZCGeq x y) => `(rho x)=(rho y)` + | (ZCGeqp x y k) => `(rho x)=(rho y)+k` + | (ZCGeqm x y k) => `(rho x)+k=(rho y)` + | (ZCGeqpm x y k k') => `(rho x)+k=(rho y)+k'` + | (ZCGzylem y k) => `k<=(rho y)` + | (ZCGzygem y k) => `k>=(rho y)` + | (ZCGzyltm y k) => `k<(rho y)` + | (ZCGzygtm y k) => `k>(rho y)` + | (ZCGzylepm y k k') => `k<=(rho y)+k'` + | (ZCGzygepm y k k') => `k>=(rho y)+k'` + | (ZCGzyltpm y k k') => `k<(rho y)+k'` + | (ZCGzygtpm y k k') => `k>(rho y)+k'` + | (ZCGzyeqm y k) => `k=(rho y)` + | (ZCGzyeqpm y k k') => `k=(rho y)+k'` + | (ZCGxzlep x k) => `(rho x)<=k` + | (ZCGxzgep x k) => `(rho x)>=k` + | (ZCGxzltp x k) => `(rho x)<k` + | (ZCGxzgtp x k) => `(rho x)>k` + | (ZCGxzlepm x k k') => `(rho x)+k<=k'` + | (ZCGxzgepm x k k') => `(rho x)+k>=k'` + | (ZCGxzltpm x k k') => `(rho x)+k<k'` + | (ZCGxzgtpm x k k') => `(rho x)+k>k'` + | (ZCGxzeqp x k) => `(rho x)=k` + | (ZCGxzeqpm x k k') => `(rho x)+k=k'` + | (ZCGzzlep k k') => `k<=k'` + | (ZCGzzltp k k') => `k<k'` + | (ZCGzzgep k k') => `k>=k'` + | (ZCGzzgtp k k') => `k>k'` + | (ZCGzzeq k k') => `k=k'` + | (ZCGand f0 f1) => (ZCGeval f0) /\ (ZCGeval f1) + | (ZCGor f0 f1) => (ZCGeval f0) \/ (ZCGeval f1) + | (ZCGimp f0 f1) => (ZCGeval f0) -> (ZCGeval f1) + | (ZCGnot f0) => ~(ZCGeval f0) + | (ZCGiff f0 f1) => (ZCGeval f0) <-> (ZCGeval f1) + end. + + Variable Zrho_zero : (rho ad_z)=ZERO. + +Lemma ZCGeval_correct + : (f:ZCGForm) (ZCGeval f) <-> (ZCG_eval rho (ZCGtranslate f)). + Proof. + Induction f; Simpl. Intros. Rewrite Zero_right. Apply Zle_is_le_bool. + Intros. Rewrite Zero_right. Apply Zge_is_le_bool. + Intros. Exact (Zlt_is_le_bool (rho a) (rho a0)). + Intros. Exact (Zgt_is_le_bool (rho a) (rho a0)). + Intros. Apply Zle_is_le_bool. + Intros. Apply iff_trans with b:=`(rho a0)+z <= (rho a)`. Apply Zge_iff_le. + Apply iff_trans with b:=`(rho a0) <= (rho a)-z`. Apply Zle_plus_swap. + Unfold Zminus. Apply Zle_is_le_bool. + Intros. Apply iff_trans with b:=(Zle_bool (rho a) `(rho a0)+z-1`)=true. Apply Zlt_is_le_bool. + Unfold 1 Zminus. Rewrite Zplus_assoc_r. Split; Intro; Assumption. + Intros. Apply iff_trans with b:=`(rho a0)+z < (rho a)`. Apply Zgt_iff_lt. + Apply iff_trans with `(rho a0) < (rho a)-z`. Apply Zlt_plus_swap. + Rewrite Zopp_Zplus. Rewrite Zplus_assoc_l. Exact (Zlt_is_le_bool (rho a0) `(rho a)-z`). + Intros. Apply iff_trans with b:=`(rho a) <= (rho a0)-z`. Apply Zle_plus_swap. + Unfold Zminus. Apply Zle_is_le_bool. + Intros. Apply Zge_is_le_bool. + Intros. Apply iff_trans with b:=`(rho a) < (rho a0)-z`. Apply Zlt_plus_swap. + Rewrite Zopp_Zplus. Rewrite Zplus_assoc_l. Exact (Zlt_is_le_bool (rho a) `(rho a0)-z`). + Intros. Unfold Zminus. Rewrite Zplus_assoc_l. Exact (Zgt_is_le_bool `(rho a)+z` (rho a0)). + Intros. Apply iff_trans with b:=`(rho a) <= (rho a0)+z0-z`. Apply Zle_plus_swap. + Unfold 1 Zminus. Rewrite Zplus_assoc_r. Unfold Zminus. Apply Zle_is_le_bool. + Intros. Apply iff_trans with b:=`(rho a0)+z0 <= (rho a)+z`. Apply Zge_iff_le. + Apply iff_trans with b:=`(rho a0) <= (rho a)+z-z0`. Apply Zle_plus_swap. + Unfold 1 Zminus. Rewrite Zplus_assoc_r. Unfold Zminus. Apply Zle_is_le_bool. + Intros. Apply iff_trans with b:=`(rho a) < (rho a0)+z0-z`. Apply Zlt_plus_swap. + Unfold 2 Zminus. Rewrite Zplus_assoc_l. Unfold 1 Zminus. Rewrite Zplus_assoc_r. + Exact (Zlt_is_le_bool (rho a) `(rho a0)+(z0+ -z)`). + Intros. Apply iff_trans with b:=`(rho a0)+z0 < (rho a)+z`. Apply Zgt_iff_lt. + Apply iff_trans with b:=`(rho a0) < (rho a)+z-z0`. Apply Zlt_plus_swap. + Unfold 2 Zminus. Rewrite Zplus_assoc_l. Unfold 1 Zminus. Rewrite Zplus_assoc_r. + Exact (Zlt_is_le_bool (rho a0) `(rho a)+(z+ -z0)`). + Intros. Rewrite Zero_right. Split; Intro; Assumption. + Split; Intro; Assumption. + Split; Intro; Apply sym_eq; Assumption. + Intros. Unfold Zminus. Rewrite Zplus_assoc_l. Exact (Zeq_plus_swap (rho a) `(rho a0)+z0` z). + Rewrite Zrho_zero. Intros. Apply iff_trans with b:=`0+z <= (rho a)`. Rewrite Zero_left. + Split; Intro; Assumption. + Apply iff_trans with b:=`0 <= (rho a)-z`. Apply Zle_plus_swap. + Unfold Zminus. Apply Zle_is_le_bool. + Rewrite Zrho_zero. Intros. Rewrite Zero_left. Apply Zge_is_le_bool. + Rewrite Zrho_zero. Intros. Apply iff_trans with b:=`0+z < (rho a)`. Rewrite Zero_left. + Split; Intro; Assumption. + Apply iff_trans with b:=`0 < (rho a)-z`. Apply Zlt_plus_swap. + Rewrite Zopp_Zplus. Rewrite Zplus_assoc_l. Exact (Zlt_is_le_bool `0` `(rho a)-z`). + Rewrite Zrho_zero. Intros. Rewrite Zero_left. Apply Zgt_is_le_bool. + Rewrite Zrho_zero. Intros. Apply iff_trans with b:=`0+z <= (rho a)+z0`. Rewrite Zero_left. + Split; Intro; Assumption. + Apply iff_trans with b:=`0 <= (rho a)+z0-z`. Apply Zle_plus_swap. + Unfold 2 Zminus. Rewrite Zplus_assoc_l. Exact (Zle_is_le_bool `0` `(rho a)+z0-z`). + Rewrite Zrho_zero. Intros. Rewrite Zero_left. Apply iff_trans with b:=`(rho a)+z0 <= z`. + Apply Zge_iff_le. + Apply iff_trans with b:=`(rho a) <= z-z0`. Apply Zle_plus_swap. + Apply Zle_is_le_bool. + Rewrite Zrho_zero. Intros. Apply iff_trans with `0+z < (rho a)+z0`. Rewrite Zero_left. + Split; Intro; Assumption. + Apply iff_trans with b:=`0 < (rho a)+z0-z`. Apply Zlt_plus_swap. + Unfold 2 Zminus. Rewrite Zplus_assoc_l. Unfold Zminus. Rewrite Zplus_assoc_l. + Exact (Zlt_is_le_bool `0` `(rho a)+z0+ -z`). + Rewrite Zrho_zero. Intros. Rewrite Zero_left. Apply iff_trans with b:=`(rho a)+z0 < z`. + Apply Zgt_iff_lt. + Apply iff_trans with b:=`(rho a) < z-z0`. Apply Zlt_plus_swap. + Apply Zlt_is_le_bool. + Rewrite Zrho_zero. Intros. Rewrite Zero_left. Split; Intro; Apply sym_eq; Assumption. + Rewrite Zrho_zero. Intros. Rewrite Zero_left. Apply iff_trans with `(rho a)+z0 = z`. + Split; Intro; Apply sym_eq; Assumption. + Apply Zeq_plus_swap. + Rewrite Zrho_zero. Intros. Rewrite Zero_left. Apply Zle_is_le_bool. + Rewrite Zrho_zero. Intros. Apply iff_trans with b:=`0+z <= (rho a)`. Rewrite Zero_left. + Apply Zge_iff_le. + Apply iff_trans with b:=`0 <= (rho a)-z`. Apply Zle_plus_swap. + Exact (Zle_is_le_bool `0` `(rho a)-z`). + Rewrite Zrho_zero. Intros. Rewrite Zero_left. Apply Zlt_is_le_bool. + Rewrite Zrho_zero. Intros. Apply iff_trans with b:=`0+z < (rho a)`. Rewrite Zero_left. + Apply Zgt_iff_lt. + Apply iff_trans with b:=`0 < (rho a)-z`. Apply Zlt_plus_swap. + Rewrite Zopp_Zplus. Rewrite Zplus_assoc_l. Exact (Zlt_is_le_bool `0` `(rho a)-z`). + Rewrite Zrho_zero. Intros. Rewrite Zero_left. Apply iff_trans with b:=`(rho a) <= z0-z`. + Apply Zle_plus_swap. + Apply Zle_is_le_bool. + Rewrite Zrho_zero. Intros. Apply iff_trans with b:=`0+z0 <= (rho a)+z`. Rewrite Zero_left. + Apply Zge_iff_le. + Apply iff_trans with b:=`0 <= (rho a)+z-z0`. Apply Zle_plus_swap. + Unfold 2 Zminus. Rewrite Zplus_assoc_l. Exact (Zle_is_le_bool `0` `(rho a)+z-z0`). + Rewrite Zrho_zero. Intros. Rewrite Zero_left. Apply iff_trans with b:=`(rho a) < z0-z`. + Apply Zlt_plus_swap. + Apply Zlt_is_le_bool. + Rewrite Zrho_zero. Intros. Apply iff_trans with b:=`0+z0 < (rho a)+z`. Rewrite Zero_left. + Apply Zgt_iff_lt. + Apply iff_trans with b:=`0 < (rho a)+z-z0`. Apply Zlt_plus_swap. + Unfold 2 Zminus. Rewrite Zplus_assoc_l. Unfold Zminus. Rewrite Zplus_assoc_l. + Exact (Zlt_is_le_bool `0` `(rho a)+z+ -z0`). + Rewrite Zrho_zero. Intros. Rewrite Zero_left. Split; Intro; Assumption. + Rewrite Zrho_zero. Intros. Rewrite Zero_left. Apply Zeq_plus_swap. + Rewrite Zrho_zero. Intros. Rewrite Zero_left. Apply iff_trans with b:=`0+z <= z0`. + Rewrite Zero_left. Split; Intro; Assumption. + Apply iff_trans with b:=`0 <= z0-z`. Apply Zle_plus_swap. + Apply Zle_is_le_bool. + Rewrite Zrho_zero. Intros. Rewrite Zero_left. Apply iff_trans with b:=`0+z < z0`. + Rewrite Zero_left. Split; Intro; Assumption. + Apply iff_trans with b:=`0 < z0-z`. Apply Zlt_plus_swap. + Apply Zlt_is_le_bool. + Rewrite Zrho_zero. Intros. Rewrite Zero_left. Apply iff_trans with b:=`0+z0 <= z`. + Rewrite Zero_left. Apply Zge_iff_le. + Apply iff_trans with b:=`0 <= z-z0`. Apply Zle_plus_swap. + Apply Zle_is_le_bool. + Rewrite Zrho_zero. Intros. Rewrite Zero_left. Apply iff_trans with b:=`0+z0 < z`. + Rewrite Zero_left. Apply Zgt_iff_lt. + Apply iff_trans with b:=`0 < z-z0`. Apply Zlt_plus_swap. + Apply Zlt_is_le_bool. + Rewrite Zrho_zero. Intros. Rewrite Zero_left. Split. Intro. Rewrite H. Apply Zminus_n_n. + Intro. Rewrite <- (Zero_left z0). Rewrite H. Unfold Zminus. Rewrite Zplus_assoc_r. + Rewrite Zplus_inverse_l. Rewrite Zero_right. Reflexivity. + Intros. Elim H. Intros. Elim H0. Intros. Split. Intro. Elim H5. Intros. Split. Apply H1. + Assumption. + Apply H3. Assumption. + Intro. Elim H5. Intros. Split. Apply H2. Assumption. + Apply H4. Assumption. + Intros. Elim H. Intros. Elim H0. Intros. Split. Intro. Elim H5. Intro. Left . Apply H1. + Assumption. + Intro. Right . Apply H3. Assumption. + Intro. Elim H5. Intro. Left . Apply H2. Assumption. + Intro. Right . Apply H4. Assumption. + Intros. Elim H. Intros. Elim H0. Intros. Split. Intros. Apply H3. Apply H5. Apply H2. + Assumption. + Intros. Apply H4. Apply H5. Apply H1. Assumption. + Unfold not. Intros. Elim H. Intros. Split. Intros. Apply H2. Apply H1. Assumption. + Intros. Apply H2. Apply H0. Assumption. + Intros. Fold (ZCG_eval rho (ZCGtranslate z))<->(ZCG_eval rho (ZCGtranslate z0)). Split. + Intro. Apply iff_trans with b:=(ZCGeval z). Apply iff_sym. Assumption. + Apply iff_trans with b:=(ZCGeval z0). Assumption. + Assumption. + Intro. Apply iff_trans with b:=(ZCG_eval rho (ZCGtranslate z)). Assumption. + Apply iff_trans with b:=(ZCG_eval rho (ZCGtranslate z0)). Assumption. + Apply iff_sym. Assumption. + Qed. + +End ZCGevalDef. + +Definition ZCG_solve + := [f:ZCGForm] (CG_solve Z ZERO Zplus Zopp Zle_bool `1` (ZCGtranslate f)). + +Theorem ZCG_solve_correct : + (f:ZCGForm) (ZCG_solve f)=true -> + {rho:ad->Z | (ZCGeval rho f) /\ (rho ad_z)=`0`}. +Proof. + Intros. + Elim (CG_solve_correct_anchored Z ZERO Zplus Zopp Zle_bool Zero_right + Zero_left Zplus_assoc_r Zplus_inverse_r Zle_bool_refl + Zle_bool_antisym Zle_bool_trans Zle_bool_total + Zle_bool_plus_mono `1` Zone_pos Zone_min_pos ad_z `0` ? H). + Intros rho H0. Split with rho. Elim H0. Intros. Split. + Apply (proj2 ? ? (ZCGeval_correct rho H2 f)). Assumption. + Assumption. +Qed. + +Theorem ZCG_solve_complete + : (f:ZCGForm) (rho:ad->Z) + (ZCGeval rho f) -> (rho ad_z)=`0` -> (ZCG_solve f)=true. +Proof. + Intros. Unfold ZCG_solve. + Apply (CG_solve_complete Z ZERO Zplus Zopp Zle_bool Zero_right + Zero_left Zplus_assoc_r Zplus_inverse_r Zle_bool_refl + Zle_bool_antisym Zle_bool_trans Zle_bool_total + Zle_bool_plus_mono `1` Zone_pos Zone_min_pos (ZCGtranslate f) + rho). + Apply (proj1 ? ? (ZCGeval_correct rho H0 f)). Assumption. +Qed. + +Definition ZCG_prove + := [f:ZCGForm] (CG_prove Z ZERO Zplus Zopp Zle_bool `1` (ZCGtranslate f)). + +Theorem ZCG_prove_correct + : (f:ZCGForm) (ZCG_prove f)=true -> + (rho:ad->Z) (rho ad_z)=`0` -> (ZCGeval rho f). +Proof. + Intros. Apply (proj2 ? ? (ZCGeval_correct rho H0 f)). + Exact (CG_prove_correct Z ZERO Zplus Zopp Zle_bool Zero_right Zero_left + Zplus_assoc_r Zplus_inverse_r Zle_bool_refl Zle_bool_antisym + Zle_bool_trans Zle_bool_total Zle_bool_plus_mono `1` Zone_pos + Zone_min_pos ? H rho). +Qed. + +Theorem ZCG_prove_complete + : (f:ZCGForm) + ((rho:ad->Z) (rho ad_z)=`0` -> (ZCGeval rho f)) -> (ZCG_prove f)=true. +Proof. + Intros. Unfold ZCG_prove. + Apply (CG_prove_complete_anchored Z ZERO Zplus Zopp Zle_bool Zero_right + Zero_left Zplus_assoc_r Zplus_inverse_r Zle_bool_refl + Zle_bool_antisym Zle_bool_trans Zle_bool_total + Zle_bool_plus_mono `1` Zone_pos Zone_min_pos (ZCGtranslate f) + ad_z `0`). + Intros. Exact (proj1 ? ? (ZCGeval_correct rho H0 f) (H rho H0)). +Qed. + +(*i Tests: + + Definition v := [n:Z] Cases n of + (POS p) => (ad_x p) + | _ => ad_z + end. + + Lemma test1 : (x,y:Z) `x<=y` -> `x<=y+1`. + Proof. + Intros. + Cut (rho:ad->Z) (rho ad_z)=`0` -> + (ZCGeval rho (ZCGimp (ZCGle (v`1`) (v`2`)) (ZCGlep (v`1`) (v`2`) `1`))). + Intro. + Exact (H0 [a:ad]Case (ad_eq a (v`1`)) of x + Case (ad_eq a (v`2`)) of y + `0` end end + (refl_equal ? ?) + H). + + Intros. Apply ZCG_prove_correct. Compute. Reflexivity. + Assumption. + Qed. + + Lemma test2 : (x,y:Z) ~(`x<=y` -> `x<=y-1`). + Proof. + Intros. + Cut (rho:ad->Z) (rho ad_z)=`0` -> + (ZCGeval rho (ZCGnot (ZCGimp (ZCGle (v `1`) (v `2`)) (ZCGlep (v `1`) (v `2`) `-1`)))). + Intro. + Exact (H [a:ad] Case (ad_eq a (v `1`)) of x + Case (ad_eq a (v `2`)) of y + `0` end end (refl_equal ? ?)). + Intros. Apply ZCG_prove_correct. Compute. (* fails: remains to prove false=true; indeed, + test2 is not provable. *) + <Your Tactic Text here> + <Your Tactic Text here> + +i*) |