(* Title: HOL/UNITY/Simple/Reachability.thy Author: Tanja Vos, Cambridge University Computer Laboratory Copyright 2000 University of Cambridge Reachability in Graphs. From Chandy and Misra, "Parallel Program Design" (1989), sections 6.2 and 11.3. *) theory Reachability imports "../Detects" Reach begin type_synonym edge = "vertex * vertex" record state = reach :: "vertex => bool" nmsg :: "edge => nat" consts root :: "vertex" E :: "edge set" V :: "vertex set" inductive_set REACHABLE :: "edge set" where base: "v \ V ==> ((v,v) \ REACHABLE)" | step: "((u,v) \ REACHABLE) & (v,w) \ E ==> ((u,w) \ REACHABLE)" definition reachable :: "vertex => state set" where "reachable p == {s. reach s p}" definition nmsg_eq :: "nat => edge => state set" where "nmsg_eq k == %e. {s. nmsg s e = k}" definition nmsg_gt :: "nat => edge => state set" where "nmsg_gt k == %e. {s. k < nmsg s e}" definition nmsg_gte :: "nat => edge => state set" where "nmsg_gte k == %e. {s. k \ nmsg s e}" definition nmsg_lte :: "nat => edge => state set" where "nmsg_lte k == %e. {s. nmsg s e \ k}" definition final :: "state set" where "final == (\v\V. reachable v <==> {s. (root, v) \ REACHABLE}) \ (\((nmsg_eq 0) ` E))" axiomatization where Graph1: "root \ V" and Graph2: "(v,w) \ E ==> (v \ V) & (w \ V)" and MA1: "F \ Always (reachable root)" and MA2: "v \ V ==> F \ Always (- reachable v \ {s. ((root,v) \ REACHABLE)})" and MA3: "[|v \ V;w \ V|] ==> F \ Always (-(nmsg_gt 0 (v,w)) \ (reachable v))" and MA4: "(v,w) \ E ==> F \ Always (-(reachable v) \ (nmsg_gt 0 (v,w)) \ (reachable w))" and MA5: "[|v \ V; w \ V|] ==> F \ Always (nmsg_gte 0 (v,w) \ nmsg_lte (Suc 0) (v,w))" and MA6: "[|v \ V|] ==> F \ Stable (reachable v)" and MA6b: "[|v \ V;w \ W|] ==> F \ Stable (reachable v \ nmsg_lte k (v,w))" and MA7: "[|v \ V;w \ V|] ==> F \ UNIV LeadsTo nmsg_eq 0 (v,w)" lemmas E_imp_in_V_L = Graph2 [THEN conjunct1] lemmas E_imp_in_V_R = Graph2 [THEN conjunct2] lemma lemma2: "(v,w) \ E ==> F \ reachable v LeadsTo nmsg_eq 0 (v,w) \ reachable v" apply (rule MA7 [THEN PSP_Stable, THEN LeadsTo_weaken_L]) apply (rule_tac [3] MA6) apply (auto simp add: E_imp_in_V_L E_imp_in_V_R) done lemma Induction_base: "(v,w) \ E ==> F \ reachable v LeadsTo reachable w" apply (rule MA4 [THEN Always_LeadsTo_weaken]) apply (rule_tac [2] lemma2) apply (auto simp add: nmsg_eq_def nmsg_gt_def) done lemma REACHABLE_LeadsTo_reachable: "(v,w) \ REACHABLE ==> F \ reachable v LeadsTo reachable w" apply (erule REACHABLE.induct) apply (rule subset_imp_LeadsTo, blast) apply (blast intro: LeadsTo_Trans Induction_base) done lemma Detects_part1: "F \ {s. (root,v) \ REACHABLE} LeadsTo reachable v" apply (rule single_LeadsTo_I) apply (simp split: if_split_asm) apply (rule MA1 [THEN Always_LeadsToI]) apply (erule REACHABLE_LeadsTo_reachable [THEN LeadsTo_weaken_L], auto) done lemma Reachability_Detected: "v \ V ==> F \ (reachable v) Detects {s. (root,v) \ REACHABLE}" apply (unfold Detects_def, auto) prefer 2 apply (blast intro: MA2 [THEN Always_weaken]) apply (rule Detects_part1 [THEN LeadsTo_weaken_L], blast) done lemma LeadsTo_Reachability: "v \ V ==> F \ UNIV LeadsTo (reachable v <==> {s. (root,v) \ REACHABLE})" by (erule Reachability_Detected [THEN Detects_Imp_LeadstoEQ]) (* ------------------------------------ *) (* Some lemmas about <==> *) lemma Eq_lemma1: "(reachable v <==> {s. (root,v) \ REACHABLE}) = {s. ((s \ reachable v) = ((root,v) \ REACHABLE))}" by (unfold Equality_def, blast) lemma Eq_lemma2: "(reachable v <==> (if (root,v) \ REACHABLE then UNIV else {})) = {s. ((s \ reachable v) = ((root,v) \ REACHABLE))}" by (unfold Equality_def, auto) (* ------------------------------------ *) (* Some lemmas about final (I don't need all of them!) *) lemma final_lemma1: "(\v \ V. \w \ V. {s. ((s \ reachable v) = ((root,v) \ REACHABLE)) & s \ nmsg_eq 0 (v,w)}) \ final" apply (unfold final_def Equality_def, auto) apply (frule E_imp_in_V_R) apply (frule E_imp_in_V_L, blast) done lemma final_lemma2: "E\{} ==> (\v \ V. \e \ E. {s. ((s \ reachable v) = ((root,v) \ REACHABLE))} \ nmsg_eq 0 e) \ final" apply (unfold final_def Equality_def) apply (auto split!: if_split) apply (frule E_imp_in_V_L, blast) done lemma final_lemma3: "E\{} ==> (\v \ V. \e \ E. (reachable v <==> {s. (root,v) \ REACHABLE}) \ nmsg_eq 0 e) \ final" apply (frule final_lemma2) apply (simp (no_asm_use) add: Eq_lemma2) done lemma final_lemma4: "E\{} ==> (\v \ V. \e \ E. {s. ((s \ reachable v) = ((root,v) \ REACHABLE))} \ nmsg_eq 0 e) = final" apply (rule subset_antisym) apply (erule final_lemma2) apply (unfold final_def Equality_def, blast) done lemma final_lemma5: "E\{} ==> (\v \ V. \e \ E. ((reachable v) <==> {s. (root,v) \ REACHABLE}) \ nmsg_eq 0 e) = final" apply (frule final_lemma4) apply (simp (no_asm_use) add: Eq_lemma2) done lemma final_lemma6: "(\v \ V. \w \ V. (reachable v <==> {s. (root,v) \ REACHABLE}) \ nmsg_eq 0 (v,w)) \ final" apply (simp (no_asm) add: Eq_lemma2 Int_def) apply (rule final_lemma1) done lemma final_lemma7: "final = (\v \ V. \w \ V. ((reachable v) <==> {s. (root,v) \ REACHABLE}) \ (-{s. (v,w) \ E} \ (nmsg_eq 0 (v,w))))" apply (unfold final_def) apply (rule subset_antisym, blast) apply (auto split: if_split_asm) apply (blast dest: E_imp_in_V_L E_imp_in_V_R)+ done (* ------------------------------------ *) (* ------------------------------------ *) (* Stability theorems *) lemma not_REACHABLE_imp_Stable_not_reachable: "[| v \ V; (root,v) \ REACHABLE |] ==> F \ Stable (- reachable v)" apply (drule MA2 [THEN AlwaysD], auto) done lemma Stable_reachable_EQ_R: "v \ V ==> F \ Stable (reachable v <==> {s. (root,v) \ REACHABLE})" apply (simp (no_asm) add: Equality_def Eq_lemma2) apply (blast intro: MA6 not_REACHABLE_imp_Stable_not_reachable) done lemma lemma4: "((nmsg_gte 0 (v,w) \ nmsg_lte (Suc 0) (v,w)) \ (- nmsg_gt 0 (v,w) \ A)) \ A \ nmsg_eq 0 (v,w)" apply (unfold nmsg_gte_def nmsg_lte_def nmsg_gt_def nmsg_eq_def, auto) done lemma lemma5: "reachable v \ nmsg_eq 0 (v,w) = ((nmsg_gte 0 (v,w) \ nmsg_lte (Suc 0) (v,w)) \ (reachable v \ nmsg_lte 0 (v,w)))" by (unfold nmsg_gte_def nmsg_lte_def nmsg_gt_def nmsg_eq_def, auto) lemma lemma6: "- nmsg_gt 0 (v,w) \ reachable v \ nmsg_eq 0 (v,w) \ reachable v" apply (unfold nmsg_gte_def nmsg_lte_def nmsg_gt_def nmsg_eq_def, auto) done lemma Always_reachable_OR_nmsg_0: "[|v \ V; w \ V|] ==> F \ Always (reachable v \ nmsg_eq 0 (v,w))" apply (rule Always_Int_I [OF MA5 MA3, THEN Always_weaken]) apply (rule_tac [5] lemma4, auto) done lemma Stable_reachable_AND_nmsg_0: "[|v \ V; w \ V|] ==> F \ Stable (reachable v \ nmsg_eq 0 (v,w))" apply (subst lemma5) apply (blast intro: MA5 Always_imp_Stable [THEN Stable_Int] MA6b) done lemma Stable_nmsg_0_OR_reachable: "[|v \ V; w \ V|] ==> F \ Stable (nmsg_eq 0 (v,w) \ reachable v)" by (blast intro!: Always_weaken [THEN Always_imp_Stable] lemma6 MA3) lemma not_REACHABLE_imp_Stable_not_reachable_AND_nmsg_0: "[| v \ V; w \ V; (root,v) \ REACHABLE |] ==> F \ Stable (- reachable v \ nmsg_eq 0 (v,w))" apply (rule Stable_Int [OF MA2 [THEN Always_imp_Stable] Stable_nmsg_0_OR_reachable, THEN Stable_eq]) prefer 4 apply blast apply auto done lemma Stable_reachable_EQ_R_AND_nmsg_0: "[| v \ V; w \ V |] ==> F \ Stable ((reachable v <==> {s. (root,v) \ REACHABLE}) \ nmsg_eq 0 (v,w))" by (simp add: Equality_def Eq_lemma2 Stable_reachable_AND_nmsg_0 not_REACHABLE_imp_Stable_not_reachable_AND_nmsg_0) (* ------------------------------------ *) (* LeadsTo final predicate (Exercise 11.2 page 274) *) lemma UNIV_lemma: "UNIV \ (\v \ V. UNIV)" by blast lemmas UNIV_LeadsTo_completion = LeadsTo_weaken_L [OF Finite_stable_completion UNIV_lemma] lemma LeadsTo_final_E_empty: "E={} ==> F \ UNIV LeadsTo final" apply (unfold final_def, simp) apply (rule UNIV_LeadsTo_completion) apply safe apply (erule LeadsTo_Reachability [simplified]) apply (drule Stable_reachable_EQ_R, simp) done lemma Leadsto_reachability_AND_nmsg_0: "[| v \ V; w \ V |] ==> F \ UNIV LeadsTo ((reachable v <==> {s. (root,v) \ REACHABLE}) \ nmsg_eq 0 (v,w))" apply (rule LeadsTo_Reachability [THEN LeadsTo_Trans], blast) apply (subgoal_tac "F \ (reachable v <==> {s. (root,v) \ REACHABLE}) \ UNIV LeadsTo (reachable v <==> {s. (root,v) \ REACHABLE}) \ nmsg_eq 0 (v,w) ") apply simp apply (rule PSP_Stable2) apply (rule MA7) apply (rule_tac [3] Stable_reachable_EQ_R, auto) done lemma LeadsTo_final_E_NOT_empty: "E\{} ==> F \ UNIV LeadsTo final" apply (rule LeadsTo_weaken_L [OF LeadsTo_weaken_R UNIV_lemma]) apply (rule_tac [2] final_lemma6) apply (rule Finite_stable_completion) apply blast apply (rule UNIV_LeadsTo_completion) apply (blast intro: Stable_INT Stable_reachable_EQ_R_AND_nmsg_0 Leadsto_reachability_AND_nmsg_0)+ done lemma LeadsTo_final: "F \ UNIV LeadsTo final" apply (cases "E={}") apply (rule_tac [2] LeadsTo_final_E_NOT_empty) apply (rule LeadsTo_final_E_empty, auto) done (* ------------------------------------ *) (* Stability of final (Exercise 11.2 page 274) *) lemma Stable_final_E_empty: "E={} ==> F \ Stable final" apply (unfold final_def, simp) apply (rule Stable_INT) apply (drule Stable_reachable_EQ_R, simp) done lemma Stable_final_E_NOT_empty: "E\{} ==> F \ Stable final" apply (subst final_lemma7) apply (rule Stable_INT) apply (rule Stable_INT) apply (simp (no_asm) add: Eq_lemma2) apply safe apply (rule Stable_eq) apply (subgoal_tac [2] "({s. (s \ reachable v) = ((root,v) \ REACHABLE) } \ nmsg_eq 0 (v,w)) = ({s. (s \ reachable v) = ( (root,v) \ REACHABLE) } \ (- UNIV \ nmsg_eq 0 (v,w)))") prefer 2 apply blast prefer 2 apply blast apply (rule Stable_reachable_EQ_R_AND_nmsg_0 [simplified Eq_lemma2 Collect_const]) apply (blast, blast) apply (rule Stable_eq) apply (rule Stable_reachable_EQ_R [simplified Eq_lemma2 Collect_const]) apply simp apply (subgoal_tac "({s. (s \ reachable v) = ((root,v) \ REACHABLE) }) = ({s. (s \ reachable v) = ( (root,v) \ REACHABLE) } \ (- {} \ nmsg_eq 0 (v,w)))") apply blast+ done lemma Stable_final: "F \ Stable final" apply (cases "E={}") prefer 2 apply (blast intro: Stable_final_E_NOT_empty) apply (blast intro: Stable_final_E_empty) done end