(* Title: LList2.thy ID: $Id: LList2.thy,v 1.13 2008/10/07 14:07:44 fhaftmann Exp $ Author: Stefan Friedrich Maintainer: Stefan Friedrich License: LGPL Llists over an alphabet. Common operations on LLists (ltake, ldrop, lnth). The prefix order of llists. Safety and liveness. *) header{* More on llists *} theory LList2a imports "Coinductive_List" begin section{*Preliminaries*} syntax LCons :: "'a \ 'a llist \ 'a llist" (infixr "##" 65) lappend :: "['a llist, 'a llist] => 'a llist" (infixr "@@" 65) (* lemmas lappend_assoc = lappend_assoc' *) lemmas llistE = llist_cases lemma llist_split: "P (llist_case f1 f2 x) = ((x = LNil \ P f1) \ (\ a xs. x = a ## xs \ P (f2 a xs)))" by (cases "x") auto lemma llist_split_asm: "P (llist_case f1 f2 x) = (\ (x = LNil \ \ P f1 \ (\a llist. x = a ## llist \ \ P (f2 a llist))))" by (cases "x") auto section{*Finite and infinite llists over an alphabet*} inductive_set finlsts :: "'a set \ 'a llist set" ("(_\\<^sup>\)" [1000] 999) for A :: "'a set" where LNil_fin [iff]: "LNil \ A\<^sup>\" | LCons_fin [intro!]: "\ l \ A\<^sup>\; a \ A \ \ a ## l \ A\<^sup>\" coinductive_set alllsts :: "'a set \ 'a llist set" ("(_\\<^sup>\)" [1000] 999) for A :: "'a set" where LNil_all [iff]: "LNil \ A\<^sup>\" | LCons_all [intro!]: "\ l \ A\<^sup>\; a \ A \ \ a ## l \ A\<^sup>\" declare alllsts.cases [case_names LNil LCons, cases set: alllsts] definition inflsts :: "'a set \ 'a llist set" where "inflsts A \ A\<^sup>\ - UNIV\<^sup>\" definition fpslsts :: "'a set \ 'a llist set" where "fpslsts A \ A\<^sup>\ - {LNil}" definition poslsts :: "'a set \ 'a llist set" where "poslsts A \ A\<^sup>\ - {LNil}" notation (xsymbols) inflsts ("(_\\<^sup>\)" [1000] 999) and fpslsts ("(_\\<^sup>\)" [1000] 999) and poslsts ("(_\\<^sup>\)" [1000] 999) subsection{*Facts about all llists*} lemma neq_LNil_conv: "(xs \ LNil) = (\y ys. xs = y ## ys)" by (cases xs) auto lemma alllsts_UNIV [iff]: "s \ UNIV\<^sup>\" proof - have "s \ UNIV" by blast thus ?thesis proof coinduct case (alllsts z) thus ?case by(cases z) auto qed qed lemma alllsts_empty [simp]: "{}\<^sup>\ = {LNil}" by (auto elim: alllsts.cases) lemma alllsts_mono: assumes asubb: "A \ B" shows "A\<^sup>\ \ B\<^sup>\" proof fix x assume "x \ A\<^sup>\" thus "x \ B\<^sup>\" proof coinduct case (alllsts z) thus ?case using asubb by(cases z) auto qed qed declare alllsts_mono [mono_set] lemma LConsE [iff]: "x##xs \ A\<^sup>\ = (x\A \ xs \ A\<^sup>\)" by (auto elim: alllsts.cases) subsection{*Facts about non-empty (positive) llists*} lemma poslsts_iff [iff]: "(s \ A\<^sup>\) = (s \ A\<^sup>\ \ s \ LNil)" by (simp add: poslsts_def) lemma poslsts_UNIV [iff]: "s \ UNIV\<^sup>\ = (s \ LNil)" by auto lemma poslsts_empty [simp]: "{}\<^sup>\ = {}" by auto lemma poslsts_mono: "A \ B \ A\<^sup>\ \ B\<^sup>\" by (auto dest: alllsts_mono) subsection{*Facts about finite llists*} lemma finlsts_empty [simp]: "{}\<^sup>\ = {LNil}" by (auto elim: finlsts.cases) lemma finsubsetall: "x \ A\<^sup>\ \ x \ A\<^sup>\" by (induct rule: finlsts.induct) auto lemma finlsts_mono: "A\B \ A\<^sup>\ \ B\<^sup>\" by (auto, erule finlsts.induct) auto declare finlsts_mono [mono_set] lemma finlsts_induct [case_names LNil_fin LCons_fin, induct set: finlsts, consumes 1]: assumes xA: "x \ A\<^sup>\" and lnil: "\l. l = LNil \ P l" and lcons: "\a l. \l \ A\<^sup>\; P l; a \ A\ \ P (a ## l)" shows "P x" using xA by (induct "x") (auto intro: lnil lcons) (* lemma LCons_finite: "a##xs \ A\<^sup>\ \ xs \ A\<^sup>\" by (erule finlsts.cases) auto *) lemma finite_lemma: assumes "x \ A\<^sup>\" shows "x \ B\<^sup>\ \ x \ B\<^sup>\" using assms proof (induct) case LNil_fin thus ?case by auto next case (LCons_fin a l) thus ?case using LCons_fin by (cases "a##l") auto qed lemma fin_finite [dest]: assumes "r \ A\<^sup>\" "r \ UNIV\<^sup>\" shows "False" proof- have "A \ UNIV" by auto hence "A\<^sup>\ \ UNIV\<^sup>\" by (rule finlsts_mono) thus ?thesis using prems by auto qed lemma finT_simp [simp]: "r \ A\<^sup>\ \ r\UNIV\<^sup>\" by auto subsubsection{*A recursion operator for finite llists*} definition finlsts_pred :: "('a llist \ 'a llist) set" where "finlsts_pred \ {(r,s). r \ UNIV\<^sup>\ \ (\a. a##r = s)}" definition finlsts_rec :: "['b, ['a, 'a llist, 'b] \ 'b] \ 'a llist \ 'b" where "finlsts_rec c d r \ if r \ UNIV\<^sup>\ then (wfrec finlsts_pred (%f. llist_case c (%a r. d a r (f r))) r) else undefined" lemma finlsts_predI: "r \ A\<^sup>\ \ (r, a##r) \ finlsts_pred" by (auto simp: finlsts_pred_def) lemma wf_finlsts_pred: "wf finlsts_pred" proof (rule wfI [of _ "UNIV\<^sup>\"]) show "finlsts_pred \ UNIV\<^sup>\ \ UNIV\<^sup>\" by (auto simp: finlsts_pred_def elim: finlsts.cases) next fix x::"'a llist" and P::"'a llist \ bool" assume xfin: "x \ UNIV\<^sup>\" and H [unfolded finlsts_pred_def]: "(\x. (\y. (y, x) \ finlsts_pred \ P y) \ P x)" from xfin show "P x" proof(induct x) case LNil_fin with H show ?case by blast next case (LCons_fin a l) with H show ?case by blast qed qed lemma finlsts_rec_LNil: "finlsts_rec c d LNil = c" by (auto simp: wf_finlsts_pred finlsts_rec_def wfrec) lemma finlsts_rec_LCons: "r \ A\<^sup>\ \ finlsts_rec c d (a ## r) = d a r (finlsts_rec c d r)" by (auto simp: wf_finlsts_pred finlsts_rec_def wfrec cut_def intro: finlsts_predI) lemma finlsts_rec_LNil_def: "f \ finlsts_rec c d \ f LNil = c" by (auto simp: finlsts_rec_LNil) lemma finlsts_rec_LCons_def: "\ f \ finlsts_rec c d; r \ A\<^sup>\ \ \ f (a ## r) = d a r (f r)" by (auto simp: finlsts_rec_LCons) subsection{*Facts about non-empty (positive) finite llists*} lemma fpslsts_iff [iff]: "(s \ A\<^sup>\) = (s \ A\<^sup>\ \ s \ LNil)" by (auto simp: fpslsts_def) lemma fpslsts_empty [simp]: "{}\<^sup>\ = {}" by auto lemma fpslsts_mono: "A \ B \ A\<^sup>\ \ B\<^sup>\" by (auto dest: finlsts_mono) lemma fpslsts_cases [case_names LCons, cases set: fpslsts]: assumes rfps: "r \ A\<^sup>\" and H: "\ a rs. \ r = a ## rs; a\A; rs \ A\<^sup>\ \ \ R" shows "R" proof- from rfps have "r \ A\<^sup>\" and "r \ LNil" by auto thus ?thesis by (cases r, simp) (blast intro!: H) qed subsection{*Facts about infinite llists*} lemma inflstsI [intro]: "\ x \ A\<^sup>\; x \ UNIV\<^sup>\ \ False \ \ x \ A\<^sup>\" unfolding inflsts_def by clarsimp lemma inflstsE [elim]: "\ x \ A\<^sup>\; \ x \ A\<^sup>\; x \ UNIV\<^sup>\ \ \ R \ \ R" by (unfold inflsts_def) auto lemma inflsts_empty [simp]: "{}\<^sup>\ = {}" by auto lemma infsubsetall: "x \ A\<^sup>\ \ x \ A\<^sup>\" by (auto intro: finite_lemma finsubsetall) lemma inflsts_mono: "A \ B \ A\<^sup>\ \ B\<^sup>\" by (blast dest: alllsts_mono infsubsetall) lemma inflsts_cases [case_names LCons, cases set: inflsts, consumes 1]: assumes sinf: "s \ A\<^sup>\" and R: "\a l. \ l \ A\<^sup>\; a \ A; s = a ## l \ \ R" shows "R" proof - from sinf have "s \ A\<^sup>\" "s \ UNIV\<^sup>\" by auto then obtain a l where "l \ A\<^sup>\" and "a\A" and "s = a ## l" by (cases "s") auto thus ?thesis by (rule R) qed lemma inflstsI2: "\a \ A; t \ A\<^sup>\\ \ a ## t \ A\<^sup>\" by (auto elim: finlsts.cases) lemma infT_simp [simp]: "r \ A\<^sup>\ \ r\UNIV\<^sup>\" by auto lemma alllstsE [consumes 1, case_names finite infinite]: "\ x\A\<^sup>\; x \ A\<^sup>\ \ P; x \ A\<^sup>\ \ P \ \ P" by (auto intro: finite_lemma simp: inflsts_def) lemma fin_inf_cases [case_names finite infinite]: "\ r\UNIV\<^sup>\ \ P; r \ UNIV\<^sup>\ \ P \ \ P" by auto lemma fin_Int_inf: "A\<^sup>\ \ A\<^sup>\ = {}" and fin_Un_inf: "A\<^sup>\ \ A\<^sup>\ = A\<^sup>\" by (auto intro: finite_lemma finsubsetall) lemma notfin_inf [iff]: "(x \ UNIV\<^sup>\) = (x \ UNIV\<^sup>\)" by auto lemma notinf_fin [iff]: "(x \ UNIV\<^sup>\) = (x \ UNIV\<^sup>\)" by auto section{*Lappend*} subsection{*Simplification*} lemma lapp_inf [simp]: assumes "s \ A\<^sup>\" shows "s @@ t = s" proof - from `s \ A\<^sup>\` have "(lappend s t, s) \ (\u. (u@@t, u))`A\<^sup>\" by auto thus ?thesis proof(coinduct rule: llist_equalityI) case (Eqllist q) then obtain u where "u \ A\<^sup>\" "q = (lappend u t, u)" by auto thus ?case by cases auto qed qed lemma LNil_is_lappend_conv [iff]: "(LNil = s @@ t) = (s = LNil \ t = LNil)" by (cases "s") auto lemma lappend_is_LNil_conv [iff]: "(s @@ t = LNil) = (s = LNil \ t = LNil)" by (cases "s") auto lemma same_lappend_eq [iff]: "r \ A\<^sup>\ \ (r @@ s = r @@ t) = (s = t)" by (erule finlsts.induct) simp+ (* lemma lappend_same_eq [iff]: assumes rA: "r \ A\<^sup>\" shows "(s @@ r = t @@ r) = (s = t)" oops *) subsection{*Typing rules*} lemma lappT: assumes sllist: "s \ A\<^sup>\" and tllist: "t \ A\<^sup>\" shows "s@@t \ A\<^sup>\" proof - from assms have "lappend s t \ (\u\A\<^sup>\. \v\A\<^sup>\. {lappend u v})" by fast thus ?thesis proof coinduct case (alllsts z) then obtain u v where ullist: "u\A\<^sup>\" and vllist: "v\A\<^sup>\" and zapp: "z=u @@ v" by auto thus ?case by (cases "u") (auto elim: alllsts.cases) qed qed lemma lappfin_finT: "\ s \ A\<^sup>\; t \ A\<^sup>\ \ \ s@@t \ A\<^sup>\" by (induct rule: finlsts.induct) auto lemma lapp_fin_fin_lemma: assumes rsA: "r @@ s \ A\<^sup>\" shows "r \ A\<^sup>\" using rsA proof(induct l\"r@@s" arbitrary: r) case LNil_fin thus ?case by auto next case (LCons_fin a l') show ?case proof (cases "r") case LNil thus ?thesis by auto next case (LCons x xs) with `a##l' = r @@ s` have "a = x" and "l' = xs @@ s" by auto with LCons_fin LCons show ?thesis by auto qed qed lemma lapp_fin_fin_iff [iff]: "(r @@ s \ A\<^sup>\) = (r \ A\<^sup>\ \ s \ A\<^sup>\)" proof (auto intro: lappfin_finT lapp_fin_fin_lemma) assume rsA: "r @@ s \ A\<^sup>\" hence "r \ A\<^sup>\" by (rule lapp_fin_fin_lemma) hence "r @@ s \ A\<^sup>\ \ s \ A\<^sup>\" by (induct "r", simp) (auto elim: finlsts.cases) with rsA show "s \ A\<^sup>\" by auto qed lemma lapp_all_invT: assumes rs: "r@@s \ A\<^sup>\" shows "r \ A\<^sup>\" proof (cases "r \ UNIV\<^sup>\") case False with rs show ?thesis by simp next case True thus ?thesis using rs by (induct "r") auto qed (* lemma lapp_infT: "s \ A\<^sup>\ \ s @@ t \ A\<^sup>\" by simp *) lemma lapp_fin_infT: "\s \ A\<^sup>\; t \ A\<^sup>\\ \ s @@ t \ A\<^sup>\" by (induct rule: finlsts.induct) (auto intro: inflstsI2) lemma app_invT: assumes "r \ A\<^sup>\" shows "r @@ s \ A\<^sup>\ \ s \ A\<^sup>\" using assms proof (induct arbitrary: s) case LNil_fin thus ?case by simp next case (LCons_fin a l) from `(a ## l) @@ s \ A\<^sup>\` have "a ## (l @@ s) \ A\<^sup>\" by simp hence "l @@ s \ A\<^sup>\" by (auto elim: inflsts_cases) with LCons_fin show "s \ A\<^sup>\" by blast qed lemma lapp_inv2T: assumes rsinf: "r @@ s \ A\<^sup>\" shows "r \ A\<^sup>\ \ s \ A\<^sup>\ \ r \ A\<^sup>\" proof (rule disjCI) assume rnotinf: "r \ A\<^sup>\" moreover from rsinf have rsall: "r@@s \ A\<^sup>\" by auto hence "r \ A\<^sup>\" by (rule lapp_all_invT) hence "r \ A\<^sup>\" using rnotinf by (auto elim: alllstsE) ultimately show "r \ A\<^sup>\ \ s \ A\<^sup>\" using rsinf by (auto intro: app_invT) qed lemma lapp_infT: "(r @@ s \ A\<^sup>\) = (r \ A\<^sup>\ \ s \ A\<^sup>\ \ r \ A\<^sup>\)" by (auto dest: lapp_inv2T intro: lapp_fin_infT) lemma lapp_allT_iff: "(r @@ s \ A\<^sup>\) = (r \ A\<^sup>\ \ s \ A\<^sup>\ \ r \ A\<^sup>\)" (is "?L = ?R") proof assume ?L thus ?R by (cases rule: alllstsE) (auto simp: lapp_infT intro: finsubsetall) next assume ?R thus ?L by (auto dest: finsubsetall intro: lappT) qed section{*Length, indexing, prefixes, and suffixes of llists*} primrec ll2f :: "'a llist \ nat \ 'a option" (infix "!!" 100) where "l!!0 = (case l of LNil \ None | LCons x xs \ Some x)" | "l!!(Suc i) = (case l of LNil \ None | x ## xs \ xs!!i)" primrec ltake :: "'a llist \ nat \ 'a llist" where "ltake l 0 = LNil" | "ltake l (Suc i) = (case l of LNil \ LNil | x ## xs \ x ## ltake xs i)" primrec ldrop :: "'a llist \ nat \ 'a llist" where "ldrop l 0 = l" | "ldrop l (Suc i) = (case l of LNil \ LNil | x ## xs \ ldrop xs i)" notation (xsymbols) ltake (infixl "\" 110) and ldrop (infixl "\" 110) definition lset :: "'a llist \ 'a set" where "lset l \ ran (ll2f l)" definition llength :: "'a llist \ nat" where "llength \ finlsts_rec 0 (\ a r n. Suc n)" definition llast :: "'a llist \ 'a" where "llast \ finlsts_rec undefined (\ x xs l. if xs = LNil then x else l)" definition lbutlast :: "'a llist \ 'a llist" where "lbutlast \ finlsts_rec LNil (\ x xs l. if xs = LNil then LNil else x##l)" definition lrev :: "'a llist \ 'a llist" where "lrev \ finlsts_rec LNil (\ x xs l. l @@ x ## LNil)" lemmas llength_LNil = llength_def [THEN finlsts_rec_LNil_def, standard] and llength_LCons = llength_def [THEN finlsts_rec_LCons_def, standard] lemmas llength_simps [simp] = llength_LNil llength_LCons lemmas llast_LNil = llast_def [THEN finlsts_rec_LNil_def, standard] and llast_LCons = llast_def [THEN finlsts_rec_LCons_def, standard] lemmas llast_simps [simp] = llast_LNil llast_LCons lemmas lbutlast_LNil = lbutlast_def [THEN finlsts_rec_LNil_def, standard] and lbutlast_LCons = lbutlast_def [THEN finlsts_rec_LCons_def, standard] lemmas lbutlast_simps [simp] = lbutlast_LNil lbutlast_LCons lemmas lrev_LNil = lrev_def [THEN finlsts_rec_LNil_def, standard] and lrev_LCons = lrev_def [THEN finlsts_rec_LCons_def, standard] lemmas lrev_simps [simp] = lrev_LNil lrev_LCons lemma lrevT [simp, intro!]: "xs \ A\<^sup>\ \ lrev xs \ A\<^sup>\" by (induct rule: finlsts.induct) auto lemma lrev_lappend [simp]: assumes fin: "xs \ UNIV\<^sup>\" "ys \ UNIV\<^sup>\" shows "lrev (xs @@ ys) = (lrev ys) @@ (lrev xs)" using fin by induct (auto simp: lrev_LCons [of _ UNIV] lappend_assoc) lemma lrev_lrev_ident [simp]: assumes fin: "xs \ UNIV\<^sup>\" shows "lrev (lrev xs) = xs" using fin proof (induct) case (LCons_fin a l) have "a ## LNil \ UNIV\<^sup>\" by auto thus ?case using LCons_fin by auto qed simp lemma lrev_is_LNil_conv [iff]: "xs \ UNIV\<^sup>\ \ (lrev xs = LNil) = (xs = LNil)" by (induct rule: finlsts.induct) auto lemma LNil_is_lrev_conv [iff]: "xs \ UNIV\<^sup>\ \ (LNil = lrev xs) = (xs = LNil)" by (induct rule: finlsts.induct) auto lemma lrev_is_lrev_conv [iff]: assumes fin: "xs \ UNIV\<^sup>\" "ys \ UNIV\<^sup>\" shows "(lrev xs = lrev ys) = (xs = ys)" (is "?L = ?R") proof assume L: ?L hence "lrev (lrev xs) = lrev (lrev ys)" by simp thus ?R using fin by simp qed simp lemma lrev_induct [case_names LNil snocl, consumes 1]: assumes fin: "xs \ A\<^sup>\" and init: "P LNil" and step: "\x xs. \ xs \ A\<^sup>\; P xs; x \ A \ \ P (xs @@ x##LNil)" shows "P xs" proof- from fin have "lrev xs \ A\<^sup>\" by simp hence "P (lrev (lrev xs))" proof (induct "lrev xs") case (LNil_fin l) with init show "P (lrev l)" by simp next case (LCons_fin a l) thus ?case by (auto intro: step) qed thus ?thesis using fin by simp qed lemma finlsts_rev_cases: assumes tfin: "t \ A\<^sup>\" obtains (LNil) "t = LNil" | (snocl) a l where "l \ A\<^sup>\" "a \ A" "t = l @@ a ## LNil" using prems by (induct rule: lrev_induct) auto (*lemma fps_lrev_cases [case_names snocl, consumes 1]: "\t \ UNIV\<^sup>\; \ a s. t = s @@ a ## LNil \ R \ \ R" by (auto elim!: finlsts_rev_cases) *) lemma ll2f_LNil [simp]: "LNil!!x = None" by (cases "x") auto lemma None_lfinite: "t!!i = None \ t \ UNIV\<^sup>\" proof (induct "i" arbitrary: t) case 0 thus ?case by(cases t) auto next case (Suc n) show ?case proof(cases t) case LNil thus ?thesis by auto next case (LCons x l') with `l' !! n = None \ l' \ UNIV\<^sup>\` `t !! Suc n = None` show ?thesis by auto qed qed lemma infinite_Some: "t \ A\<^sup>\ \ \a. t!!i = Some a" by (rule ccontr) (auto dest: None_lfinite) lemmas infinite_idx_SomeE = exE [OF infinite_Some, standard] lemma Least_True [simp]: "(LEAST (n::nat). True) = 0" by (auto simp: Least_def) lemma ll2f_llength [simp]: "r \ A\<^sup>\ \ r!!(llength r) = None" by (erule finlsts.induct) auto lemma llength_least_None: assumes rA: "r \ A\<^sup>\" shows "llength r = (LEAST i. r!!i = None)" using rA proof induct case LNil_fin thus ?case by simp next case (LCons_fin a l) hence "(LEAST i. (a ## l) !! i = None) = llength (a ## l)" by (auto intro!: ll2f_llength Least_Suc2) thus ?case by rule qed lemma ll2f_lem1: "t !! (Suc i) = Some x \ \ y. t !! i = Some y" proof (induct i arbitrary: x t) case 0 thus ?case by (auto split: llist_split llist_split_asm) next case (Suc k) thus ?case by (cases t) auto qed lemmas ll2f_Suc_Some = ll2f_lem1 [THEN exE, standard] lemma ll2f_None_Suc: "t !! i = None \ t !! Suc i = None" proof (induct i arbitrary: t) case 0 thus ?case by (auto split: llist_split) next case (Suc k) thus ?case by (cases t) auto qed lemma ll2f_None_le: "\ t!!j = None; j \ i \ \ t!!i = None" proof (induct i arbitrary: t j) case 0 thus ?case by simp next case (Suc k) thus ?case by (cases j) (auto split: llist_split) qed lemma ll2f_Some_le: assumes jlei: "j \ i" and tisome: "t !! i = Some x" and H: "\ y. t !! j = Some y \ Q" shows "Q" proof - have "\ y. t !! j = Some y" (is "?R") proof (rule ccontr) assume "\ ?R" hence "t !! j = None" by auto with tisome jlei show False by (auto dest: ll2f_None_le) qed thus ?thesis using H by auto qed lemma ltake_LNil [simp]: "LNil \ i = LNil" by (cases "i") auto lemma ltake_LCons_Suc: "(a ## l) \ (Suc i) = a ## l \ i" by simp lemma take_fin [iff]: "t \ A\<^sup>\ \ t\i \ A\<^sup>\" proof (induct i arbitrary: t) case 0 show ?case by auto next case (Suc j) thus ?case by (cases "t") auto qed lemma ltake_fin [iff]: "r \ i \ UNIV\<^sup>\" by simp (* lemma take_fin [iff]: "\t. t\i \ UNIV\<^sup>\" proof (induct i) case 0 show ?case by auto next case (Suc j) thus ?case by (cases "t") auto qed *) lemma llength_take [simp]: "t \ A\<^sup>\ \ llength (t\i) = i" proof (induct "i" arbitrary: t) case 0 thus ?case by simp next case (Suc j) from `t \ A\<^sup>\` `\t. t \ A\<^sup>\ \ llength (t \ j) = j` show ?case by(cases) (auto simp: llength_LCons [of _ UNIV]) qed lemma ltake_ldrop_id: "(x \ i) @@ (x \ i) = x" proof (induct "i" arbitrary: x) case 0 thus ?case by simp next case (Suc j) thus ?case by (cases x) auto qed lemma ltake_ldrop: "(xs \ m) \ n =(xs \ (n + m)) \ m" proof (induct "m" arbitrary: xs) case 0 show ?case by simp next case (Suc l) thus ?case by (cases "xs") auto qed lemma ldrop_LNil [simp]: "LNil \ i = LNil" by (cases "i") auto lemma ldrop_add: "t \ (i + k) = t \ i \ k" proof (induct "i" arbitrary: t) case (Suc j) thus ?case by (cases "t") auto qed simp lemma ldrop_fun: "t \ i !! j = t!!(i + j)" proof (induct i arbitrary: t) case 0 thus ?case by simp next case (Suc k) then show ?case by (cases "t") auto qed lemma ldropT[simp]: "t \ A\<^sup>\ \ t \ i \ A\<^sup>\" proof (induct i arbitrary: t) case 0 thus ?case by simp next case (Suc j) thus ?case by (cases "t") auto qed lemma ldrop_finT[simp]: "t \ A\<^sup>\ \ t \ i \ A\<^sup>\" proof (induct i arbitrary: t) case 0 thus ?case by simp next fix n t assume "t \ A\<^sup>\" and "\t::'a llist. t \ A\<^sup>\ \ t \ n \ A\<^sup>\" thus "t \ Suc n \ A\<^sup>\" by (cases "t") auto qed lemma ldrop_infT[simp]: "t \ A\<^sup>\ \ t \ i \ A\<^sup>\" proof (induct i arbitrary: t) case 0 thus ?case by simp next case (Suc n) from `t \ A\<^sup>\` `\t. t \ A\<^sup>\ \ t \ n \ A\<^sup>\` show ?case by (cases "t") auto qed lemma lapp_suff_llength: "r \ A\<^sup>\ \ (r@@s) \ llength r = s" by (induct rule: finlsts.induct) auto lemma ltake_lappend_llength [simp]: "r \ A\<^sup>\ \ (r @@ s) \ llength r = r" by (induct rule: finlsts.induct) auto lemma ldrop_LNil_less: "\j \ i; t \ j = LNil\ \ t \ i = LNil" proof (induct i arbitrary: j t) case 0 thus ?case by auto next case (Suc n) thus ?case by (cases j, simp) (cases t, simp_all) qed lemma ldrop_inf_iffT [iff]: "(t \ i \ UNIV\<^sup>\) = (t \ UNIV\<^sup>\)" proof show "t\i \ UNIV\<^sup>\ \ t \ UNIV\<^sup>\" by (rule ccontr) (auto dest: ldrop_finT) qed auto lemma ldrop_fin_iffT [iff]: "(t \ i \ UNIV\<^sup>\) = (t \ UNIV\<^sup>\)" by auto lemma drop_nonLNil: "t\i \ LNil \ t \ LNil" by (auto) lemma llength_drop_take: "t\i \ LNil \ llength (t\i) = i" proof (induct i arbitrary: t) case 0 show ?case by simp next case (Suc j) thus ?case by (cases t) (auto simp: llength_LCons [of _ UNIV]) qed lemma fps_induct [case_names LNil LCons, induct set: fpslsts, consumes 1]: assumes fps: "l \ A\<^sup>\" and init: "\a. a \ A \ P (a##LNil)" and step: "\a l. \ l \ A\<^sup>\; P l; a \ A \ \ P (a ## l)" shows "P l" proof- from fps have "l \ A\<^sup>\" and "l \ LNil" by auto thus ?thesis by (induct, simp) (cases, auto intro: init step) qed lemma lbutlast_lapp_llast: assumes "l \ A\<^sup>\" shows "l = lbutlast l @@ (llast l ## LNil)" using prems by induct auto lemma llast_snoc [simp]: assumes fin: "xs \ A\<^sup>\" shows "llast (xs @@ x ## LNil) = x" using fin proof induct case LNil_fin thus ?case by simp next case (LCons_fin a l) have "x ## LNil \ UNIV\<^sup>\" by auto with LCons_fin show ?case by (auto simp: llast_LCons [of _ UNIV]) qed lemma lbutlast_snoc [simp]: assumes fin: "xs \ A\<^sup>\" shows "lbutlast (xs @@ x ## LNil) = xs" using fin proof induct case LNil_fin thus ?case by simp next case (LCons_fin a l) have "x ## LNil \ UNIV\<^sup>\" by auto with LCons_fin show ?case by (auto simp: lbutlast_LCons [of _ UNIV]) qed lemma llast_lappend [simp]: "\ x \ UNIV\<^sup>\; y \ UNIV\<^sup>\ \ \ llast (x @@ a ## y) = llast (a ## y)" proof (induct rule: finlsts.induct) case LNil_fin thus ?case by simp next case (LCons_fin l b) hence "l @@ a ## y \ UNIV\<^sup>\" by auto thus ?case using LCons_fin by (auto simp: llast_LCons [of _ UNIV]) qed lemma llast_llength: assumes tfin: "t \ UNIV\<^sup>\" shows "t \ LNil \ t !! (llength t - (Suc 0)) = Some (llast t)" using tfin proof induct case (LNil_fin l) thus ?case by auto next case (LCons_fin a l) note consal = this thus ?case proof (cases l) case LNil_fin thus ?thesis using consal by simp next case (LCons_fin aa la) thus ?thesis using consal by simp qed qed section{*The constant llist *} constdefs lconst :: "'a \ 'a llist" "lconst a \ iterates (\x. x) a" lemma lconst_unfold: "lconst a = a ## lconst a" by (auto simp: lconst_def intro: iterates) lemma lconst_LNil [iff]: "lconst a \ LNil" by (clarify,frule subst [OF lconst_unfold]) simp lemma lconstT: assumes aA: "a \ A" shows "lconst a \ A\<^sup>\" proof (rule inflstsI) show "lconst a \ A\<^sup>\" proof (rule alllsts.coinduct [of "\x. x = lconst a"], simp_all) have "lconst a = a ## lconst a" by (rule lconst_unfold) with aA show "\l aa. lconst a = aa ## l \ (l = lconst a \ l \ A\<^sup>\) \ aa \ A" by blast qed next assume lconst: "lconst a \ UNIV\<^sup>\" moreover have "\l. l \ UNIV\<^sup>\ \ lconst a \ l" proof- fix l::"'a llist" assume "l\UNIV\<^sup>\" thus "lconst a \ l" proof (rule finlsts_induct, simp_all) fix a' l' assume al': "lconst a \ l'" and l'A: "l' \ UNIV\<^sup>\" from al' show "lconst a \ a' ## l'" proof (rule contrapos_np) assume notal: "\ lconst a \ a' ## l'" hence "lconst a = a' ## l'" by simp hence "a ## lconst a = a' ## l'" by (rule subst [OF lconst_unfold]) thus "lconst a = l'" by auto qed qed qed ultimately show "False" using aA by auto qed section{*The prefix order of llists*} instantiation llist :: (type) order begin definition llist_le_def: "(s :: 'a llist) \ t \ (\d. t = s @@ d)" definition llist_less_def: "(s :: 'a llist) < t \ (s \ t \ s \ t)" lemma not_LCons_le_LNil [iff]: "\ (a##l) \ LNil" by (unfold llist_le_def) auto lemma LNil_le [iff]:"LNil \ s" by (auto simp: llist_le_def) lemma le_LNil [iff]: "(s \ LNil) = (s = LNil)" by (auto simp: llist_le_def) lemma llist_inf_le: "s \ A\<^sup>\ \ (s\t) = (s=t)" by (unfold llist_le_def) auto lemma le_LCons [iff]: "(x ## xs \ y ## ys) = (x = y \ xs \ ys)" by (unfold llist_le_def) auto lemma llist_le_refl [iff]: "(s:: 'a llist) \ s" by (unfold llist_le_def) (rule exI [of _ "LNil"], simp) lemma llist_le_trans [trans]: fixes r:: "'a llist" shows "r \ s \ s \ t \ r \ t" by (auto simp: llist_le_def lappend_assoc) lemma llist_le_anti_sym: fixes s:: "'a llist" assumes st: "s \ t" and ts: "t \ s" shows "s = t" proof- have "s \ UNIV\<^sup>\" by auto thus ?thesis proof (cases rule: alllstsE) case finite hence "\ t. s \ t \ t \ s \ s = t" proof (induct rule: finlsts.induct) case LNil_fin thus ?case by auto next case (LCons_fin l a) show ?case proof fix t from LCons_fin show "a ## l \ t \ t \ a ## l \ a ## l = t" by (cases "t") blast+ qed qed thus ?thesis using st ts by blast next case infinite thus ?thesis using st by (simp add: llist_inf_le) qed qed lemma llist_less_le_not_le: fixes s :: "'a llist" shows "(s < t) = (s \ t \ \ t \ s)" by (auto simp add: llist_less_def dest: llist_le_anti_sym) instance by default (assumption | rule llist_le_refl llist_le_trans llist_le_anti_sym llist_less_le_not_le)+ end subsection{*Typing rules*} lemma llist_le_finT [simp]: "r\s \ s \ A\<^sup>\ \ r \ A\<^sup>\" proof- assume rs: "r\s" and sfin: "s \ A\<^sup>\" from sfin have "\r. r\s \ r\A\<^sup>\" proof (induct "s") case LNil_fin thus ?case by auto next case (LCons_fin a l) show ?case proof (clarify) fix r assume ral: "r \ a ## l" thus "r \ A\<^sup>\" using LCons_fin by (cases r) auto qed qed with rs show ?thesis by auto qed lemma llist_less_finT [iff]: "r s \ A\<^sup>\ \ r \ A\<^sup>\" by (auto simp: less_le) subsection{*More simplification rules*} lemma LNil_less_LCons [iff]: "LNil < a ## t" by (simp add: less_le) lemma not_less_LNil [iff]: "\ r < LNil" by (auto simp: less_le) lemma less_LCons [iff]: " (a ## r < b ## t) = (a = b \ r < t)" by (auto simp: less_le) lemma llength_mono [iff]: assumes"r \ A\<^sup>\" shows "s llength s < llength r" using assms proof(induct "r" arbitrary: s) case LNil_fin thus ?case by simp next case (LCons_fin a l) thus ?case by (cases s) (auto simp: llength_LCons [of _ UNIV]) qed lemma le_lappend [iff]: "r \ r @@ s" by (auto simp: llist_le_def) lemma take_inf_less: "t \ UNIV\<^sup>\ \ t \ i < t" proof (induct i arbitrary: t) case 0 thus ?case by (auto elim: inflsts_cases) next case (Suc i) from `t \ UNIV\<^sup>\` show ?case proof (cases "t") case (LCons a l) with Suc show ?thesis by auto qed qed lemma lapp_take_less: assumes iless: "i < llength r" shows "(r @@ s) \ i < r" proof (cases "r \ UNIV\<^sup>\") case True thus ?thesis using iless proof(induct i arbitrary: r) case 0 thus ?case by (cases "r") auto next case (Suc j) from `r \ UNIV\<^sup>\` `Suc j < llength r` `\r. \r \ UNIV\<^sup>\; j < llength r\ \ lappend r s \ j < r` show ?case by (cases) auto qed next case False thus ?thesis by (simp add: take_inf_less) qed subsection{*Finite prefixes and infinite suffixes*} definition finpref :: "'a set \ 'a llist \ 'a llist set" where "finpref A s \ {r. r \ A\<^sup>\ \ r \ s}" definition suff :: "'a set \ 'a llist \ 'a llist set" where "suff A s \ {r. r \ A\<^sup>\ \ s \ r}" definition infsuff :: "'a set \ 'a llist \ 'a llist set" where "infsuff A s \ {r. r \ A\<^sup>\ \ s \ r}" definition prefix_closed :: "'a llist set \ bool" where "prefix_closed A \ \ t \ A. \ s \ t. s \ A" definition pprefix_closed :: "'a llist set \ bool" where "pprefix_closed A \ \ t \ A. \ s. s \ t \ s \ LNil \ s \ A" definition suffix_closed :: "'a llist set \ bool" where "suffix_closed A \ \ t \ A. \ s. t \ s \ s \ A" lemma finpref_LNil [simp]: "finpref A LNil = {LNil}" by (auto simp: finpref_def) lemma finpref_fin: "x \ finpref A s \ x \ A\<^sup>\" by (auto simp: finpref_def) lemma finpref_mono2: "s \ t \ finpref A s \ finpref A t" by (unfold finpref_def) (auto dest: llist_le_trans) lemma suff_LNil [simp]: "suff A LNil = A\<^sup>\" by (simp add: suff_def) lemma suff_all: "x \ suff A s \ x \ A\<^sup>\" by (auto simp: suff_def) lemma suff_mono2: "s \ t \ suff A t \ suff A s" by (unfold suff_def) (auto dest: llist_le_trans) lemma suff_appE: assumes rA: "r \ A\<^sup>\" and tsuff: "t \ suff A r" obtains s where "s \ A\<^sup>\" "t = r@@s" proof- from tsuff obtain s where tA: "t \ A\<^sup>\" and trs: "t = r @@ s" by (auto simp: suff_def llist_le_def) from rA trs tA have "s \ A\<^sup>\" by (auto simp: lapp_allT_iff) thus ?thesis using trs by (rule that) qed lemma LNil_suff [iff]: "(LNil \ suff A s) = (s = LNil)" by (auto simp: suff_def) lemma finpref_suff [dest]: "\ r \ finpref A t; t\A\<^sup>\ \ \ t \ suff A r" by (auto simp: finpref_def suff_def) lemma suff_finpref: "\ t \ suff A r; r\A\<^sup>\ \ \ r \ finpref A t" by (auto simp: finpref_def suff_def) lemma suff_finpref_iff: "\ r\A\<^sup>\; t\A\<^sup>\ \ \ (r \ finpref A t) = (t \ suff A r)" by (auto simp: finpref_def suff_def) lemma infsuff_LNil [simp]: "infsuff A LNil = A\<^sup>\" by (simp add: infsuff_def) lemma infsuff_inf: "x \ infsuff A s \ x \ A\<^sup>\" by (auto simp: infsuff_def) lemma infsuff_mono2: "s \ t \ infsuff A t \ infsuff A s" by (unfold infsuff_def) (auto dest: llist_le_trans) lemma infsuff_appE: assumes rA: "r \ A\<^sup>\" and tinfsuff: "t \ infsuff A r" obtains s where "s \ A\<^sup>\" "t = r@@s" proof- from tinfsuff obtain s where tA: "t \ A\<^sup>\" and trs: "t = r @@ s" by (auto simp: infsuff_def llist_le_def) from rA trs tA have "s \ A\<^sup>\" by (auto dest: app_invT) thus ?thesis using trs by (rule that) qed lemma finpref_infsuff [dest]: "\ r \ finpref A t; t\A\<^sup>\ \ \ t \ infsuff A r" by (auto simp: finpref_def infsuff_def) lemma infsuff_finpref: "\ t \ infsuff A r; r\A\<^sup>\ \ \ r \ finpref A t" by (auto simp: finpref_def infsuff_def) lemma infsuff_finpref_iff [iff]: "\ r\A\<^sup>\; t\A\<^sup>\ \ \ (t \ finpref A r) = (r \ infsuff A t)" by (auto simp: finpref_def infsuff_def) lemma prefix_lemma: assumes xinf: "x \ A\<^sup>\" and yinf: "y \ A\<^sup>\" and R: "\ s. \ s \ A\<^sup>\; s \ x\ \ s \ y" shows "x = y" proof- let ?r = "{(x, y). x\A\<^sup>\ \ y\A\<^sup>\ \ finpref A x \ finpref A y}" have "(x, y) \ ?r" using xinf yinf by (auto simp: finpref_def intro: R) thus ?thesis proof (coinduct rule: llist_equalityI) case (Eqllist q) then obtain a b where q: "q = (a, b)" and ainf: "a \ A\<^sup>\" and binf: "b \ A\<^sup>\" and pref: "finpref A a \ finpref A b" by auto from ainf show ?case proof cases case (LCons a' l') note acons = this with binf show ?thesis proof (cases b) case (LCons b' l'') with acons pref have "a' = b'" "finpref A l' \ finpref A l''" by (auto simp: finpref_def) thus ?thesis using acons LCons q by auto qed qed qed qed lemma inf_neqE: "\ x \ A\<^sup>\; y \ A\<^sup>\; x \ y; \s. \ s\A\<^sup>\; s \ x; \ s \ y\ \ R \ \ R" by (auto intro!: prefix_lemma) lemma pref_locally_linear: fixes s::"'a llist" assumes sx: "s \ x" and tx: "t \ x" shows "s \ t \ t \ s" proof- have "s \ UNIV\<^sup>\" by auto thus ?thesis proof (cases rule: alllstsE) case infinite with sx tx show ?thesis by (auto simp: llist_inf_le) next case finite thus ?thesis using sx tx proof (induct "s" arbitrary: x t) case LNil_fin thus ?case by simp next case (LCons_fin a l) note alx = `a ## l \ x` note tx = `t \ x` show ?case proof(rule disjCI) assume tal: "\ t \ a ## l" show "LCons a l \ t" proof (cases t) case LNil thus ?thesis using tal by auto next case (LCons b ts) note tcons = this show ?thesis proof (cases x) case LNil thus ?thesis using alx by auto next case (LCons c xs) from alx LCons have ac: "a = c" and lxs: "l \ xs" by auto from tx tcons LCons have bc: "b = c" and tsxs: "ts \ xs" by auto from tcons tal ac bc have tsl: "\ ts \ l" by auto from LCons_fin lxs tsxs tsl have "l \ ts" by auto with tcons ac bc show ?thesis by auto qed qed qed qed qed qed definition pfinpref :: "'a set \ 'a llist \ 'a llist set" where "pfinpref A s \ finpref A s - {LNil}" lemma pfinpref_iff [iff]: "(x \ pfinpref A s) = (x \ finpref A s \ x \ LNil)" by (auto simp: pfinpref_def) section{* Safety and Liveness *} definition infsafety :: "'a set \ 'a llist set \ bool" where "infsafety A P \ \ t \ A\<^sup>\. (\ r \ finpref A t. \ s \ A\<^sup>\. r @@ s \ P) \ t \ P" definition infliveness :: "'a set \ 'a llist set \ bool" where "infliveness A P \ \ t \ A\<^sup>\. \ s \ A\<^sup>\. t @@ s \ P" definition possafety :: "'a set \ 'a llist set \ bool" where "possafety A P \ \ t \ A\<^sup>\. (\ r \ pfinpref A t. \ s \ A\<^sup>\. r @@ s \ P) \ t \ P" definition posliveness :: "'a set \ 'a llist set \ bool" where "posliveness A P \ \ t \ A\<^sup>\. \ s \ A\<^sup>\. t @@ s \ P" definition safety :: "'a set \ 'a llist set \ bool" where "safety A P \ \ t \ A\<^sup>\. (\ r \ finpref A t. \ s \ A\<^sup>\. r @@ s \ P) \ t \ P" definition liveness :: "'a set \ 'a llist set \ bool" where "liveness A P \ \ t \ A\<^sup>\. \ s \ A\<^sup>\. t @@ s \ P" lemma safetyI: "(\t. \t \ A\<^sup>\; \ r \ finpref A t. \ s \ A\<^sup>\. r @@ s \ P\ \ t \ P) \ safety A P" by (unfold safety_def) blast lemma safetyD: "\ safety A P; t \ A\<^sup>\; \r. r \ finpref A t \ \ s \ A\<^sup>\. r @@ s \ P \ \ t \ P" by (unfold safety_def) blast lemma safetyE: "\ safety A P; \ t \ A\<^sup>\. (\ r \ finpref A t. \ s \ A\<^sup>\. r @@ s \ P) \ t \ P \ R \ \ R" by (unfold safety_def) blast lemma safety_prefix_closed: "safety UNIV P \ prefix_closed P" by (auto dest!: safetyD simp: prefix_closed_def finpref_def llist_le_def lappend_assoc) blast lemma livenessI: "(\s. s\ A\<^sup>\ \ \ t \ A\<^sup>\. s @@ t \ P) \ liveness A P" by (auto simp: liveness_def) lemma livenessE: "\ liveness A P; \t. \ t \ A\<^sup>\; s @@ t \ P\ \ R; s \ A\<^sup>\ \ R\ \ R" by (auto simp: liveness_def) lemma possafetyI: "(\t. \t \ A\<^sup>\; \ r \ pfinpref A t. \ s \ A\<^sup>\. r @@ s \ P\ \ t \ P) \ possafety A P" by (unfold possafety_def) blast lemma possafetyD: "\ possafety A P; t \ A\<^sup>\; \r. r \ pfinpref A t \ \ s \ A\<^sup>\. r @@ s \ P \ \ t \ P" by (unfold possafety_def) blast lemma possafetyE: "\ possafety A P; \ t \ A\<^sup>\. (\ r \ pfinpref A t. \ s \ A\<^sup>\. r @@ s \ P) \ t \ P \ R \ \ R" by (unfold possafety_def) blast lemma possafety_pprefix_closed: assumes psafety: "possafety UNIV P" shows "pprefix_closed P" unfolding pprefix_closed_def proof(intro ballI allI impI, erule conjE) fix t s assume tP: "t \ P" and st: "s \ t" and spos: "s \ LNil" from psafety show "s \ P" proof (rule possafetyD) from spos show "s \ UNIV\<^sup>\" by auto next fix r assume "r \ pfinpref UNIV s" then obtain u where scons: "s = r @@ u" by (auto simp: pfinpref_def finpref_def llist_le_def) with st obtain v where "t = r @@ u @@ v" by (auto simp: lappend_assoc llist_le_def) with tP show "\s\UNIV\<^sup>\. r @@ s \ P" by auto qed qed lemma poslivenessI: "(\s. s\ A\<^sup>\ \ \ t \ A\<^sup>\. s @@ t \ P) \ posliveness A P" by (auto simp: posliveness_def) lemma poslivenessE: "\ posliveness A P; \t. \ t \ A\<^sup>\; s @@ t \ P\ \ R; s \ A\<^sup>\ \ R\ \ R" by (auto simp: posliveness_def) end