\<comment> \<open>weak until:\<close> coinductive UNTIL (infix\<open>until\<close> 60) for \<phi> \<psi> where
base: "\ xs \ (\ until \) xs"
|
step: "\\ xs; (\ until \) (stl xs)\ \ (\ until \) xs"
end
lemma holds_mono: assumes holds: "holds P xs"and 0: "\ x. P x \ Q x" shows"holds Q xs" using assms by auto
lemma holds_aand: "(holds P aand holds Q) steps \ holds (\ step. P step \ Q step) steps" by auto
lemma HLD_iff: "HLD s \ \ shd \ \ s" by (simp add: HLD_def)
lemma HLD_Stream[simp]: "HLD X (x ## \) \ x \ X" by (simp add: HLD_iff)
lemma nxt_mono: assumes nxt: "nxt \ xs" and 0: "\ xs. \ xs \ \ xs" shows"nxt \ xs" using assms by auto
declare ev.intros[intro] declare alw.cases[elim]
lemma ev_induct_strong[consumes 1, case_names base step]: "ev \ x \ (\xs. \ xs \ P xs) \ (\xs. ev \ (stl xs) \ \ \ xs \ P (stl xs) \ P xs) \ P x" by (induct rule: ev.induct) auto
lemma alw_coinduct[consumes 1, case_names alw stl]: "X x \ (\x. X x \ \ x) \ (\x. X x \ \ alw \ (stl x) \ X (stl x)) \ alw \ x" using alw.coinduct[of X x \<phi>] by auto
lemma ev_mono: assumes ev: "ev \ xs" and 0: "\ xs. \ xs \ \ xs" shows"ev \ xs" using ev by induct (auto simp: 0)
lemma alw_mono: assumes alw: "alw \ xs" and 0: "\ xs. \ xs \ \ xs" shows"alw \ xs" using alw by coinduct (auto simp: 0)
lemma until_monoL: assumes until: "(\1 until \) xs" and 0: "\ xs. \1 xs \ \2 xs" shows"(\2 until \) xs" using until by coinduct (auto elim: UNTIL.cases simp: 0)
lemma until_monoR: assumes until: "(\ until \1) xs" and 0: "\ xs. \1 xs \ \2 xs" shows"(\ until \2) xs" using until by coinduct (auto elim: UNTIL.cases simp: 0)
lemma until_mono: assumes until: "(\1 until \1) xs" and
0: "\ xs. \1 xs \ \2 xs" "\ xs. \1 xs \ \2 xs" shows"(\2 until \2) xs" using until by coinduct (auto elim: UNTIL.cases simp: 0)
lemma until_false: "\ until false = alw \"
proof-
{fix xs assume"(\ until false) xs" hence "alw \ xs" by coinduct (auto elim: UNTIL.cases)
} moreover
{fix xs assume"alw \ xs" hence "(\ until false) xs" by coinduct auto
} ultimatelyshow ?thesis by blast qed
lemma ev_nxt: "ev \ = (\ or nxt (ev \))" by (rule ext) (metis ev.simps nxt.simps)
lemma ev_or: "ev (\ or \) = ev \ or ev \"
proof-
{fix xs assume"(ev \ or ev \) xs" hence "ev (\ or \) xs" by (auto elim: ev_mono)
} moreover
{fix xs assume"ev (\ or \) xs" hence "(ev \ or ev \) xs" by induct auto
} ultimatelyshow ?thesis by blast qed
lemma ev_alw_aand: assumes\<phi>: "ev (alw \<phi>) xs" and \<psi>: "ev (alw \<psi>) xs" shows"ev (alw (\ aand \)) xs"
proof- obtain xl xs1 where xs1: "xs = xl @- xs1"and\<phi>\<phi>: "alw \<phi> xs1" using\<phi> by (metis ev_imp_shift) moreoverobtain yl ys1 where xs2: "xs = yl @- ys1"and\<psi>\<psi>: "alw \<psi> ys1" using\<psi> by (metis ev_imp_shift) ultimatelyhave 0: "xl @- xs1 = yl @- ys1"by auto hence"prefix xl yl \ prefix yl xl" using shift_prefix_cases by auto thus ?thesis proof assume"prefix xl yl" thenobtain yl1 where yl: "yl = xl @ yl1"by (elim prefixE) have xs1': "xs1 = yl1 @- ys1" using 0 unfolding yl by simp have"alw \ ys1" using \\ unfolding xs1' by (metis alw_shift) hence"alw (\ aand \) ys1" using \\ unfolding alw_aand by auto thus ?thesis unfolding xs2 by (auto intro: alw_ev_shift) next assume"prefix yl xl" thenobtain xl1 where xl: "xl = yl @ xl1"by (elim prefixE) have ys1': "ys1 = xl1 @- xs1" using 0 unfolding xl by simp have"alw \ xs1" using \\ unfolding ys1' by (metis alw_shift) hence"alw (\ aand \) xs1" using \\ unfolding alw_aand by auto thus ?thesis unfolding xs1 by (auto intro: alw_ev_shift) qed qed
lemma ev_alw_alw_impl: assumes"ev (alw \) xs" and "alw (alw \ impl ev \) xs" shows"ev \ xs" using assms by induct auto
lemma ev_alw_stl[simp]: "ev (alw \) (stl x) \ ev (alw \) x" by (metis (full_types) alw_nxt ev_nxt nxt.simps)
lemma alw_alw_impl_ev: "alw (alw \ impl ev \) = (ev (alw \) impl alw (ev \))" (is "?A = ?B")
proof-
{fix xs assume"?A xs \ ev (alw \) xs" hence "alw (ev \) xs" by coinduct (auto elim: ev_alw_alw_impl)
} moreover
{fix xs assume"?B xs"hence"?A xs" by coinduct auto
} ultimatelyshow ?thesis by blast qed
lemma ev_alw_impl: assumes"ev \ xs" and "alw (\ impl \) xs" shows "ev \ xs" using assms by induct auto
lemma ev_alw_impl_ev: assumes"ev \ xs" and "alw (\ impl ev \) xs" shows "ev \ xs" using ev_alw_impl[OF assms] by simp
lemma alw_mp: assumes"alw \ xs" and "alw (\ impl \) xs" shows"alw \ xs"
proof-
{assume"alw \ xs \ alw (\ impl \) xs" hence ?thesis by coinduct auto
} thus ?thesis using assms by auto qed
lemma all_imp_alw: assumes"\ xs. \ xs" shows "alw \ xs"
proof-
{assume"\ xs. \ xs" hence ?thesis by coinduct auto
} thus ?thesis using assms by auto qed
lemma alw_impl_ev_alw: assumes"alw (\ impl ev \) xs" shows"alw (ev \ impl ev \) xs" using assms by coinduct (auto dest: ev_alw_impl)
lemma ev_holds_sset: "ev (holds P) xs \ (\ x \ sset xs. P x)" (is "?L \ ?R") proof safe assume ?L thus ?R by induct (metis holds.simps stream.set_sel(1), metis stl_sset) next fix x assume"x \ sset xs" "P x" thus ?L by (induct rule: sset_induct) (simp_all add: ev.base ev.step) qed
text\<open>LTL as a program logic:\<close> lemma alw_invar: assumes"\ xs" and "alw (\ impl nxt \) xs" shows"alw \ xs"
proof-
{assume"\ xs \ alw (\ impl nxt \) xs" hence ?thesis by coinduct auto
} thus ?thesis using assms by auto qed
lemma variance: assumes 1: "\ xs" and 2: "alw (\ impl (\ or nxt \)) xs" shows"(alw \ or ev \) xs"
proof-
{assume"\ ev \ xs" hence "alw (not \) xs" unfolding not_ev[symmetric] . moreoverhave"alw (not \ impl (\ impl nxt \)) xs" using 2 by coinduct auto ultimatelyhave"alw (\ impl nxt \) xs" by(auto dest: alw_mp) with 1 have"alw \ xs" by(rule alw_invar)
} thus ?thesis by blast qed
lemma ev_alw_imp_nxt: assumes e: "ev \ xs" and a: "alw (\ impl (nxt \)) xs" shows"ev (alw \) xs"
proof- obtain xl xs1 where xs: "xs = xl @- xs1"and\<phi>: "\<phi> xs1" using e by (metis ev_imp_shift) have"\ xs1 \ alw (\ impl (nxt \)) xs1" using a \ unfolding xs by (metis alw_shift) hence"alw \ xs1" by(coinduct xs1 rule: alw.coinduct) auto thus ?thesis unfolding xs by (auto intro: alw_ev_shift) qed
inductive ev_at :: "('a stream \ bool) \ nat \ 'a stream \ bool" for P :: "'a stream \ bool" where
base: "P \ \ ev_at P 0 \"
| step:"\ P \ \ ev_at P n (stl \) \ ev_at P (Suc n) \"
inductive_simps ev_at_0[simp]: "ev_at P 0 \"
inductive_simps ev_at_Suc[simp]: "ev_at P (Suc n) \"
lemma ev_at_imp_snth: "ev_at P n \ \ P (sdrop n \)" by (induction n arbitrary: \<omega>) auto
lemma ev_at_HLD_imp_snth: "ev_at (HLD X) n \ \ \ !! n \ X" by (auto dest!: ev_at_imp_snth simp: HLD_iff)
lemma ev_at_HLD_single_imp_snth: "ev_at (HLD {x}) n \ \ \ !! n = x" by (drule ev_at_HLD_imp_snth) simp
lemma ev_at_unique: "ev_at P n \ \ ev_at P m \ \ n = m" proof (induction arbitrary: m rule: ev_at.induct) case (base \<omega>) then show ?case by (simp add: ev_at.simps[of _ _ \<omega>]) next case (step \<omega> n) from step.prems step.hyps step.IH[of "m - 1"] show ?case by (auto simp add: ev_at.simps[of _ _ \<omega>]) qed
lemma ev_iff_ev_at: "ev P \ \ (\n. ev_at P n \)" proof assume"ev P \" then show "\n. ev_at P n \" by (induction rule: ev_induct_strong) (auto intro: ev_at.intros) next assume"\n. ev_at P n \" thenobtain n where"ev_at P n \" by auto thenshow"ev P \" byinduction auto qed
lemma ev_at_shift: "ev_at (HLD X) i (stake (Suc i) \ @- \' :: 's stream) \ ev_at (HLD X) i \" by (induction i arbitrary: \<omega>) (auto simp: HLD_iff)
lemma ev_iff_ev_at_unique: "ev P \ \ (\!n. ev_at P n \)" by (auto intro: ev_at_unique simp: ev_iff_ev_at)
lemma alw_HLD_iff_streams: "alw (HLD X) \ \ \ \ streams X" proof assume"alw (HLD X) \" then show "\ \ streams X" proof (coinduction arbitrary: \<omega>) case (streams \<omega>) then show ?case by (cases \<omega>) auto qed next assume"\ \ streams X" then show "alw (HLD X) \" proof (coinduction arbitrary: \<omega>) case (alw \<omega>) then show ?case by (cases \<omega>) auto qed qed
lemma not_alw_iff: "\ (alw P \) \ ev (not P) \" using not_alw[of P] by (simp add: fun_eq_iff)
lemma not_ev_iff: "\ (ev P \) \ alw (not P) \" using not_alw_iff[of "not P"\<omega>, symmetric] by simp
lemma ev_Stream: "ev P (x ## s) \ P (x ## s) \ ev P s" by (auto elim: ev.cases)
lemma alw_ev_imp_ev_alw: assumes"alw (ev P) \" shows "ev (P aand alw (ev P)) \" proof - have"ev P \" using assms by auto from this assms show ?thesis by induct auto qed
lemma ev_False: "ev (\x. False) \ \ False" proof assume"ev (\x. False) \" then show False by induct auto qed auto
lemma alw_False: "alw (\x. False) \ \ False" by auto
lemma ev_iff_sdrop: "ev P \ \ (\m. P (sdrop m \))" proof safe assume"ev P \" then show "\m. P (sdrop m \)" by (induct rule: ev_induct_strong) (auto intro: exI[of _ 0] exI[of _ "Suc n"for n]) next fix m assume"P (sdrop m \)" then show "ev P \" by (induct m arbitrary: \<omega>) auto qed
lemma alw_iff_sdrop: "alw P \ \ (\m. P (sdrop m \))" proof safe fix m assume"alw P \" then show "P (sdrop m \)" by (induct m arbitrary: \<omega>) auto next assume"\m. P (sdrop m \)" then show "alw P \" by (coinduction arbitrary: \<omega>) (auto elim: allE[of _ 0] allE[of _ "Suc n" for n]) qed
lemma infinite_iff_alw_ev: "infinite {m. P (sdrop m \)} \ alw (ev P) \" unfolding infinite_nat_iff_unbounded_le alw_iff_sdrop ev_iff_sdrop by simp (metis le_Suc_ex le_add1)
lemma alw_inv: assumes stl: "\s. f (stl s) = stl (f s)" shows"alw P (f s) \ alw (\x. P (f x)) s" proof assume"alw P (f s)"thenshow"alw (\x. P (f x)) s" by (coinduction arbitrary: s rule: alw_coinduct)
(auto simp: stl) next assume"alw (\x. P (f x)) s" then show "alw P (f s)" by (coinduction arbitrary: s rule: alw_coinduct) (auto simp flip: stl) qed
lemma ev_inv: assumes stl: "\s. f (stl s) = stl (f s)" shows"ev P (f s) \ ev (\x. P (f x)) s" proof assume"ev P (f s)"thenshow"ev (\x. P (f x)) s" by (induction"f s" arbitrary: s) (auto simp: stl) next assume"ev (\x. P (f x)) s" then show "ev P (f s)" byinduction (auto simp flip: stl) qed
lemma alw_smap: "alw P (smap f s) \ alw (\x. P (smap f x)) s" by (rule alw_inv) simp
lemma ev_smap: "ev P (smap f s) \ ev (\x. P (smap f x)) s" by (rule ev_inv) simp
lemma alw_cong: assumes P: "alw P \" and eq: "\\. P \ \ Q1 \ \ Q2 \" shows"alw Q1 \ \ alw Q2 \" proof - from eq have"(alw P aand Q1) = (alw P aand Q2)"by auto thenhave"alw (alw P aand Q1) \ = alw (alw P aand Q2) \" by auto with P show"alw Q1 \ \ alw Q2 \" by (simp add: alw_aand) qed
lemma ev_cong: assumes P: "alw P \" and eq: "\\. P \ \ Q1 \ \ Q2 \" shows"ev Q1 \ \ ev Q2 \" proof - from P have"alw (\xs. Q1 xs \ Q2 xs) \" by (rule alw_mono) (simp add: eq) moreoverfrom P have"alw (\xs. Q2 xs \ Q1 xs) \" by (rule alw_mono) (simp add: eq) moreovernote ev_alw_impl[of Q1 \<omega> Q2] ev_alw_impl[of Q2 \<omega> Q1] ultimatelyshow"ev Q1 \ \ ev Q2 \" by auto qed
lemma suntil_induct_strong[consumes 1, case_names base step]: "(\ suntil \) x \
(\<And>\<omega>. \<psi> \<omega> \<Longrightarrow> P \<omega>) \<Longrightarrow>
(\<And>\<omega>. \<phi> \<omega> \<Longrightarrow> \<not> \<psi> \<omega> \<Longrightarrow> (\<phi> suntil \<psi>) (stl \<omega>) \<Longrightarrow> P (stl \<omega>) \<Longrightarrow> P \<omega>) \<Longrightarrow> P x" using suntil.induct[of \<phi> \<psi> x P] by blast
lemma ev_suntil: "(\ suntil \) \ \ ev \ \" by (induct rule: suntil.induct) auto
lemma suntil_inv: assumes stl: "\s. f (stl s) = stl (f s)" shows"(P suntil Q) (f s) \ ((\x. P (f x)) suntil (\x. Q (f x))) s" proof assume"(P suntil Q) (f s)"thenshow"((\x. P (f x)) suntil (\x. Q (f x))) s" by (induction"f s" arbitrary: s) (auto simp: stl intro: suntil.intros) next assume"((\x. P (f x)) suntil (\x. Q (f x))) s" then show "(P suntil Q) (f s)" byinduction (auto simp flip: stl intro: suntil.intros) qed
lemma suntil_smap: "(P suntil Q) (smap f s) \ ((\x. P (smap f x)) suntil (\x. Q (smap f x))) s" by (rule suntil_inv) simp
lemma hld_smap: "HLD x (smap f s) = holds (\y. f y \ x) s" by (simp add: HLD_def)
lemma suntil_mono: assumes eq: "\\. P \ \ Q1 \ \ Q2 \" "\\. P \ \ R1 \ \ R2 \" assumes *: "(Q1 suntil R1) \" "alw P \" shows "(Q2 suntil R2) \" using * by induct (auto intro: eq suntil.intros)
lemma suntil_cong: "alw P \ \ (\\. P \ \ Q1 \ \ Q2 \) \ (\\. P \ \ R1 \ \ R2 \) \
(Q1 suntil R1) \<omega> \<longleftrightarrow> (Q2 suntil R2) \<omega>" using suntil_mono[of P Q1 Q2 R1 R2 \<omega>] suntil_mono[of P Q2 Q1 R2 R1 \<omega>] by auto
lemma ev_suntil_iff: "ev (P suntil Q) \ \ ev Q \" proof assume"ev (P suntil Q) \" then show "ev Q \" by induct (auto dest: ev_suntil) next assume"ev Q \" then show "ev (P suntil Q) \" by induct (auto intro: suntil.intros) qed
lemma true_suntil: "((\_. True) suntil P) = ev P" by (simp add: suntil_def ev_def)
lemma suntil_lfp: "(\ suntil \) = lfp (\P s. \ s \ (\ s \ P (stl s)))" by (simp add: suntil_def)
lemma sfilter_P[simp]: "P (shd s) \ sfilter P s = shd s ## sfilter P (stl s)" using sfilter_Stream[of P "shd s""stl s"] by simp
lemma sfilter_not_P[simp]: "\ P (shd s) \ sfilter P s = sfilter P (stl s)" using sfilter_Stream[of P "shd s""stl s"] by simp
lemma sfilter_eq: assumes"ev (holds P) s" shows"sfilter P s = x ## s' \
P x \<and> (not (holds P) suntil (HLD {x} aand nxt (\<lambda>s. sfilter P s = s'))) s" using assms by (induct rule: ev_induct_strong)
(auto simp add: HLD_iff intro: suntil.intros elim: suntil.cases)
lemma sfilter_streams: "alw (ev (holds P)) \ \ \ \ streams A \ sfilter P \ \ streams {x\A. P x}" proof (coinduction arbitrary: \<omega>) case (streams \<omega>) thenhave"ev (holds P) \" by blast from this streams show ?case by (induct rule: ev_induct_strong) (auto elim: streamsE) qed
lemma alw_sfilter: assumes *: "alw (ev (holds P)) s" shows"alw Q (sfilter P s) \ alw (\x. Q (sfilter P x)) s" proof assume"alw Q (sfilter P s)"with * show"alw (\x. Q (sfilter P x)) s" proof (coinduction arbitrary: s rule: alw_coinduct) case (stl s) thenhave"ev (holds P) s" by blast from this stl show ?case by (induct rule: ev_induct_strong) auto qed auto next assume"alw (\x. Q (sfilter P x)) s" with * show "alw Q (sfilter P s)" proof (coinduction arbitrary: s rule: alw_coinduct) case (stl s) thenhave"ev (holds P) s" by blast from this stl show ?case by (induct rule: ev_induct_strong) auto qed auto qed
lemma ev_sfilter: assumes *: "alw (ev (holds P)) s" shows"ev Q (sfilter P s) \ ev (\x. Q (sfilter P x)) s" proof assume"ev Q (sfilter P s)"from this * show"ev (\x. Q (sfilter P x)) s" proof (induction"sfilter P s" arbitrary: s rule: ev_induct_strong) case (step s) thenhave"ev (holds P) s" by blast from this step show ?case by (induct rule: ev_induct_strong) auto qed auto next assume"ev (\x. Q (sfilter P x)) s" then show "ev Q (sfilter P s)" proof (induction rule: ev_induct_strong) case (step s) thenshow ?case by (cases "P (shd s)") auto qed auto qed
lemma holds_sfilter: assumes"ev (holds Q) s"shows"holds P (sfilter Q s) \ (not (holds Q) suntil (holds (Q aand P))) s" proof assume"holds P (sfilter Q s)"with assms show"(not (holds Q) suntil (holds (Q aand P))) s" by (induct rule: ev_induct_strong) (auto intro: suntil.intros) next assume"(not (holds Q) suntil (holds (Q aand P))) s"thenshow"holds P (sfilter Q s)" by induct auto qed
lemma alw_sconst: "alw P (sconst x) \ P (sconst x)" proof assume"P (sconst x)"thenshow"alw P (sconst x)" by coinduction auto qed auto
lemma ev_sconst: "ev P (sconst x) \ P (sconst x)" proof assume"ev P (sconst x)"thenshow"P (sconst x)" by (induction"sconst x") auto qed auto
lemma suntil_sconst: "(\ suntil \) (sconst x) \ \ (sconst x)" proof assume"(\ suntil \) (sconst x)" then show "\ (sconst x)" by (induction"sconst x") auto qed (auto intro: suntil.intros)
lemma hld_smap': "HLD x (smap f s) = HLD (f -` x) s" by (simp add: HLD_def)
lemma pigeonhole_stream: assumes"alw (HLD s) \" assumes"finite s" shows"\x\s. alw (ev (HLD {x})) \" proof - have"\i\UNIV. \x\s. \ !! i = x" using\<open>alw (HLD s) \<omega>\<close> by (simp add: alw_iff_sdrop HLD_iff) from pigeonhole_infinite_rel[OF infinite_UNIV_nat \<open>finite s\<close> this] show ?thesis by (simp add: HLD_iff flip: infinite_iff_alw_ev) qed
lemma ev_eq_suntil: "ev P \ \ (not P suntil P) \" proof assume"ev P \" then show "((\xs. \ P xs) suntil P) \" by (induction rule: ev_induct_strong) (auto intro: suntil.intros) qed (auto simp: ev_suntil)
section \<open>Weak vs. strong until (contributed by Michael Foster, University of Sheffield)\<close>
lemma suntil_implies_until: "(\ suntil \) \ \ (\ until \) \" by (induct rule: suntil_induct_strong) (auto intro: UNTIL.intros)
lemma alw_implies_until: "alw \ \ \ (\ until \) \" unfolding until_false[symmetric] by (auto elim: until_mono)
lemma until_ev_suntil: "(\ until \) \ \ ev \ \ \ (\ suntil \) \" proof (rotate_tac, induction rule: ev.induct) case (base xs) thenshow ?case by (simp add: suntil.base) next case (step xs) thenshow ?case by (metis UNTIL.cases suntil.base suntil.step) qed
lemma suntil_as_until: "(\ suntil \) \ = ((\ until \) \ \ ev \ \)" using ev_suntil suntil_implies_until until_ev_suntil by blast
lemma until_not_relesased_now: "(\ until \) \ \ \ \ \ \ \ \" using UNTIL.cases by auto
lemma until_must_release_ev: "(\ until \) \ \ ev (not \) \ \ ev \ \" proof (rotate_tac, induction rule: ev.induct) case (base xs) thenshow ?case using until_not_relesased_now by blast next case (step xs) thenshow ?case using UNTIL.cases by blast qed
lemma until_as_suntil: "(\ until \) \ = ((\ suntil \) or (alw \)) \" using alw_implies_until not_alw_iff suntil_implies_until until_ev_suntil until_must_release_ev by blast
lemma alw_holds: "alw (holds P) (h##t) = (P h \ alw (holds P) t)" by (metis alw.simps holds_Stream stream.sel(2))
lemma alw_eq_sconst: "(alw (HLD {h}) t) = (t = sconst h)" unfolding sconst_alt alw_HLD_iff_streams streams_iff_sset using stream.set_sel(1) by force
lemma sdrop_if_suntil: "(p suntil q) \ \ \j. q (sdrop j \) \ (\k < j. p (sdrop k \))" proof(induction rule: suntil.induct) case (base \<omega>) thenshow ?case by force next case (step \<omega>) thenobtain j where"q (sdrop j (stl \))" "\k))" by blast with step(1,2) show ?case using ev_at_imp_snth less_Suc_eq_0_disj by (auto intro!: exI[where x="j+1"]) qed
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.