definition LeftDerivationFix :: "sentence ==> nat ==> derivation ==> nat ==> sentence ==> bool" where "LeftDerivationFix α i D j β = (is_sentence α ∧ is_sentence β ∧ LeftDerivation α D β ∧ i < length α ∧ j < length β ∧ α ! i = β ! j ∧ (∃ E F. D = E@(derivation_shift F 0 (Suc j)) ∧ LeftDerivation (take i α) E (take j β) ∧ LeftDerivation (drop (Suc i) α) F (drop (Suc j) β)))"
definition LeftDerivationIntro :: "sentence ==> nat ==> rule ==> nat ==> derivation ==> nat ==> sentence ==> bool" where "LeftDerivationIntro α i r ix D j γ = (∃ β. LeftDerives1 α i r β ∧ ix < length (snd r) ∧ (snd r) ! ix = γ ! j ∧ LeftDerivationFix β (i + ix) D j γ)"
lemma LeftDerivationFix_empty[simp]: "is_sentence α ==> i < length α ==> LeftDerivationFix α i [] i α" apply (auto simp add: LeftDerivationFix_def) apply (rule_tac x="[]"in exI) apply auto done
lemma Derive_empty[simp]: "Derive a [] = a" by (auto simp add: Derive_def)
lemma LeftDerivation_append1: "LeftDerivation a (D@[(i, r)]) c ==>∃ b. LeftDerivation a D b ∧ LeftDerives1 b i r c" by (simp add: LeftDerivation_append)
lemma Derivation_append1: "Derivation a (D@[(i, r)]) c ==>∃ b. Derivation a D b ∧ Derives1 b i r c" by (simp add: Derivation_append)
lemma Derivation_take_derive: assumes"Derivation a D b" shows"Derivation a (take n D) (Derive a (take n D))" by (metis Derivation_append Derive append_take_drop_id assms)
lemma LeftDerivation_take_derive: assumes"LeftDerivation a D b" shows"LeftDerivation a (take n D) (Derive a (take n D))" by (metis Derive LeftDerivation_append LeftDerivation_implies_Derivation append_take_drop_id assms)
lemma Derivation_Derive_take_Derives1: assumes"N ≠ 0" assumes"N ≤ length D" assumes"Derivation a D b" assumes α: "α = Derive a (take (N - 1) D)" assumes"β = Derive a (take N D)" shows"Derives1 α (fst (D ! (N - 1))) (snd (D ! (N - 1))) β" proof - let ?D1 = "take (N - 1) D" let ?D2 = "take N D" from assms have app: "?D2 = ?D1 @ [D ! (N - 1)]" apply auto by (metis Suc_less_eq Suc_pred le_imp_less_Suc take_Suc_conv_app_nth) from assms have"Derivation a ?D2 β" using Derivation_take_derive by blast with app show ?thesis using Derivation.simps Derivation_append Derive α by auto qed
lemma LeftDerivation_Derive_take_LeftDerives1: assumes"N ≠ 0" assumes"N ≤ length D" assumes"LeftDerivation a D b" assumes α: "α = Derive a (take (N - 1) D)" assumes"β = Derive a (take N D)" shows"LeftDerives1 α (fst (D ! (N - 1))) (snd (D ! (N - 1))) β" proof - let ?D1 = "take (N - 1) D" let ?D2 = "take N D" from assms have app: "?D2 = ?D1 @ [D ! (N - 1)]" apply auto by (metis Suc_less_eq Suc_pred le_imp_less_Suc take_Suc_conv_app_nth) from assms have"LeftDerivation a ?D2 β" using LeftDerivation_take_derive by blast with app show ?thesis by (metis Derive LeftDerivation_append1 LeftDerivation_implies_Derivation α prod.collapse) qed
lemma LeftDerives1_skip_prefix: "length a ≤ i ==> LeftDerives1 (a@b) i r (a@c) ==> LeftDerives1 b (i - length a) r c" apply (auto simp add: LeftDerives1_def) using leftmost_skip_prefix apply blast by (simp add: Derives1_skip_prefix)
lemma LeftDerives1_skip_suffix: assumes i: "i < length a" assumes D: "LeftDerives1 (a@c) i r (b@c)" shows"LeftDerives1 a i r b" proof - note Derives1_def[where u="a@c"and v="b@c"and i=i and r=r] thenhave"∃x y N α. a @ c = x @ [N] @ y ∧ b @ c = x @ α @ y ∧ is_sentence x ∧ is_sentence y ∧ (N, α) ∈R∧ r = (N, α) ∧ i = length x" using D LeftDerives1_implies_Derives1 by auto thenobtain x y N α where split: "a @ c = x @ [N] @ y ∧ b @ c = x @ α @ y ∧ is_sentence x ∧ is_sentence y ∧ (N, α) ∈R∧ r = (N, α) ∧ i = length x" by blast from split have"length (a@c) = length (x @ [N] @ y)"by auto thenhave"length a + length c = length x + length y + 1"by simp with split have"length a + length c = i + length y + 1"by simp with i have len_c_y: "length c ≤ length y"by arith let ?y = "take (length y - length c) y" from split have ac: "a @ c = (x @ [N]) @ y"by auto note cancel_suffix[where a=a and c = c and b = "x@[N]"and d = "y", OF ac len_c_y] thenhave a: "a = x @ [N] @ ?y"by auto from split have bc: "b @ c = (x @ α) @ y"by auto note cancel_suffix[where a=b and c = c and b = "x@α"and d = "y", OF bc len_c_y] thenhave b: "b = x @ α @ ?y"by auto from split len_c_y a b show ?thesis apply (simp only: LeftDerives1_def Derives1_def) apply (rule_tac conjI) using D LeftDerives1_def i leftmost_cons_less apply blast apply (rule_tac x=x in exI) apply (rule_tac x="?y"in exI) apply (rule_tac x="N"in exI) apply (rule_tac x="α"in exI) apply auto by (rule is_sentence_take) qed
lemma LeftDerives1_X_is_part_of_rule[consumes 2, case_names Suffix Prefix]: assumes aXb: "LeftDerives1 δ i r (a@[X]@b)" assumes split: "splits_at δ i α N β" assumes prefix: "∧ β. δ = a @ [X] @ β ==> length a < i ==> is_word (a @ [X]) ==> LeftDerives1 β (i - length a - 1) r b ==> False" assumes suffix: "∧ α. δ = α @ [X] @ b ==> LeftDerives1 α i r a ==> False" shows"∃ u v. a = α @ u ∧ b = v @ β ∧ (snd r) = u@[X]@v" proof - have aXb_old: "Derives1 δ i r (a@[X]@b)" using LeftDerives1_implies_Derives1 aXb by blast have prefix_or: "is_prefix α a ∨ is_proper_prefix a α" by (metis Derives1_prefix split aXb_old is_prefix_eq_proper_prefix) have is_word_α: "is_word α" using LeftDerives1_splits_at_is_word aXb assms(2) by blast have"is_proper_prefix a α ==> False" proof - assume proper:"is_proper_prefix a α" thenhave"∃ u. u ≠ [] ∧ α = a@u"by (metis is_proper_prefix_def) thenobtain u where u: "u ≠ [] ∧ α = a@u"by blast note splits_at = splits_at_α[OF aXb_old split] splits_at_combine[OF split] from splits_at have α1: "α = take i δ"by blast from splits_at have α2: "α = take i (a@[X]@b)"by blast from splits_at have lenα: "length α = i"by blast with proper have lena: "length a < i" using append_eq_conv_conj drop_eq_Nil leI u by auto with is_word_α α2have is_word_aX: "is_word (a@[X])" by (simp add: is_word_terminals not_less take_Cons' u) from u α2have"a@u = take i (a@[X]@b)"by auto with lena have"u = take (i - length a) ([X]@b)"by (simp add: less_or_eq_imp_le) with lena have uX: "u = [X]@(take (i - length a - 1) b)"by (simp add: not_less take_Cons') let ?β = "(take (i - length a - 1) b) @ [N] @ β" from splits_at have f1: "δ = α @ [N] @ β"by blast with u uX have f2: "δ = a @ [X] @ ?β"by simp note skip = LeftDerives1_skip_prefix[where a = "a @ [X]"and b = "?β"and
r = r and i = i and c = b] thenhave D: "LeftDerives1 ?β (i - length a - 1) r b" using One_nat_def Suc_leI aXb append_assoc diff_diff_left f2 lena length_Cons
length_append length_append_singleton list.size(3) by fastforce note prefix[OF f2 lena is_word_aX D] thenshow"False" . qed with prefix_or have is_prefix: "is_prefix α a"by blast
from aXb have aXb': "LeftDerives1 δ i r ((a@[X])@b)"by auto thenhave aXb'_old: "Derives1 δ i r ((a@[X])@b)"by (simp add: LeftDerives1_implies_Derives1) note Derives1_suffix[OF aXb'_old split] thenhave suffix_or: "is_suffix β b ∨ is_proper_suffix b β" by (metis is_suffix_eq_proper_suffix) have"is_proper_suffix b β ==> False" proof - assume proper: "is_proper_suffix b β" thenhave"∃ u. u ≠ [] ∧ β = u@b"by (metis is_proper_suffix_def) thenobtain u where u: "u ≠ [] ∧ β = u@b"by blast note splits_at = splits_at_β[OF aXb_old split] splits_at_combine[OF split] from splits_at have β1: "β = drop (Suc i) δ"by blast from splits_at have β2: "β = drop (i + length (snd r)) (a @ [X] @ b)"by blast from splits_at have lenβ: "length β = length δ - i - 1"by blast with proper have lenb: "length b < length β"by (metis is_proper_suffix_length_cmp) from u β2have"u@b = drop (i + length (snd r)) ((a @ [X]) @ b)"by auto hence"u = drop (i + length (snd r)) (a @ [X])" by (metis drop_cancel_suffix) hence uX: "u = drop (i + length (snd r)) a @ [X]"by (metis drop_keep_last u) let ?α = "α @ [N] @ (drop (i + length (snd r)) a)" from splits_at have f1: "δ = α @ [N] @ β"by blast with u uX have f2: "δ = ?α @ [X] @ b"by simp note skip = LeftDerives1_skip_suffix[where a = "?α"and c = "[X]@b"and b="a"and
r = r and i = i] have f3: "i < length (α @ [N] @ drop (i + length (snd r)) a)" proof - have f1: "1 + i + length b = length [X] + length b + i" by (metis Groups.add_ac(2) Suc_eq_plus1_left length_Cons list.size(3) list.size(4) semiring_normalization_rules(22)) have f2: "length δ - i - 1 = length ((α @ [N] @ drop (i + length (snd r)) a) @ [X] @ b) - Suc i" by (metis f2 length_drop splits_at(1)) have"length ([]::symbol list) ≠ length δ - i - 1 - length b" by (metis add_diff_cancel_right' append_Nil2 append_eq_append_conv lenβ length_append u) thenhave"length ([]::symbol list) ≠ length α + length ([N] @ drop (i + length (snd r)) a) - i" using f2 f1 by (metis Suc_eq_plus1_left add_diff_cancel_right' diff_diff_left length_append) thenshow ?thesis by auto qed from aXb f2 have D: "LeftDerives1 (?α @ [X] @ b) i r (a@[X]@b)"by auto note skip[OF f3 D] note suffix[OF f2 skip[OF f3 D]] thenshow"False" . qed with suffix_or have is_suffix: "is_suffix β b"by blast
from is_prefix have"∃ u. a = α @ u"by (auto simp add: is_prefix_def) thenobtain u where u: "a = α @ u"by blast from is_suffix have"∃ v. b = v @ β"by (auto simp add: is_suffix_def) thenobtain v where v: "b = v @ β"by blast
from u v splits_at_combine[OF split] aXb have D:"LeftDerives1 (α@[N]@β) i r (α@(u@[X]@v)@β)" by simp from splits_at_α[OF aXb_old split] have i: "length α = i"by blast from i have i1: "length α ≤ i"and i2: "i ≤ length α"by auto note LeftDerives1_skip_suffix[OF _ LeftDerives1_skip_prefix[OF i1 D], simplified, OF i2] thenhave"LeftDerives1 [N] 0 r (u @ [X] @ v)"by auto thenhave"Derives1 [N] 0 r (u @ [X] @ v)" using LeftDerives1_implies_Derives1 by auto thenhave r: "snd r = u @ [X] @ v" by (metis Derives1_split append_Cons append_Nil length_0_conv list.inject self_append_conv) show ?thesis using u v r by auto qed
lemma LeftDerivationFix_grow_suffix: assumes LDF: "LeftDerivationFix (b1@[X]@b2) (length b1) D j c" assumes suffix_b2: "LeftDerives1 suffix e r b2" assumes is_word_b1X: "is_word (b1@[X])" shows"LeftDerivationFix (b1@[X]@suffix) (length b1) ((e + length (b1@[X]), r)#D) j c" proof - from LDF have LDF': "is_sentence (b1@[X]@b2) ∧ is_sentence c ∧ LeftDerivation (b1 @ [X] @ b2) D c ∧ length b1 < length (b1 @ [X] @ b2) ∧ j < length c ∧ (b1 @ [X] @ b2) ! length b1 = c ! j ∧ (∃E F. D = E @ derivation_shift F 0 (Suc j) ∧ LeftDerivation (take (length b1) (b1 @ [X] @ b2)) E (take j c) ∧ LeftDerivation (drop (Suc (length b1)) (b1 @ [X] @ b2)) F (drop (Suc j) c))" using LeftDerivationFix_def by blast thenobtain E F where EF: "D = E @ derivation_shift F 0 (Suc j) ∧ LeftDerivation (take (length b1) (b1 @ [X] @ b2)) E (take j c) ∧ LeftDerivation (drop (Suc (length b1)) (b1 @ [X] @ b2)) F (drop (Suc j) c)"by blast thenhave LD_b1_c: "LeftDerivation b1 E (take j c)"by simp with is_word_b1X have E: "E = []" using LeftDerivation_implies_Derivation is_word_Derivation is_word_append by blast thenhave b1_def: "b1 = take j c"using LD_b1_c by auto thenhave b1_len: "j = length b1" by (simp add: LDF' dual_order.strict_implies_order min.absorb2) have D: "D = derivation_shift F 0 (Suc j)"using EF E by simp have step: "LeftDerives1 (b1 @ [X] @ suffix) (Suc (e + length b1)) r (b1 @ [X] @ b2) ∧ LeftDerivation (b1 @ [X] @ b2) D c" by (metis LDF' LeftDerives1_append_prefix add_Suc_right append_assoc assms(2) is_word_b1X
length_append_singleton) thenhave is_sentence_b1Xsuffix: "is_sentence (b1 @ [X] @ suffix)" using Derives1_sentence1 LeftDerives1_implies_Derives1 by blast have X_eq_cj: "X = c ! j"using LDF' by auto show ?thesis apply (simp add: LeftDerivationFix_def) apply (rule conjI) using is_sentence_b1Xsuffix apply simp apply (rule conjI) using LDF' apply simp apply (rule conjI) using step apply force apply (rule conjI) using LDF' apply simp apply (rule conjI) apply (rule X_eq_cj) apply (rule_tac x="[]"in exI) apply (rule_tac x="(e, r)#F"in exI) apply auto apply (rule b1_len[symmetric]) apply (rule D) apply (rule b1_def) apply (rule_tac x="b2"in exI) apply (simp add: suffix_b2) using EF by auto qed
lemma Derives1_append_suffix: assumes Derives1: "Derives1 v i r w" assumes u: "is_sentence u" shows"Derives1 (v@u) i r (w@u)" proof - have"∃ α N β. splits_at v i α N β"using assms splits_at_ex by auto thenobtain α N β where split_v: "splits_at v i α N β"by blast have split_w: "w = α@(snd r)@β"using assms split_v splits_at_combine_dest by blast have split_uv: "splits_at (v@u) i α N (β@u)" by (simp add: split_v splits_at_append) have is_sentence_uv: "is_sentence (v@u)" using Derives1 Derives1_sentence1 is_sentence_concat u by blast show ?thesis by (metis Derives1 Derives1_nonterminal Derives1_rule append_assoc is_sentence_uv
split_uv split_v split_w splits_at_implies_Derives1) qed
lemma leftmost_append_suffix: "leftmost i v ==> leftmost i (v@u)" by (simp add: leftmost_def nth_append)
lemma LeftDerives1_append_suffix: assumes Derives1: "LeftDerives1 v i r w" assumes u: "is_sentence u" shows"LeftDerives1 (v@u) i r (w@u)" proof - have1: "Derives1 v i r w" by (simp add: Derives1 LeftDerives1_implies_Derives1) have2: "leftmost i v" using Derives1 LeftDerives1_def by blast have3: "is_sentence u"using u by fastforce have4: "Derives1 (v@u) i r (w@u)" by (simp add: "1""3" Derives1_append_suffix) have5: "leftmost i (v@u)" by (simp add: "2" leftmost_append_suffix u) show ?thesis by (simp add: "4""5" LeftDerives1_def) qed
lemma LeftDerivationFix_is_sentence: "LeftDerivationFix a i D j b ==> is_sentence a ∧ is_sentence b" using LeftDerivationFix_def by blast
lemma LeftDerivationIntro_is_sentence: "LeftDerivationIntro α i r ix D j γ ==> is_sentence α ∧ is_sentence γ" by (meson Derives1_sentence1 LeftDerivationFix_is_sentence LeftDerivationIntro_def
LeftDerives1_implies_Derives1)
lemma LeftDerivationFix_grow_prefix: assumes LDF: "LeftDerivationFix (b1@[X]@b2) (length b1) D j c" assumes prefix_b1: "LeftDerives1 prefix e r b1" shows"LeftDerivationFix (prefix@[X]@b2) (length prefix) ((e, r)#D) j c" proof - from LDF have LDF': "LeftDerivation (b1 @ [X] @ b2) D c ∧ length b1 < length (b1 @ [X] @ b2) ∧ j < length c ∧ (b1 @ [X] @ b2) ! length b1 = c ! j ∧ (∃E F. D = E @ derivation_shift F 0 (Suc j) ∧ LeftDerivation (take (length b1) (b1 @ [X] @ b2)) E (take j c) ∧ LeftDerivation (drop (Suc (length b1)) (b1 @ [X] @ b2)) F (drop (Suc j) c))" using LeftDerivationFix_def by blast thenobtain E F where EF: "D = E @ derivation_shift F 0 (Suc j) ∧ LeftDerivation (take (length b1) (b1 @ [X] @ b2)) E (take j c) ∧ LeftDerivation (drop (Suc (length b1)) (b1 @ [X] @ b2)) F (drop (Suc j) c)"by blast thenhave E_b1_c: "LeftDerivation b1 E (take j c)"by simp with EF have F_b2_c: "LeftDerivation b2 F (drop (Suc j) c)"by simp have step: "LeftDerives1 (prefix @ [X] @ b2) e r (b1 @ [X] @ b2)" using LDF LeftDerivationFix_is_sentence LeftDerives1_append_suffix
is_sentence_concat prefix_b1 by blast show ?thesis apply (simp add: LeftDerivationFix_def) apply (rule conjI) apply (metis Derives1_sentence1 LDF LeftDerivationFix_def LeftDerives1_implies_Derives1
is_sentence_concat is_sentence_cons prefix_b1) apply (rule conjI) using LDF LeftDerivationFix_is_sentence apply blast apply (rule conjI) apply (rule_tac x="b1@[X]@b2"in exI) using step apply simp using LDF' apply auto[1] apply (rule conjI) using LDF' apply simp apply (rule conjI) using LDF' apply auto[1] apply (rule_tac x="(e,r)#E"in exI) apply (rule_tac x="F"in exI) apply (auto simp add: EF F_b2_c) apply (rule_tac x="b1"in exI) apply (simp add: prefix_b1 E_b1_c) done qed
lemma LeftDerivationFixOrIntro: "LeftDerivation a D γ ==> is_sentence γ ==> j < length γ ==> (∃ i. LeftDerivationFix a i D j γ) ∨ (∃ d α ix. d < length D ∧ LeftDerivation a (take d D) α ∧ LeftDerivationIntro α (fst (D ! d)) (snd (D ! d)) ix (drop (Suc d) D) j γ)" proof (induct "length D" arbitrary: a D γ j rule: less_induct) (* The induction here is unnecessary, but we use it anyway for context reasons *) case less have"length D = 0 ∨ length D ≠ 0"by blast thenshow ?case proof (induct rule: disjCases2) case1 thenhave D: "D = []"by auto with less have"∃i. LeftDerivationFix a i D j γ" apply (rule_tac x=j in exI) by auto thenshow ?caseby blast next case2 note less2 = 2 have"∃ n β i. n ≤ length D ∧ β = Derive a (take n D) ∧ LeftDerivationFix β i (drop n D) j γ" apply (rule_tac x="length D"in exI) apply auto using Derive LeftDerivationFix_empty LeftDerivation_implies_Derivation less by blast thenshow ?case proof (induct rule: ex_minimal_witness) case (Minimal N) thenobtain β i where Minimal_N: "N ≤ length D ∧ β = Derive a (take N D) ∧ LeftDerivationFix β i (drop N D) j γ"by blast have"N = 0 ∨ N ≠ 0"by blast thenshow ?case proof (induct rule: disjCases2) case1 with Minimal_N have"β = a"by auto with1 Minimal_N show ?case apply (rule_tac disjI1) by auto next case2 let ?δ = "Derive a (take (N - 1) D)" have LeftDerives1_δ: "LeftDerives1 ?δ (fst (D ! (N - 1))) (snd (D ! (N - 1))) β" using"2.hyps" LeftDerivation_Derive_take_LeftDerives1 Minimal_N less.prems(1) by blast thenhave Derives1_δ: "Derives1 ?δ (fst (D ! (N - 1))) (snd (D ! (N - 1))) β" using LeftDerives1_implies_Derives1 by blast have i_len: "i < length β"using Minimal_N by (auto simp add: LeftDerivationFix_def) thenhave"∃ X β_1 β_2. splits_at β i β_1 X β_2" using splits_at_def by blast thenobtain X β_1 β_2where β_split: "splits_at β i β_1 X β_2"by blast thenhave β_combine: "β = β_1 @ [X] @ β_2"using splits_at_combine by blast thenhave LeftDerives1_δ_hyp: "LeftDerives1 ?δ (fst (D ! (N - 1))) (snd (D ! (N - 1))) (β_1 @ [X] @ β_2)" using LeftDerives1_δ by blast from β_split have i_def: "i = length β_1" by (simp add: dual_order.strict_implies_order min.absorb2 splits_at_def) have"∃ Y δ_1 δ_2. splits_at ?δ (fst (D ! (N - 1))) δ_1 Y δ_2" using Derives1_δ splits_at_ex by blast thenobtain Y δ_1 δ_2where δ_split: "splits_at ?δ (fst (D ! (N - 1))) δ_1 Y δ_2"by blast have NFix: "LeftDerivationFix (β_1 @ [X] @ β_2) (length β_1) (drop N D) j γ" using Minimal_N β_combine i_def by auto from LeftDerives1_δ_hyp δ_split have"∃u v. β_1 = δ_1 @ u ∧ β_2 = v @ δ_2 ∧ snd (snd (D ! (N - 1))) = u @ [X] @ v" proof (induct rule: LeftDerives1_X_is_part_of_rule) case (Suffix suffix) let ?k = "N - 1" let ?β = "Derive a (take ?k D)" let ?i = "length β_1" have k_less: "?k < length D"using"2.hyps" Minimal_N by linarith thenhave k_leq: "?k ≤ length D"by auto have drop_k_d: "drop ?k D = (D ! (N - 1))#(drop N D)" using"2.hyps" Cons_nth_drop_Suc k_less by fastforce from LeftDerivationFix_grow_suffix[OF NFix Suffix(4) Suffix(3)] Suffix(1) Suffix(2) 2 have"LeftDerivationFix ?β ?i (drop ?k D) j γ" apply auto by (metis One_nat_def drop_k_d) with Minimal(2)[where k="?k"] show"False" using"2.hyps" k_leq by auto next case (Prefix prefix) have collapse: "(fst (D ! (N - 1)), snd (D ! (N - 1))) # drop N D = drop (N - 1) D" by (metis "2.hyps" Cons_nth_drop_Suc Minimal_N Suc_diff_1 neq0_conv not_less
not_less_eq prod.collapse) from LeftDerivationFix_grow_prefix[OF NFix Prefix(2)] Prefix(1) collapse have"LeftDerivationFix ?δ (length prefix) (drop (N - 1) D) j γ"by auto with Minimal(2)[where k = "N - 1"] show"False" by (metis Minimal_N collapse diff_le_self le_neq_implies_less less_imp_diff_less
less_or_eq_imp_le not_Cons_self2) qed thenobtain u v where uv: "β_1 = δ_1 @ u ∧ β_2 = v @ δ_2 ∧ snd (snd (D ! (N - 1))) = u @ [X] @ v"by blast have X_1: "snd (snd (D ! (N - Suc 0))) ! length u = X"using uv by auto have X_2: "γ ! j = X"using LeftDerivationFix_def NFix by auto show ?case apply (rule disjI2) apply (rule_tac x="N - 1"in exI) apply (rule_tac x="?δ"in exI) apply (rule_tac x="length u"in exI) apply (rule conjI) using Minimal_N less2 apply linarith apply (rule conjI) using LeftDerivation_take_derive less.prems(1) apply blast apply (subst LeftDerivationIntro_def) apply (rule_tac x=β in exI) apply auto using LeftDerives1_δ One_nat_def apply presburger using uv apply auto[1] using X_1 X_2 apply auto[1] by (metis (no_types, lifting) "2.hyps" Derives1_δ Derives1_split Minimal_N One_nat_def
Suc_diff_1 δ_split append_eq_conv_conj i_def length_append neq0_conv splits_at_def uv) qed qed qed qed
definition ladder_j :: "ladder ==> nat ==> nat"where "ladder_j L index = deriv_j (L ! index)"
definition ladder_i :: "ladder ==> nat ==> nat"where "ladder_i L index = (if index = 0 then deriv_i (hd L) else ladder_j L (index - 1))"
definition ladder_n :: "ladder ==> nat ==> nat"where "ladder_n L index = deriv_n (L ! index)"
definition ladder_prev_n :: "ladder ==> nat ==> nat"where "ladder_prev_n L index = (if index = 0 then 0 else (ladder_n L (index - 1)))"
definition ladder_ix :: "ladder ==> nat ==> nat"where "ladder_ix L index = (if index = 0 then undefined else deriv_ix (L ! index))"
definition ladder_last_j :: "ladder ==> nat"where "ladder_last_j L = ladder_j L (length L - 1)"
definition ladder_last_n :: "ladder ==> nat"where "ladder_last_n L = ladder_n L (length L - 1)"
definition is_ladder :: "derivation ==> ladder ==> bool"where "is_ladder D L = (L ≠ [] ∧ (∀ u. u < length L ⟶ ladder_n L u ≤ length D) ∧ (∀ u v. u < v ∧ v < length L ⟶ ladder_n L u < ladder_n L v) ∧ ladder_last_n L = length D)"
definition ladder_γ :: "sentence ==> derivation ==> ladder ==> nat ==> sentence"where "ladder_γ a D L index = Derive a (take (ladder_n L index) D)"
definition ladder_α :: "sentence ==> derivation ==> ladder ==> nat ==> sentence"where "ladder_α a D L index = (if index = 0 then a else ladder_γ a D L (index - 1))"
definition LeftDerivationIntrosAt :: "sentence ==> derivation ==> ladder ==> nat ==> bool"where "LeftDerivationIntrosAt a D L index = ( let α = ladder_α a D L index in let i = ladder_i L index in let j = ladder_j L index in let ix = ladder_ix L index in let γ = ladder_γ a D L index in let n = ladder_n L (index - 1) in let m = ladder_n L index in let e = D ! n in let E = drop (Suc n) (take m D) in i = fst e ∧ LeftDerivationIntro α i (snd e) ix E j γ)"
definition LeftDerivationIntros :: "sentence ==> derivation ==> ladder ==> bool"where "LeftDerivationIntros a D L = ( ∀ index. 1 ≤ index ∧ index < length L ⟶ LeftDerivationIntrosAt a D L index)"
definition LeftDerivationLadder :: "sentence ==> derivation ==> ladder ==> sentence==> bool"where "LeftDerivationLadder a D L b = ( LeftDerivation a D b ∧ is_ladder D L ∧ LeftDerivationFix a (ladder_i L 0) (take (ladder_n L 0) D) (ladder_j L 0) (ladder_γ a D L 0) ∧ LeftDerivationIntros a D L)"
definition mk_deriv_fix :: "nat ==> nat ==> nat ==> deriv"where "mk_deriv_fix i n j = (n, j, i)"
definition mk_deriv_intro :: "nat ==> nat ==> nat ==> deriv"where "mk_deriv_intro ix n j = (n, j, ix)"
lemma mk_deriv_fix_i[simp]: "deriv_i (mk_deriv_fix i n j) = i" by (simp add: deriv_i_def mk_deriv_fix_def)
lemma mk_deriv_fix_j[simp]: "deriv_j (mk_deriv_fix i n j) = j" by (simp add: deriv_j_def mk_deriv_fix_def)
lemma mk_deriv_fix_n[simp]: "deriv_n (mk_deriv_fix i n j) = n" by (simp add: deriv_n_def mk_deriv_fix_def)
lemma mk_deriv_intro_i[simp]: "deriv_i (mk_deriv_intro i n j) = i" by (simp add: deriv_i_def mk_deriv_intro_def)
lemma mk_deriv_intro_ix[simp]: "deriv_ix (mk_deriv_intro ix n j) = ix" by (simp add: deriv_ix_def mk_deriv_intro_def)
lemma mk_deriv_intro_j[simp]: "deriv_j (mk_deriv_intro i n j) = j" by (simp add: deriv_j_def mk_deriv_intro_def)
lemma mk_deriv_intro_n[simp]: "deriv_n (mk_deriv_intro i n j) = n" by (simp add: deriv_n_def mk_deriv_intro_def)
lemma LeftDerivationFix_implies_ex_ladder: "LeftDerivationFix a i D j γ ==>∃ L. LeftDerivationLadder a D L γ ∧ ladder_last_j L = j ∧ ladder_last_n L = length D" apply (rule_tac x="[mk_deriv_fix i (length D) j]"in exI) apply (auto simp add: LeftDerivationLadder_def) apply (simp add: LeftDerivationFix_def) apply (simp add: is_ladder_def) apply (auto simp add: ladder_i_def ladder_j_def ladder_n_def ladder_γ_def) apply (simp add: ladder_last_n_def ladder_n_def) using Derive LeftDerivationFix_def LeftDerivation_implies_Derivation apply blast apply (simp add: LeftDerivationIntros_def) apply (simp add: ladder_last_j_def ladder_j_def) apply (simp add: ladder_last_n_def ladder_n_def) done
lemma trivP[case_names prems]: "P ==> P"by blast
lemma LeftDerivationLadder_ladder_n_bound: assumes"LeftDerivationLadder a D L b" assumes"index < length L" shows"ladder_n L index ≤ length D" using LeftDerivationLadder_def assms(1) assms(2) is_ladder_def by blast
lemma LeftDerivationLadder_deriv_n_bound: assumes"LeftDerivationLadder a D L b" assumes"index < length L" shows"deriv_n (L ! index) ≤ length D" using LeftDerivationLadder_def assms(1) assms(2) is_ladder_def ladder_n_def by auto
lemma ladder_n_simp1[simp]: "u < length L ==> ladder_n (L@L') u = ladder_n L u" by (simp add: ladder_n_def)
lemma ladder_γ_simp1[simp]: "u < length L ==> ladder_γ a D (L@L') u = ladder_γ a D L u" by (simp add: ladder_γ_def)
lemma ladder_γ_simp2[simp]: "u < length L ==> is_ladder D L ==> ladder_γ a (D@D') L u = ladder_γ a D L u" by (simp add: is_ladder_def ladder_γ_def)
lemma ladder_α_simp1[simp]: "u < length L ==> ladder_α a D (L@L') u = ladder_α a D L u" by (simp add: ladder_α_def)
lemma ladder_α_simp2[simp]: "u < length L ==> is_ladder D L ==> ladder_α a (D@D') L u = ladder_α a D L u" by (simp add: is_ladder_def ladder_α_def)
lemma ladder_n_minus_1_bound: "is_ladder D L ==> index ≥ 1 ==> index < length L ==> ladder_n L (index - Suc 0) < length D" by (metis (no_types, lifting) One_nat_def Suc_diff_1 Suc_le_lessD dual_order.strict_implies_order
is_ladder_def le_neq_implies_less not_less)
lemma LeftDerivationIntrosAt_ignore_appendix: assumes is_ladder: "is_ladder D L" assumes hyp: "LeftDerivationIntrosAt a D L index" assumes index_ge: "index ≥ 1" assumes index_less: "index < length L" shows"LeftDerivationIntrosAt a (D @ D') (L @ L') index" proof - have index_minus_1: "index - Suc 0 < length L" using index_less by arith have is_0: "ladder_n L index - length D = 0" using index_less is_ladder is_ladder_def by auto from index_ge index_less show ?thesis apply (simp add: LeftDerivationIntrosAt_def Let_def) apply (simp add: index_minus_1 is_ladder ladder_n_minus_1_bound is_0) using hyp apply (auto simp add: LeftDerivationIntrosAt_def Let_def) done qed
lemma ladder_last_n_intro: "L ≠ [] ==> ladder_n L (length L - Suc 0) = ladder_last_n L" by (simp add: ladder_last_n_def)
lemma is_ladder_not_empty: "is_ladder D L ==> L ≠ []" using is_ladder_def by blast
lemma last_ladder_γ: assumes is_ladder: "is_ladder D L" assumes ladder_last_n: "ladder_last_n L = length D" shows"ladder_γ a D L (length L - Suc 0) = Derive a D" proof - from is_ladder is_ladder_not_empty have"L ≠ []"by blast thenshow ?thesis by (simp add: ladder_γ_def ladder_last_n_intro ladder_last_n) qed
lemma ladder_α_full: assumes is_ladder: "is_ladder D L" assumes ladder_last_n: "ladder_last_n L = length D" shows"ladder_α a (D @ D') (L @ L') (length L) = Derive a D" proof - from is_ladder have L_not_empty: "L ≠ []"by (simp add: is_ladder_def) with is_ladder ladder_last_n show ?thesis apply (simp add: ladder_α_def) apply (simp add: last_ladder_γ) done qed
lemma LeftDerivationIntro_implies_LeftDerivation: "LeftDerivationIntro α i r ix D j γ ==> LeftDerivation α ((i,r)#D) γ" using LeftDerivationFix_def LeftDerivationIntro_def by auto
lemma LeftDerivationLadder_grow: "LeftDerivationLadder a D L α ==> ladder_last_j L = i ==> LeftDerivationIntro α i r ix E j γ ==> LeftDerivationLadder a (D@[(i, r)]@E) (L@[mk_deriv_intro ix (Suc(length D + length E)) j]) γ" proof (induct arbitrary: a D L α i r ix E j γ rule: trivP) case prems
{ fix u :: nat assume"u < Suc (length L)" thenhave"u < length L ∨ u = length L"by arith thenhave"ladder_n (L @ [mk_deriv_intro ix (Suc (length D + length E)) j]) u ≤ Suc (length D + length E)" proof (induct rule: disjCases2) case1 thenshow ?case apply simp by (meson LeftDerivationLadder_ladder_n_bound le_Suc_eq le_add1 le_trans prems(1)) next case2 thenshow ?case by (simp add: ladder_n_def) qed
} note ladder_n_ineqs = this
{ fix u :: nat fix v :: nat assume u_less_v: "u < v" assume"v < Suc (length L)" thenhave"v < length L ∨ v = length L"by arith thenhave"ladder_n (L @ [mk_deriv_intro ix (Suc (length D + length E)) j]) u < ladder_n (L @ [mk_deriv_intro ix (Suc (length D + length E)) j]) v" proof (induct rule: disjCases2) case1 with u_less_v have u_bound: "u < length L"by arith show ?caseusing1 u_bound apply simp using prems u_less_v LeftDerivationLadder_def is_ladder_def by auto next case2 with u_less_v have u_bound: "u < length L"by arith have"deriv_n (L ! u) ≤ length D" using LeftDerivationLadder_deriv_n_bound prems(1) u_bound by blast thenshow ?case apply (simp add: u_bound) apply (simp add: ladder_n_def 2) done qed
} note ladder_n_ineqs = ladder_n_ineqs this have is_ladder: "is_ladder (D @ (i, r) # E) (L @ [mk_deriv_intro ix (Suc (length D + length E)) j])" apply (auto simp add: is_ladder_def) using ladder_n_ineqs apply auto apply (simp add: ladder_last_n_def) done have is_ladder_L: "is_ladder D L" using LeftDerivationLadder_def prems.prems(1) by blast have ladder_last_n_eq_length: "ladder_last_n L = length D" using is_ladder_L is_ladder_def by blast have L_not_empty: "L ≠ []" using LeftDerivationLadder_def is_ladder_def prems(1) by blast
{ fix index :: nat assume index_ge: "Suc 0 ≤ index" assume"index < Suc (length L)" thenhave"index < length L ∨ index = length L"by arith thenhave"LeftDerivationIntrosAt a (D @ (i, r) # E) (L @ [mk_deriv_intro ix (Suc (length D + length E)) j]) index" proof (induct rule: disjCases2) case1 thenshow ?case using LeftDerivationIntrosAt_ignore_appendix
LeftDerivationIntros_def LeftDerivationLadder_def One_nat_def
index_ge prems.prems(1) by presburger next case2 have min_simp: "∧ n E. min n (Suc (n + length E)) = n" by auto with2 prems is_ladder_L ladder_last_n_eq_length show ?case apply (simp add: LeftDerivationIntrosAt_def) apply (simp add: L_not_empty ladder_i_eq_last_j ladder_last_n_intro) apply (simp add: ladder_α_full min_simp) apply (simp add: ladder_γ_def) by (metis Derive LeftDerivationIntro_implies_LeftDerivation LeftDerivationLadder_def
LeftDerivation_implies_Derivation LeftDerivation_implies_append) qed
} thenshow ?case apply (auto simp add: LeftDerivationLadder_def) using prems apply (auto simp add: LeftDerivationLadder_def)[1] using LeftDerivationFix_def LeftDerivationIntro_def LeftDerivation_append apply auto[1] using is_ladder apply simp using L_not_empty apply simp using LeftDerivationLadder_def LeftDerivationLadder_ladder_n_bound ladder_γ_def
prems.prems(1) apply auto[1] apply (subst LeftDerivationIntros_def) apply auto done qed
lemma LeftDerivationIntro_bounds_ij: "LeftDerivationIntro α i r ix D j β ==> i < length α ∧ j < length β" by (meson Derives1_bound LeftDerivationFix_def LeftDerivationIntro_def
LeftDerives1_implies_Derives1)
theorem LeftDerivationLadder_exists: "LeftDerivation a D γ ==> is_sentence γ ==> j < length γ ==> ∃ L. LeftDerivationLadder a D L γ ∧ ladder_last_j L = j" proof (induct "length D" arbitrary: a D γ j rule: less_induct) case less from LeftDerivationFixOrIntro[OF less(2,3,4)] show ?case proof (induct rule: disjCases2) case1 thenobtain i where"LeftDerivationFix a i D j γ"by blast show ?case using"1.hyps" LeftDerivationFix_implies_ex_ladder by blast next case2 thenobtain d α ix where inductrule: "d < length D ∧ LeftDerivation a (take d D) α ∧ LeftDerivationIntro α (fst (D ! d)) (snd (D ! d)) ix (drop (Suc d) D) j γ"by blast thenhave less_length_D: "length (take d D) < length D" and LeftDerivation_α: "LeftDerivation a (take d D) α"by auto have is_sentence_α: "is_sentence α"using LeftDerivationIntro_is_sentence inductrule by blast have"fst (D ! d) < length α"using LeftDerivationIntro_bounds_ij inductrule by blast from less(1)[OF less_length_D LeftDerivation_α is_sentence_α, where j=" fst (D ! d)", OF this] obtain L where induct_Ladder: "LeftDerivationLadder a (take d D) L α"and induct_last: "ladder_last_j L = fst (D ! d)" by blast have induct_intro: "LeftDerivationIntro α (fst (D ! d)) (snd (D ! d)) ix (drop (Suc d) D) j γ" using inductrule by blast have"d < length D"using inductrule by blast thenhave simp_to_D: "take d D @ D ! d # drop (Suc d) D = D" using id_take_nth_drop by force from LeftDerivationLadder_grow[OF induct_Ladder induct_last induct_intro] simp_to_D show ?case apply auto apply (rule_tac x= "L @ [mk_deriv_intro ix (Suc (min (length D) d + (length D - Suc d))) j]"in exI) apply (simp add: ladder_last_j_def) done qed qed
lemma LeftDerivationLadder_L_0: assumes"LeftDerivationLadder α D L β" assumes"length L = 1" shows"∃ i. LeftDerivationFix α i D (ladder_last_j L) β" proof - have"is_ladder D L"using assms by (auto simp add: LeftDerivationLadder_def) thenhave ladder_n: "ladder_n L 0 = length D" by (simp add: assms(2) is_ladder_def ladder_last_n_def) show ?thesis apply (rule_tac x = "ladder_i L 0"in exI) using assms(1) apply (auto simp add: LeftDerivationLadder_def) by (metis Derive LeftDerivationFix_def LeftDerivation_implies_Derivation One_nat_def assms(2)
diff_Suc_1 ladder_last_j_def ladder_n order_refl take_all) qed
lemma LeftDerivationFix_splits_at_derives: assumes"LeftDerivationFix a i D j b" shows"∃ U a1 a2 b1 b2. splits_at a i a1 U a2 ∧ splits_at b j b1 U b2 ∧ derives a1 b1 ∧ derives a2 b2" proof - note hyp = LeftDerivationFix_def[where α=a and β=b and D=D and i=i and j=j] from hyp obtain E F where EF: "D = E @ derivation_shift F 0 (Suc j) ∧ LeftDerivation (take i a) E (take j b) ∧ LeftDerivation (drop (Suc i) a) F (drop (Suc j) b)" using assms by blast show ?thesis apply (rule_tac x="a ! i"in exI) apply (rule_tac x="take i a"in exI) apply (rule_tac x="drop (Suc i) a"in exI) apply (rule_tac x="take j b"in exI) apply (rule_tac x="drop (Suc j) b"in exI) using Derivation_implies_derives LeftDerivation_implies_Derivation assms hyp
splits_at_def by blast qed
lemma LeftDerivation_append_suffix: "LeftDerivation a D b ==> is_sentence c ==> LeftDerivation (a@c) D (b@c)" proof (induct D arbitrary: a b c) case Nil thenshow ?caseby auto next case (Cons d D) thenshow ?case apply auto apply (rule_tac x="x@c"in exI) apply auto using LeftDerives1_append_suffix by simp qed
lemma LeftDerivation_impossible: "LeftDerivation a D b ==> i < length a ==> is_nonterminal (a ! i) ==> derivation_ge D (Suc i) ==> D = []" proof (induct D) case Nil thenshow ?caseby auto next case (Cons d D) thenhave lm: "∧ j. leftmost j a ==> j ≤ i" by (metis Derives1_sentence1 LeftDerivation.simps(2) LeftDerives1_implies_Derives1
leftmost_exists leftmost_unique) from Cons show ?case apply auto apply (auto simp add: derivation_ge_def LeftDerives1_def) using lm[where j="fst d"] by arith qed
lemma LeftDerivationFix_splits_at_nonterminal: assumes"LeftDerivationFix a i D j b" assumes"is_nonterminal (a ! i)" shows"∃ U a1 a2 b1. splits_at a i a1 U a2 ∧ splits_at b j b1 U a2 ∧ LeftDerivation a1 D b1" proof - note hyp = LeftDerivationFix_def[where α=a and β=b and D=D and i=i and j=j] from hyp obtain E F where EF: "D = E @ derivation_shift F 0 (Suc j) ∧ LeftDerivation (take i a) E (take j b) ∧ LeftDerivation (drop (Suc i) a) F (drop (Suc j) b)" using assms by blast have"∃ β. LeftDerivation a E β ∧ LeftDerivation β (derivation_shift F 0 (Suc j)) b" using EF LeftDerivation_append assms(1) hyp by blast thenobtain β where β_intro: "LeftDerivation a E β ∧ LeftDerivation β (derivation_shift F 0 (Suc j)) b"by blast have"LeftDerivation ((take i a)@(drop i a)) E ((take j b)@(drop i a))" by (metis EF LeftDerivation_append_suffix append_take_drop_id assms(1) hyp is_sentence_concat) thenhave"LeftDerivation a E ((take j b)@(drop i a))"by simp thenhave β_decomposed: "β = (take j b)@(drop i a)" using Derivation_unique_dest LeftDerivation_implies_Derivation β_intro by blast thenhave"β ! j = a ! i" by (metis Cons_nth_drop_Suc assms(1) hyp length_take min.absorb2 nth_append_length
order.strict_implies_order) thenhave is_nt: "is_nonterminal (β ! j)"by (simp add: assms(2)) have index_j: "j < length β"using β_decomposed assms(1) hyp by auto have derivation: "LeftDerivation β (derivation_shift F 0 (Suc j)) b" by (simp add: β_intro) from LeftDerivation_impossible[OF derivation index_j is_nt derivation_ge_shift] have F: "F = []"by (metis length_0_conv length_derivation_shift) thenhave β_is_b: "β = b"using β_intro by auto show ?thesis apply (rule_tac x="a ! i"in exI) apply (rule_tac x="take i a"in exI) apply (rule_tac x="drop (Suc i) a"in exI) apply (rule_tac x="take j b"in exI) using EF F assms(1) hyp splits_at_def by auto qed
lemma LeftDerivationIntro_implies_nonterminal: "LeftDerivationIntro α i (snd e) ix E j γ ==> is_nonterminal (α ! i)" by (simp add: LeftDerivationIntro_def LeftDerives1_def leftmost_is_nonterminal)
lemma LeftDerivationIntrosAt_implies_nonterminal: "LeftDerivationIntrosAt a D L index ==> is_nonterminal((ladder_α a D L index) ! (ladder_i L index))" by (meson LeftDerivationIntro_implies_nonterminal LeftDerivationIntrosAt_def)
lemma LeftDerivationIntro_examine_rule: "LeftDerivationIntro α i r ix D j γ ==> splits_at α i α1 M α2 ==> ∃ η. M = fst r ∧ η = snd r ∧ (M, η) ∈R" by (metis Derives1_nonterminal Derives1_rule LeftDerivationIntro_def LeftDerives1_implies_Derives1
prod.collapse)
lemma LeftDerivation_skip_prefixword_ex: assumes"LeftDerivation (u@v) D w" assumes"is_word u" shows"∃ w'. w = u@w' ∧ LeftDerivation v (derivation_shift D (length u) 0) w'" by (metis LeftDerivation.simps(1) LeftDerivation_breakdown LeftDerivation_implies_Derivation
LeftDerivation_skip_prefix append_eq_conv_conj assms(1) assms(2) is_word_Derivation
is_word_Derivation_derivation_ge)
definition ladder_cut :: "ladder ==> nat ==> ladder" where"ladder_cut L n = (let i = length L - 1 in L[i := (n, snd (L ! i))])"
definition ladder_shift :: "ladder ==> nat ==> nat ==> ladder" where"ladder_shift L dn dj = map (deriv_shift dn dj) L"
lemma splits_at_append_suffix_prevails: assumes"splits_at (a@b) i u N v" assumes"i < length a" shows"∃ v'. v = v'@b ∧ a=u@[N]@v'" proof - have"min (length a) (Suc i) = Suc i" using Suc_leI assms(2) min.absorb2 by blast thenshow ?thesis by (metis (no_types) append_assoc append_eq_conv_conj append_take_drop_id assms(1)
hd_drop_conv_nth length_take splits_at_def take_hd_drop) qed
lemma derivation_shift_right_left_cancel: "derivation_shift (derivation_shift D 0 r) r 0 = D" by (induct D, auto)
lemma derivation_shift_left_right_cancel: assumes"derivation_ge D r" shows"derivation_shift (derivation_shift D r 0) 0 r = D" using assms derivation_ge_shift_simp derivation_shift_0_shift by auto
lemma LeftDerivation_ge_take: assumes"derivation_ge D k" assumes"LeftDerivation a D b" assumes"D ≠ []" shows"take k a = take k b ∧ is_word (take k a)" proof - obtain d D' where d: "d#D' = D"using assms(3) list.exhaust by blast thenhave"∃ x. LeftDerives1 a (fst d) (snd d) x ∧ LeftDerivation x D' b" using LeftDerivation.simps(2) assms(2) by blast thenobtain x where x: "LeftDerives1 a (fst d) (snd d) x ∧ LeftDerivation x D' b"by blast have fst_d_k: "fst d ≥ k"using d assms(1) derivation_ge_cons by blast from x fst_d_k have is_word: "is_word (take k a)" by (metis LeftDerives1_def append_take_drop_id is_word_append leftmost_def
min.absorb2 take_append take_take) have is_eq: "take k a = take k b" using Derivation_take LeftDerivation_implies_Derivation assms(1) assms(2) by blast show ?thesis using is_word is_eq by blast qed
lemma LeftDerivationFix_splits_at_symbol: assumes"LeftDerivationFix a i D j b" shows"∃ U a1 a2 b1 b2 n. splits_at a i a1 U a2 ∧ splits_at b j b1 U b2 ∧ n ≤ length D ∧ LeftDerivation a1 (take n D) b1 ∧ derivation_ge (drop n D) (Suc(length b1)) ∧ LeftDerivation a2 (derivation_shift (drop n D) (Suc(length b1)) 0) b2 ∧ (n = length D ∨ (n < length D ∧ is_word (b1@[U])))" proof - note hyp = LeftDerivationFix_def[where α=a and β=b and D=D and i=i and j=j] from hyp obtain E F where EF: "D = E @ derivation_shift F 0 (Suc j) ∧ LeftDerivation (take i a) E (take j b) ∧ LeftDerivation (drop (Suc i) a) F (drop (Suc j) b)" using assms by blast have"∃ β. LeftDerivation a E β ∧ LeftDerivation β (derivation_shift F 0 (Suc j)) b" using EF LeftDerivation_append assms(1) hyp by blast thenobtain β where β_intro: "LeftDerivation a E β ∧ LeftDerivation β (derivation_shift F 0 (Suc j)) b"by blast have"LeftDerivation ((take i a)@(drop i a)) E ((take j b)@(drop i a))" by (metis EF LeftDerivation_append_suffix append_take_drop_id assms(1) hyp is_sentence_concat) thenhave"LeftDerivation a E ((take j b)@(drop i a))"by simp thenhave β_decomposed: "β = (take j b)@(drop i a)" using Derivation_unique_dest LeftDerivation_implies_Derivation β_intro by blast have derivation: "LeftDerivation β (derivation_shift F 0 (Suc j)) b" by (simp add: β_intro) have"∃ n. n ≤ length D ∧ E = take n D" by (metis EF append_eq_conv_conj is_prefix_length is_prefix_take) thenobtain n where n: "n ≤ length D ∧ E = take n D"by blast have F_def: "drop n D = derivation_shift F 0 (Suc j)" by (metis EF append_eq_conv_conj length_take min.absorb2 n) have min_j: "min (length b) j = j"using assms hyp by linarith have derivation_ge_Suc_j: "derivation_ge (drop n D) (Suc j)" using F_def derivation_ge_shift by simp have LeftDerivation_β_b: "LeftDerivation β (drop n D) b"by (simp add: F_def β_intro) have is_word_Suc_j_b: "n ≠ length D ==> is_word (take (Suc j) b)" by (metis EF F_def LeftDerivation_ge_take β_intro append_Nil2 derivation_ge_Suc_j
length_take min.absorb2 n) have take_Suc_j_b_decompose: "take (Suc j) b = take j b @ [a ! i]" using assms hyp take_Suc_conv_app_nth by auto show ?thesis apply (rule_tac x="a ! i"in exI) apply (rule_tac x="take i a"in exI) apply (rule_tac x="drop (Suc i) a"in exI) apply (rule_tac x="take j b"in exI) apply (rule_tac x="drop (Suc j) b"in exI) apply (rule_tac x="n"in exI) apply (auto simp add: min_j) using assms hyp splits_at_def apply blast using assms hyp splits_at_def apply blast using n apply blast using EF n apply simp using F_def apply simp using derivation_ge_shift apply blast using F_def derivation_shift_right_left_cancel apply simp using EF apply blast using n apply arith using is_word_Suc_j_b take_Suc_j_b_decompose is_word_append apply simp+ done qed
lemma LeftDerivation_breakdown': "LeftDerivation (u @ v) D w ==> ∃n w1 w2. n ≤ length D ∧ w = w1 @ w2 ∧ LeftDerivation u (take n D) w1 ∧ derivation_ge (drop n D) (length w1) ∧ LeftDerivation v (derivation_shift (drop n D) (length w1) 0) w2" proof - assume hyp: "LeftDerivation (u @ v) D w" from LeftDerivation_breakdown[OF hyp] obtain n w1 w2 where breakdown: "w = w1 @ w2 ∧ LeftDerivation u (take n D) w1 ∧ derivation_ge (drop n D) (length w1) ∧ LeftDerivation v (derivation_shift (drop n D) (length w1) 0) w2"by blast obtain m where m: "m = min (length D) n"by blast have take_m: "take m D = take n D"using m is_prefix_take take_prefix by fastforce have drop_m: "drop m D = drop n D" by (metis append_eq_conv_conj append_take_drop_id length_take m) have m_bound: "m ≤ length D"by (simp add: m) show ?thesis apply (rule_tac x="m"in exI) apply (rule_tac x="w1"in exI) apply (rule_tac x="w2"in exI) using breakdown m_bound take_m drop_m by auto qed
lemma LeftDerives1_append_replace_in_left: assumes ld1: "LeftDerives1 (α@δ) i r β" assumes i_bound: "i < length α" shows"∃ α'. β = α'@δ ∧ LeftDerives1 α i r α' ∧ i + length (snd r) ≤ length α'" proof - obtain α' where α': "α' = (take i α)@(snd r)@(drop (i+1) α)"by blast have fst_r: "fst r = α ! i" proof - have"∀ss n p ssa. ¬ LeftDerives1 ss n p ssa ∨ Derives1 ss n p ssa" using LeftDerives1_implies_Derives1 by blast thenhave"Derives1 (α @ δ) i r β" using ld1 by blast thenshow ?thesis using Derives1_nonterminal i_bound splits_at_def by auto qed have"Derives1 α i r α'" using i_bound ld1 apply (auto simp add: α' Derives1_def) apply (rule_tac x="take i α"in exI) apply (rule_tac x="drop (i+1) α"in exI) apply (rule_tac x="fst r"in exI) apply auto apply (simp add: fst_r) using id_take_nth_drop apply blast using Derives1_sentence1 LeftDerives1_implies_Derives1 is_sentence_concat
is_sentence_take apply blast apply (metis Derives1_sentence1 LeftDerives1_implies_Derives1 append_take_drop_id
is_sentence_concat) using Derives1_rule LeftDerives1_implies_Derives1 by blast thenhave leftderives1_α_α': "LeftDerives1 α i r α'" using LeftDerives1_def i_bound ld1 leftmost_cons_less by auto have i_bound_α': "i + length (snd r) ≤ length α'" using α' i_bound by (simp add: add_mono_thms_linordered_semiring(2) le_add1 less_or_eq_imp_le min.absorb2) have is_sentence_δ: "is_sentence δ" using Derives1_sentence1 LeftDerives1_implies_Derives1 is_sentence_concat ld1 by blast thenhave β: "β = α'@δ" using ld1 leftderives1_α_α' Derives1_append_suffix Derives1_unique_dest
LeftDerives1_implies_Derives1 by blast show ?thesis apply (rule_tac x="α'"in exI) using β i_bound_α' leftderives1_α_α' by blast qed
lemma LeftDerivationIntro_propagate: assumes intro: "LeftDerivationIntro (α@δ) i r ix D j γ" assumes i_α: "i < length α" assumes non: "is_nonterminal (γ ! j)" shows"∃ ψ. LeftDerivation α ((i,r)#D) ψ ∧ γ = ψ@δ ∧ j < length ψ" proof - from intro LeftDerivationIntro_def[where α="α@δ"and i=i and r=r and ix=ix and D=D and
j=j and γ=γ] obtain β where ld_β: "LeftDerives1 (α @ δ) i r β"and
ix: "ix < length (snd r) ∧ snd r ! ix = γ ! j"and
β_fix: "LeftDerivationFix β (i + ix) D j γ" by blast from LeftDerives1_append_replace_in_left[OF ld_β i_α] obtain α' where α': "β = α' @ δ ∧ LeftDerives1 α i r α' ∧ i + length (snd r) ≤ length α'" by blast have i_plus_ix_bound: "i + ix < length α'"using α' ix by linarith have ld_γ: "LeftDerivationFix (α' @ δ) (i + ix) D j γ" using β_fix α' by simp thenhave non_i_ix: "is_nonterminal ((α' @ δ) ! (i + ix))" by (simp add: LeftDerivationFix_def non) from LeftDerivationFix_splits_at_nonterminal[OF ld_γ non_i_ix] obtain U a1 a2 b1 where U: "splits_at (α' @ δ) (i + ix) a1 U a2 ∧ splits_at γ j b1 U a2 ∧ LeftDerivation a1 D b1" by blast have"∃ q. a2 = q@δ ∧ α' = a1 @ [U] @ q" using splits_at_append_suffix_prevails[OF _ i_plus_ix_bound, where b=δ] U by blast thenobtain q where q: "a2 = q@δ ∧ α' = a1 @ [U] @ q"by blast show ?thesis apply (rule_tac x="b1@[U]@q"in exI) apply auto apply (rule_tac x="α'"in exI) apply (metis LeftDerivationFix_def LeftDerivation_append_suffix U α'
q append_Cons append_Nil is_sentence_concat ld_γ) using U q splits_at_combine apply auto[1] using U splits_at_def by auto qed
lemma LeftDerivationIntro_finish: assumes intro: "LeftDerivationIntro (α@δ) i r ix D j γ" assumes i_α: "i < length α" shows"∃ k ψ δ'. k ≤ length D ∧ LeftDerivation α ((i, r)#(take k D)) ψ ∧ LeftDerivation (α @ δ) ((i, r)#(take k D)) (ψ @ δ) ∧ derivation_ge (drop k D) (length ψ) ∧ LeftDerivation δ (derivation_shift (drop k D) (length ψ) 0) δ' ∧ γ = ψ @ δ' ∧ j < length ψ" proof - from intro LeftDerivationIntro_def[where α="α@δ"and i=i and r=r and ix=ix and D=D and
j=j and γ=γ] obtain β where ld_β: "LeftDerives1 (α @ δ) i r β"and
ix: "ix < length (snd r) ∧ snd r ! ix = γ ! j"and
β_fix: "LeftDerivationFix β (i + ix) D j γ" by blast from LeftDerives1_append_replace_in_left[OF ld_β i_α] obtain α' where α': "β = α' @ δ ∧ LeftDerives1 α i r α' ∧ i + length (snd r) ≤ length α'" by blast have i_plus_ix_bound: "i + ix < length α'"using α' ix by linarith have ld_γ: "LeftDerivationFix (α' @ δ) (i + ix) D j γ" using β_fix α' by simp from LeftDerivationFix_splits_at_symbol[OF ld_γ] obtain U a1 a2 b1 b2 n where U: "splits_at (α' @ δ) (i + ix) a1 U a2 ∧ splits_at γ j b1 U b2 ∧ n ≤ length D ∧ LeftDerivation a1 (take n D) b1 ∧ derivation_ge (drop n D) (Suc (length b1)) ∧ LeftDerivation a2 (derivation_shift (drop n D) (Suc (length b1)) 0) b2 ∧ (n = length D ∨ n < length D ∧ is_word (b1 @ [U]))" by blast have n_bound: "n ≤ length D"using U by blast have"∃ q. a2 = q@δ ∧ α' = a1 @ [U] @ q" using splits_at_append_suffix_prevails[OF _ i_plus_ix_bound, where b=δ] U by blast thenobtain q where q: "a2 = q@δ ∧ α' = a1 @ [U] @ q"by blast have j: "j = length b1" using U by (simp add: dual_order.strict_implies_order min.absorb2 splits_at_def) have"n = length D ∨ n < length D ∧ is_word (b1 @ [U])"using U by blast thenshow ?thesis proof (induct rule: disjCases2) case1 from1have drop_n_D: "drop n D = []"by (simp add: U) thenhave"LeftDerivation a2 [] b2"using U by simp thenhave a2_eq_b2: "a2 = b2"by simp show ?case apply (rule_tac x="n"in exI) apply (rule_tac x="b1@[U]@q"in exI) apply (rule_tac x="δ"in exI) apply auto apply (simp add: 1) apply (rule_tac x="α'"in exI) apply (metis LeftDerivationFix_is_sentence LeftDerivation_append_suffix U α'
append_Cons append_Nil is_sentence_concat ld_γ q) apply (rule_tac x="α' @ δ"in exI) apply (metis "1.hyps" LeftDerivationFix_def U α' a2_eq_b2 id_take_nth_drop ld_β
ld_γ q splits_at_def take_all) apply (simp add: drop_n_D)+ apply (metis U a2_eq_b2 id_take_nth_drop q splits_at_def) using j apply arith done next case2 obtain E where E: "E = (derivation_shift (drop n D) (Suc (length b1)) 0)"by blast thenhave"LeftDerivation (q@δ) E b2"using U q by simp from LeftDerivation_breakdown'[OF this] obtain n' w1 w2 where w1w2: "n' ≤ length E ∧ b2 = w1 @ w2 ∧ LeftDerivation q (take n' E) w1 ∧ derivation_ge (drop n' E) (length w1) ∧ LeftDerivation δ (derivation_shift (drop n' E) (length w1) 0) w2"by blast have length_E_D: "length E = length D - n"using E n_bound by simp have n_plus_n'_bound: "n + n' ≤ length D"using length_E_D w1w2 n_bound by arith have take_breakdown: "take (n + n') D = (take n D) @ (take n' (drop n D))" using take_add by blast have q_w1: "LeftDerivation q (take n' E) w1"using w1w2 by blast have isw: "is_word (b1 @ [U])"using2by blast have take_n': "take n' (drop n D) = derivation_shift (take n' E) 0 (Suc (length b1))" by (metis E U derivation_shift_left_right_cancel take_derivation_shift) have α'_derives_b1_U_w1: "LeftDerivation α' (take (n + n') D) (b1 @ U # w1)" apply (subst take_breakdown) apply (rule_tac LeftDerivation_implies_append[where b="b1@[U]@q"]) apply (metis LeftDerivationFix_is_sentence LeftDerivation_append_suffix U
is_sentence_concat ld_γ q) apply (simp add: take_n') by (rule LeftDerivation_append_prefix[OF q_w1, where u = "b1@[U]", OF isw, simplified]) have dge: "derivation_ge (drop (n + n') D) (Suc (length b1 + length w1))" proof - have"derivation_ge (drop n' (drop n D)) (length b1 + 1 + length w1)" by (metis (no_types) E Suc_eq_plus1 U append_take_drop_id derivation_ge_append derivation_ge_shift_plus drop_derivation_shift w1w2) thenshow"derivation_ge (drop (n + n') D) (Suc (length b1 + length w1))" by (metis (no_types) Suc_eq_plus1 add.commute drop_drop semiring_normalization_rules(23)) qed show ?case apply (rule_tac x="n+n'"in exI) apply (rule_tac x="b1 @ [U] @ w1"in exI) apply (rule_tac x=w2 in exI) apply auto using n_plus_n'_bound apply simp apply (rule_tac x="α'"in exI) using α' α'_derives_b1_U_w1 apply blast apply (rule_tac x="α' @ δ"in exI) apply (metis Cons_eq_appendI LeftDerivationFix_is_sentence LeftDerivation_append_suffix
α' α'_derives_b1_U_w1 append_assoc is_sentence_concat ld_β ld_γ) apply (rule dge) apply (metis E Suc_eq_plus1 add.commute derivation_shift_0_shift drop_derivation_shift
drop_drop w1w2) using U splits_at_combine w1w2 apply auto[1] by (simp add: j) qed qed
lemma LeftDerivationLadder_propagate: "LeftDerivationLadder (α@δ) D L γ ==> ladder_i L 0 < length α ==> n = ladder_n L index ==> index < length L ==> if (index + 1 < length L) then (∃ β. LeftDerivation α (take n D) β ∧ ladder_γ (α@δ) D L index = β@δ ∧ ladder_j L index < length β) else (∃ n' β δ'. (index = 0 ∨ ladder_prev_n L index < n') ∧ n' ≤ n ∧ LeftDerivation α (take n' D) β ∧ LeftDerivation (α@δ) (take n' D) (β@δ) ∧ derivation_ge (drop n' D) (length β) ∧ LeftDerivation δ (derivation_shift (drop n' D) (length β) 0) δ' ∧ ladder_γ (α@δ) D L index = β@δ' ∧ ladder_j L index < length β)" proof (induct index arbitrary: n) case0 have ldfix: "LeftDerivationFix (α@δ) (ladder_i L 0) (take n D) (ladder_j L 0) (ladder_γ (α@δ) D L 0)" using"0.prems"(1) "0.prems"(3) LeftDerivationLadder_def by blast from0have"1 < length L ∨ 1 = length L"by arith thenshow ?case proof (induct rule: disjCases2) case1 have"LeftDerivationIntrosAt (α@δ) D L 1" using"0.prems"(1) "1.hyps" LeftDerivationIntros_def LeftDerivationLadder_def by blast from LeftDerivationIntrosAt_implies_nonterminal[OF this] have"is_nonterminal (ladder_γ (α @ δ) D L 0 ! ladder_j L 0)" by (simp add: ladder_α_def ladder_i_def) with ldfix have"is_nonterminal ((α@δ) ! (ladder_i L 0))"by (simp add: LeftDerivationFix_def) from LeftDerivationFix_splits_at_nonterminal[OF ldfix this] obtain U a1 a2 b where thesplit: "splits_at (α @ δ) (ladder_i L 0) a1 U a2 ∧ splits_at (ladder_γ (α @ δ) D L 0) (ladder_j L 0) b U a2 ∧ LeftDerivation a1 (take n D) b"by blast have"∃ δ'. a2 = δ' @ δ ∧ α = a1 @ [U] @ δ'" using thesplit splits_at_append_suffix_prevails using"0.prems"(2) by blast thenobtain δ' where δ': "a2 = δ' @ δ ∧ α = a1 @ ([U] @ δ')"by blast obtain β where β: "β = b @ ([U] @ δ')"by blast have"is_sentence α"using LeftDerivationFix_is_sentence is_sentence_concat ldfix by blast thenhave"is_sentence ([U] @ δ')"using δ' is_sentence_concat by blast with δ' thesplit have"LeftDerivation (a1 @ ([U] @ δ')) (take n D) (b @ ([U] @ δ'))" using LeftDerivation_append_suffix by blast thenhave α_derives_β: "LeftDerivation α (take n D) β"using β δ' by blast have β_append_δ: "ladder_γ (α @ δ) D L 0 = β@δ" by (metis β δ' append_assoc splits_at_combine thesplit) have ladder_j_bound: "ladder_j L 0 < length β" by (metis One_nat_def β diff_add_inverse dual_order.strict_implies_order leD le_add1
length_Cons length_append length_take list.size(3) min.absorb2 neq0_conv splits_at_def
thesplit zero_less_diff zero_less_one) show ?case using1apply simp apply (rule_tac x="β"in exI) by (auto simp add: α_derives_β β_append_δ ladder_j_bound) next case2 note case_2 = 2 have n_def: "n = length D" by (metis "0.prems"(1) "0.prems"(3) "2.hyps" LeftDerivationLadder_def One_nat_def
diff_Suc_1 is_ladder_def ladder_last_n_intro) thenhave take_n_D: "take n D = D"by (simp add: eq_imp_le) from LeftDerivationFix_splits_at_symbol[OF ldfix] obtain U a1 a2 b1 b2 m where U: "splits_at (α @ δ) (ladder_i L 0) a1 U a2 ∧ splits_at (ladder_γ (α @ δ) D L 0) (ladder_j L 0) b1 U b2 ∧ m ≤ length (take n D) ∧ LeftDerivation a1 (take m (take n D)) b1 ∧ derivation_ge (drop m (take n D)) (Suc (length b1)) ∧ LeftDerivation a2 (derivation_shift (drop m (take n D)) (Suc (length b1)) 0) b2 ∧ (m = length (take n D) ∨ (m < length (take n D) ∧ is_word (b1 @ [U])))"by blast obtain D' where D': "D' = derivation_shift (drop m D) (Suc (length b1)) 0"by blast thenhave a2_derives_b2: "LeftDerivation a2 D' b2"using U take_n_D by auto from U have m_leq_n: "m ≤ n" by (simp add: "0.prems"(1) "0.prems"(3) "0.prems"(4) LeftDerivationLadder_def is_ladder_def
min.absorb2) from U have"splits_at (α @ δ) (ladder_i L 0) a1 U a2"by blast from splits_at_append_suffix_prevails[OF this 0(2)] obtain v' where
v': "a2 = v' @ δ ∧ α = a1 @ [U] @ v'"by blast have a1_derives_b1: "LeftDerivation a1 (take m D) b1"using m_leq_n U by (metis "0.prems"(1) "0.prems"(3) "2.hyps" LeftDerivationLadder_def One_nat_def
cancel_comm_monoid_add_class.diff_cancel is_ladder_def ladder_last_n_intro order_refl
take_all) have"LeftDerivation (v' @ δ) D' b2"using a2_derives_b2 v' by simp from LeftDerivation_breakdown'[OF this] obtain m' w1 w2 where w12: "b2 = w1 @ w2 ∧ m' ≤ length D' ∧ LeftDerivation v' (take m' D') w1 ∧ derivation_ge (drop m' D') (length w1) ∧ LeftDerivation δ (derivation_shift (drop m' D') (length w1) 0) w2"by blast have"length D' ≤ length D - m"by (simp add: D') thenhave"m' ≤ length D - m"using w12 dual_order.trans by blast thenhave m_m'_leq_n: "m + m' ≤ n"using n_def m_leq_n le_diff_conv2 add.commute by linarith obtain β where β: "β = b1 @ ([U] @ w1)"by blast have"is_sentence ([U] @ v')" using LeftDerivationFix_is_sentence is_sentence_concat ldfix v' by blast thenhave"LeftDerivation (a1 @ ([U] @ v')) (take m D) (b1 @ ([U] @ v'))" using LeftDerivation_append_suffix a1_derives_b1 by blast thenhave α_derives_pre_β: "LeftDerivation α (take m D) (b1 @ ([U] @ v'))" using v' by blast have"m = n ∨ (m < n ∧ is_word (b1 @ [U]))" using U n_def[symmetric] take_n_D by simp thenhave pre_β_derives_β: "LeftDerivation (b1 @ ([U] @ v')) (take m' (drop m D)) β" proof (induct rule: disjCases2) case1 thenhave"m' = 0"using m_m'_leq_n by arith thenshow ?case apply (simp add: β) using w12 by simp next case2 thenhave is_word_prefix: "is_word (b1 @ [U])"by blast have take_drop_eq: "take m' (drop m D) = derivation_shift (take m' D') 0 (length (b1 @ [U]))" apply (simp add: D' take_derivation_shift) by (metis U derivation_shift_left_right_cancel take_derivation_shift take_n_D) have v'_derives_w1: "LeftDerivation v' (take m' D') w1" by (simp add: w12) with is_word_prefix have "LeftDerivation ((b1 @ [U]) @ v') (derivation_shift (take m' D') 0 (length (b1 @ [U]))) ((b1 @ [U]) @ w1)" using LeftDerivation_append_prefix by blast with take_drop_eq show ?caseby (simp add: β) qed have"(take m D) @ (take m' (drop m D)) = (take (m + m') D)" by (simp add: take_add) thenhave α_derives_β: "LeftDerivation α (take (m + m') D) β" using LeftDerivation_implies_append α_derives_pre_β pre_β_derives_β by fastforce have derivation_ge_drop_m_m': "derivation_ge (drop (m + m') D) (length β)" proof - have f1: "drop m' (drop m D) = drop (m + m') D" by (simp add: add.commute) have"derivation_ge (drop m' (drop m D)) (Suc (length b1))" by (metis (no_types) U append_take_drop_id derivation_ge_append take_n_D) thenshow"derivation_ge (drop (m + m') D) (length β)" using f1 by (metis (no_types) D' β append_assoc derivation_ge_shift_plus
drop_derivation_shift length_append length_append_singleton w12) qed have δ_derives_w2: "LeftDerivation δ (derivation_shift (drop (m + m') D) (length β) 0) w2" proof - have"derivation_shift (drop m' D') (length w1) 0 = derivation_shift (drop (m + m') D) (length β) 0" by (simp add: D' β add.commute derivation_shift_0_shift drop_derivation_shift) thenshow"LeftDerivation δ (derivation_shift (drop (m + m') D) (length β) 0) w2" using w12 by presburger qed have ladder_γ_def: "ladder_γ (α @ δ) D L 0 = β @ w2" using U β splits_at_combine w12 by auto have ladder_j_bound: "ladder_j L 0 < length β"using U β splits_at_def by auto show ?case using2apply simp apply (rule_tac x="m + m'"in exI) apply (auto simp add: m_m'_leq_n) apply (rule_tac x="β"in exI) apply (auto simp add: α_derives_β) using LeftDerivationFix_is_sentence LeftDerivation_append_suffix α_derives_β
is_sentence_concat ldfix apply blast using derivation_ge_drop_m_m' apply blast apply (rule_tac x="w2"in exI) apply auto using δ_derives_w2 apply blast using ladder_γ_defapply blast using ladder_j_bound apply blast done qed next case (Suc index) have step: "LeftDerivationIntrosAt (α@δ) D L (Suc index)" by (metis LeftDerivationIntros_def LeftDerivationLadder_def Suc.prems(1) Suc.prems(4)
Suc_eq_plus1_left le_add1) have index_plus_1_bound: "index + 1 < length L" using Suc.prems(4) by linarith thenhave index_bound: "index < length L"by arith obtain n' where n': "n' = ladder_n L index"by blast from Suc.hyps[OF Suc.prems(1) Suc.prems(2) n' index_bound] index_plus_1_bound have"∃ α'. LeftDerivation α (take n' D) α' ∧ ladder_γ (α@δ) D L index = α'@δ ∧ ladder_j L index < length α'" by auto thenobtain α' where α': "LeftDerivation α (take n' D) α' ∧ ladder_γ (α@δ) D L index = α'@δ ∧ ladder_j L index < length α'" by blast have Suc_index_bound: "Suc index < length L"using Suc.prems by auto have is_ladder: "is_ladder D L"using Suc.prems LeftDerivationLadder_def by auto have n_def: "n = ladder_n L (Suc index)" using Suc_index_bound n' by (simp add: Suc.prems(3)) with n' have n'_less_n: "n' < n"using is_ladder Suc_index_bound is_ladder_def lessI by blast have ladder_α_is_γ: "ladder_α (α@δ) D L (Suc index) = ladder_γ (α@δ) D L index" by (simp add: ladder_α_def) obtain i where i: "i = ladder_i L (Suc index)"by blast obtain e where e: "e = (D ! n')"by blast obtain E where E: "E = drop (Suc n') (take n D)"by blast obtain ix where ix: "ix = ladder_ix L (Suc index)"by blast obtain j where j: "j = ladder_j L (Suc index)"by blast obtain γ where γ: "γ = ladder_γ (α@δ) D L (Suc index)"by blast have intro: "LeftDerivationIntro (α'@δ) i (snd e) ix E j γ" by (metis E LeftDerivationIntrosAt_def α' γ ladder_α_is_γ
diff_Suc_1 e i ix j local.step n' n_def) have is_eq_fst_e: "i = fst e" by (metis LeftDerivationIntrosAt_def diff_Suc_1 e i local.step n') have i_less_α': "i < length α'"using i α' ladder_i_def by simp have"(Suc index) + 1 < length L ∨ (Suc index) + 1 = length L" using Suc_index_bound by arith thenshow ?case proof (induct rule: disjCases2) case1 from1have"LeftDerivationIntrosAt (α@δ) D L (Suc (Suc index))" by (metis LeftDerivationIntros_def LeftDerivationLadder_def Suc.prems(1)
Suc_eq_plus1 Suc_eq_plus1_left le_add1) from LeftDerivationIntrosAt_implies_nonterminal[OF this] have "is_nonterminal (ladder_α (α @ δ) D L (Suc (Suc index)) ! ladder_i L (Suc (Suc index)))" by blast thenhave non_γ_j: "is_nonterminal (γ ! j)"by (simp add: γ j ladder_α_def ladder_i_def) from LeftDerivationIntro_propagate[OF intro i_less_α' non_γ_j] obtain ψ where ψ: "LeftDerivation α' ((i, snd e) # E) ψ ∧ γ = ψ @ δ ∧ j < length ψ" by blast have α_ψ: "LeftDerivation α ((take n' D)@((i, snd e) # E)) ψ" using α' ψ LeftDerivation_implies_append by blast have i_e: "(i, snd e) = e"by (simp add: is_eq_fst_e) have take_n_D_e: "((take n' D)@(e # E)) = take n D" proof - (* automatically found, then modified *) have f2: "ladder_last_n L = length D" using is_ladder is_ladder_def by blast have f3: "min (ladder_last_n L) n = n" using is_ladder_def by (metis (no_types) Suc_eq_plus1 index_plus_1_bound is_ladder min.absorb2 n_def) thenhave"take n' (take n D) @ take n D ! n' # E = take n D" using f2 by (metis E id_take_nth_drop length_take n'_less_n) thenshow ?thesis using f3 f2 by (metis (no_types) append_assoc append_eq_conv_conj
dual_order.strict_implies_order e length_take min.absorb2 n'_less_n nth_append) qed from1show ?case apply auto apply (rule_tac x=ψ in exI) apply auto using α_ψ i_e take_n_D_e apply auto[1] using γ ψ apply blast using ψ j by blast next case2 from LeftDerivationIntro_finish[OF intro i_less_α'] obtain k ψ δ' where kwδ': "k ≤ length E ∧ LeftDerivation α' ((i, snd e) # take k E) ψ ∧ LeftDerivation (α' @ δ) ((i, snd e) # take k E) (ψ @ δ) ∧ derivation_ge (drop k E) (length ψ) ∧ LeftDerivation δ (derivation_shift (drop k E) (length ψ) 0) δ' ∧ γ = ψ @ δ' ∧ j < length ψ"by blast have ladder_last_n_1: "ladder_last_n L = n" by (metis "2.hyps" Suc_eq_plus1 diff_Suc_1 ladder_last_n_def n_def) from is_ladder have ladder_last_n_2: "ladder_last_n L = length D" using is_ladder_def by blast from ladder_last_n_1 ladder_last_n_2 have n_eq_length_D: "n = length D"by blast have take_split: "take (Suc (n' + k)) D = (take n' D) @ ((i, snd e) # take k E)" apply (simp add: E n_eq_length_D) by (metis (no_types, lifting) Cons_eq_appendI add_Suc append_eq_appendI e
is_eq_fst_e n'_less_n n_eq_length_D prod.collapse
self_append_conv2 take_Suc_conv_app_nth take_add) have α_ψ: "LeftDerivation α (take (Suc (n' + k)) D) ψ" apply (subst take_split) apply (rule LeftDerivation_implies_append[where b="α'"]) apply (simp add: α') using kwδ' by blast have Suc_n'_k_bound: "Suc (n' + k) ≤ n"using E kwδ' n'_less_n by auto[1] from2show ?case apply auto apply (rule_tac x="Suc (n' + k)"in exI) apply auto apply (simp add: ladder_prev_n_def n') using Suc_n'_k_bound apply blast apply (rule_tac x="ψ"in exI) apply auto using α_ψ apply blast using α_ψ LeftDerivationFix_def LeftDerivationLadder_def LeftDerivation_append_suffix
Suc.prems(1) is_sentence_concat apply auto[1] apply (metis E add.commute add_Suc_right drop_drop kwδ' n_eq_length_D nat_le_linear
take_all) apply (rule_tac x="δ'"in exI) apply auto apply (metis E LeftDerivationLadder_ladder_n_bound Suc.prems(1) Suc_index_bound
add.commute add_Suc_right drop_drop kwδ' n_def n_eq_length_D take_all) using γ kwδ' apply blast using j kwδ' by blast qed qed
lemma ladder_i_of_cut_at_0: assumes L_non_empty: "L ≠ []" shows"ladder_i (ladder_cut L n) 0 = ladder_i L 0" proof - have"length L ≠ 0"using L_non_empty by auto thenhave"length L = 1 ∨ length L > 1"by arith thenshow ?thesis proof (induct rule: disjCases2) case1 thenshow ?case apply (simp add: ladder_cut_def ladder_i_def deriv_i_def) by (simp add: assms hd_conv_nth) next case2 thenshow ?case apply (simp add: ladder_cut_def ladder_i_def deriv_i_def) by (metis diff_is_0_eq hd_conv_nth leD list_update_nonempty nth_list_update_neq) qed qed
lemma ladder_last_j_of_cut: assumes L_non_empty: "L ≠ []" shows"ladder_last_j (ladder_cut L n) = ladder_last_j L" proof - have length_L_nonzero: "length L ≠ 0"using L_non_empty by auto thenhave length_ladder_cut: "length (ladder_cut L n) = length L" by (metis ladder_cut_def length_list_update) show ?thesis apply (simp add: ladder_last_j_def length_ladder_cut) apply (simp add: ladder_cut_def ladder_j_def deriv_j_def) by (metis length_L_nonzero diff_less neq0_conv nth_list_update_eq snd_conv zero_less_Suc) qed
lemma length_ladder_cut: assumes L_non_empty: "L ≠ []" shows"length (ladder_cut L n) = length L" by (metis ladder_cut_def length_list_update)
lemma ladder_last_n_of_cut: assumes L_non_empty: "L ≠ []" shows"ladder_last_n (ladder_cut L n) = n" proof - show ?thesis apply (simp add: ladder_last_n_def length_ladder_cut[OF L_non_empty]) apply (simp add: ladder_n_def ladder_cut_def deriv_n_def) by (metis assms diff_Suc_less fst_conv length_greater_0_conv nth_list_update_eq) qed
lemma ladder_n_of_cut: assumes L_non_empty: "L ≠ []" assumes"index < length L - 1" shows"ladder_n (ladder_cut L n) index = ladder_n L index" by (metis assms(2) ladder_cut_def ladder_n_def nat_neq_iff nth_list_update_neq)
lemma ladder_n_prev_bound: assumes ladder: "is_ladder D L" assumes u_bound: "u < length L - 1" shows"ladder_n L u ≤ ladder_prev_n L (length L - 1)" proof - have"ladder_n L u ≤ ladder_n L (length L - 2)" proof - have"u < Suc (length L - 2)" using u_bound by linarith thenshow ?thesis by (metis (no_types) diff_Suc_less is_ladder_def ladder leI length_greater_0_conv
not_less_eq numeral_2_eq_2 order.order_iff_strict) qed thenshow ?thesis by (metis One_nat_def Suc_diff_Suc diff_Suc_1 ladder_prev_n_def neq0_conv not_less0
numeral_2_eq_2 u_bound zero_less_diff) qed
lemma ladder_n_last_is_length: assumes"is_ladder D L" shows"ladder_n L (length L - 1) = length D" using assms is_ladder_def ladder_last_n_intro by auto
lemma derivation_ge_shift_implies_derivation_ge: assumes dge: "derivation_ge (derivation_shift F 0 j) k" shows"derivation_ge F (k - j)" proof - have"∧ i r. (i, r) ∈ set (derivation_shift F 0 j) ==> i ≥ k" using dge derivation_ge_def by auto
{ fix i :: nat fix r :: "symbol × (symbol list)" assume ir: "(i, r) ∈ set F" thenhave"(i + j, r) ∈ set (derivation_shift F 0 j)" proof - have"(i + j, r) ∈ (λp. (fst p - 0 + j, snd p)) ` set F" by (metis (lifting) ir diff_zero image_eqI prod.collapse prod.inject) thenshow ?thesis by (simp add: derivation_shift_def) qed thenhave"i + j ≥ k"using dge derivation_ge_def by auto thenhave"i ≥ k - j"by auto
} thenshow ?thesis using derivation_ge_def by auto qed
lemma Derives1_bound': "Derives1 a i r b ==> i ≤ length b" by (metis Derives1_bound Derives1_take append_Nil2 append_take_drop_id drop_eq_Nil
dual_order.strict_implies_order length_take min.absorb2 nat_le_linear)
lemma LeftDerivation_Derives1_last: assumes"LeftDerivation a D b" assumes"D ≠ []" shows"Derives1 (Derive a (take (length D - 1) D)) (fst (last D)) (snd (last D)) b" by (metis Derive LeftDerivation_Derive_take_LeftDerives1 LeftDerivation_implies_Derivation
LeftDerives1_implies_Derives1 assms(1) assms(2) last_conv_nth le_refl length_0_conv take_all)
lemma last_of_prefix_in_set: assumes"n < length E" assumes"D = E@F" shows"last E ∈ set (drop n D)" proof - have f1: "last (drop n E) = last E" by (simp add: assms(1)) have"drop n E ≠ []" by (metis (no_types) Cons_nth_drop_Suc assms(1) list.simps(3)) thenshow ?thesis using f1 by (metis (no_types) append.simps(2) append_butlast_last_id append_eq_conv_conj assms(2) drop_append in_set_dropD insertCI list.set(2)) qed
lemma LeftDerivationFix_cut_appendix: assumes ldfix: "LeftDerivationFix (α@δ) i D j (β@δ')" assumes α_β: "LeftDerivation α (take n D) β" assumes n_bound: "n ≤ length D" assumes dge: "derivation_ge (drop n D) (length β)" assumes i_in: "i < length α" assumes j_in: "j < length β" shows"LeftDerivationFix α i (take n D) j β" proof - from LeftDerivationFix_def[where α="α@δ"and i=i and D=D and j=j and β="β@δ'"] obtain E F where EF: "is_sentence (α @ δ) ∧ is_sentence (β @ δ') ∧ LeftDerivation (α @ δ) D (β @ δ') ∧ i < length (α @ δ) ∧ j < length (β @ δ') ∧ (α @ δ) ! i = (β @ δ') ! j ∧ D = E @ derivation_shift F 0 (Suc j) ∧ LeftDerivation (take i (α @ δ)) E (take j (β @ δ')) ∧ LeftDerivation (drop (Suc i) (α @ δ)) F (drop (Suc j) (β @ δ'))"using ldfix by auto with i_in j_in have take_i_E_take_j: "LeftDerivation (take i α) E (take j β)" by (simp add: less_or_eq_imp_le) obtain m where m: "m = length E"by blast
{ assume n_less_m: "n < m" thenhave E_nonempty: "E ≠ []"using gr_implies_not0 list.size(3) m by auto have last_E_in_set: "last E ∈ set (drop n D)" using last_of_prefix_in_set n_less_m m EF by blast obtain k r where kr: "(k, r) = last E"by (metis old.prod.exhaust) have k_lower_bound: "k ≥ length β"using dge last_E_in_set kr by (metis derivation_ge_def fst_conv) have"∃ α'. Derives1 α' k r (take j β)"using LeftDerivation_Derives1_last take_i_E_take_j by (metis E_nonempty kr fst_conv snd_conv) thenhave"k ≤ j"by (metis Derives1_bound' j_in length_take less_imp_le_nat min.absorb2) thenhave k_upper_bound: "k < length β"using j_in by arith from k_lower_bound k_upper_bound have"False"by arith
} thenhave m_le_n: "m ≤ n"by arith have take_i_E_take_j: "LeftDerivation (take i α) E (take j β)" by (simp add: take_i_E_take_j) have"take n D = E @ (take (n - m) (derivation_shift F 0 (Suc j)))" using EF m m_le_n by auto thenhave take_n_D: "take n D = E @ (derivation_shift (take (n - m) F) 0 (Suc j))" using take_derivation_shift by auto obtain F' where F': "F' = derivation_shift (take (n - m) F) 0 (Suc j)"by blast have"LeftDerivation ((take i α)@(drop i α)) E ((take j β)@(drop i α))" using take_i_E_take_j by (metis EF LeftDerivation_append_suffix append_take_drop_id is_sentence_concat) thenhave"LeftDerivation α E ((take j β)@(drop i α))"by simp with take_n_D have take_j_drop_i: "LeftDerivation ((take j β)@(drop i α)) F' β"using F' by (metis Derivation_unique_dest LeftDerivation_append LeftDerivation_implies_Derivation α_β) have F'_ge: "derivation_ge F' (Suc j)"using F' derivation_ge_shift by blast have drop_append: "drop i α = [α!i] @ (drop (Suc i) α)"by (simp add: Cons_nth_drop_Suc i_in) have take_append: "take j β @ [α!i] = take (Suc j) β" by (metis LeftDerivationFix_def i_in j_in ldfix nth_superfluous_append take_Suc_conv_app_nth) have take_drop_Suc: "(take j β)@(drop i α) = (take (Suc j) β)@(drop (Suc i) α)" by (simp add: drop_append take_append) with take_drop_Suc take_j_drop_i have"LeftDerivation ((take (Suc j) β)@(drop (Suc i) α)) F' β" by auto note helper = LeftDerivation_skip_prefix[OF this] have len_take: "length (take (Suc j) β) = Suc j"by (simp add: Suc_leI j_in min.absorb2) have F'_shift: "derivation_shift F' (Suc j) 0 = take (n - m) F" using F' derivation_shift_right_left_cancel by blast have LeftDerivation_drop: "LeftDerivation (drop (Suc i) α) (take (n - m) F) (drop (Suc j) β)" using helper len_take F'_shift F'_ge by auto show ?thesis apply (auto simp add: LeftDerivationFix_def) using LeftDerivationFix_is_sentence is_sentence_concat ldfix apply blast using LeftDerivationFix_is_sentence is_sentence_concat ldfix apply blast using α_β apply blast using i_in apply blast using j_in apply blast using LeftDerivationFix_def i_in j_in ldfix apply auto[1] apply (rule_tac x=E in exI) apply (rule_tac x="take (n - m) F"in exI) apply auto using take_n_D apply blast using take_i_E_take_j apply blast using LeftDerivation_drop by blast qed
lemma LeftDerivationFix_cut_appendix': assumes ldfix: "LeftDerivationFix (α@δ) i D j (β@δ')" assumes α_β: "LeftDerivation α D β" assumes i_in: "i < length α" assumes j_in: "j < length β" shows"LeftDerivationFix α i D j β" proof - obtain n where n: "n = length D"by blast have"LeftDerivationFix α i (take n D) j β" apply (rule_tac LeftDerivationFix_cut_appendix) apply (rule ldfix) using α_β n apply auto[1] using n apply auto[1] using n apply auto[1] using i_in apply blast using j_in apply blast done thenshow ?thesis using n by auto qed
lemma LeftDerivationIntro_cut_appendix: assumes ldfix: "LeftDerivationIntro (α@δ) i r ix D j (β@δ')" assumes α_β: "LeftDerivation α ((i,r)#(take n D)) β" assumes n_bound: "n ≤ length D" assumes dge: "derivation_ge (drop n D) (length β)" assumes i_in: "i < length α" assumes j_in: "j < length β" shows"LeftDerivationIntro α i r ix (take n D) j β" proof - from LeftDerivationIntro_def[where α="α@δ"and i=i and r=r and ix=ix and D=D and j=j and γ="β@δ'"] obtain ψ where ψ: "LeftDerives1 (α @ δ) i r ψ ∧ ix < length (snd r) ∧ snd r ! ix = (β @ δ') ! j ∧ LeftDerivationFix ψ (i + ix) D j (β @ δ')" using ldfix by blast thenhave"∃ α'. ψ = α' @ δ ∧ i + length (snd r) ≤ length α'" using i_in using LeftDerives1_append_replace_in_left by blast thenobtain α' where α': "ψ = α' @ δ ∧ i + length (snd r) ≤ length α'"by blast have α_α': "LeftDerives1 α i r α'"using α' ψ using LeftDerives1_skip_suffix i_in by blast from α_β obtain u where u: "LeftDerives1 α i r u ∧ LeftDerivation u (take n D) β"by auto with α_α' have"u = α'"using Derives1_unique_dest LeftDerives1_implies_Derives1 by blast with u have α'_β: "LeftDerivation α' (take n D) β"by auto have ldfix_append: "LeftDerivationFix (α' @ δ) (i + ix) D j (β @ δ')"using α' ψ by blast have i_plus_ix_bound: "i + ix < length α'"using ψ α' using add_lessD1 le_add_diff_inverse less_asym' linorder_neqE_nat nat_add_left_cancel_less by linarith from LeftDerivationFix_cut_appendix[OF ldfix_append α'_β n_bound dge i_plus_ix_bound j_in] have ldfix: "LeftDerivationFix α' (i + ix) (take n D) j β" . show ?thesis apply (simp add: LeftDerivationIntro_def) apply (rule_tac x="α'"in exI) apply auto using α_α' apply blast using ψ apply blast apply (simp add: ψ j_in) using ldfix by blast qed
lemma LeftDerivationIntro_cut_appendix': assumes ldfix: "LeftDerivationIntro (α@δ) i r ix D j (β@δ')" assumes α_β: "LeftDerivation α ((i,r)#D) β" assumes i_in: "i < length α" assumes j_in: "j < length β" shows"LeftDerivationIntro α i r ix D j β" proof - obtain n where n: "n = length D"by blast have"LeftDerivationIntro α i r ix (take n D) j β" apply (rule_tac LeftDerivationIntro_cut_appendix) apply (rule ldfix) using α_β n apply auto[1] using n apply auto[1] using n apply auto[1] using i_in apply blast using j_in apply blast done thenshow ?thesis using n by auto qed
lemma ladder_n_monotone: "is_ladder D L ==> u ≤ v ==> v < length L ==> ladder_n L u≤ ladder_n L v" by (metis is_ladder_def le_neq_implies_less linear not_less)
lemma ladder_i_cut: assumes index_bound: "index < length L" shows"ladder_i (ladder_cut L n) index = ladder_i L index" proof - have"index = 0 ∨ index > 0"by arith thenshow ?thesis proof (induct rule: disjCases2) case1 with index_bound have"L ≠ []"by (simp add: less_numeral_extra(3)) thenshow ?caseusing1by (simp add: ladder_i_of_cut_at_0) next case2 thenshow ?case apply (auto simp add: ladder_i_def ladder_cut_def ladder_j_def deriv_j_def Let_def) using index_bound by auto qed qed
lemma ladder_j_cut: assumes index_bound: "index < length L" shows"ladder_j (ladder_cut L n) index = ladder_j L index" by (metis gr_implies_not0 index_bound ladder_cut_def ladder_j_def ladder_last_j_def
ladder_last_j_of_cut length_ladder_cut list.size(3) nth_list_update_neq)
lemma ladder_ix_cut: assumes index_lower_bound: "index > 0" assumes index_upper_bound: "index < length L" shows"ladder_ix (ladder_cut L n) index = ladder_ix L index" proof - show ?thesis using index_lower_bound apply (simp add: ladder_ix_def deriv_ix_def) by (metis index_upper_bound ladder_cut_def nth_list_update_eq nth_list_update_neq snd_conv) qed
lemma LeftDerivation_from_in_between: assumes α_β: "LeftDerivation α (take u D) β" assumes α_γ: "LeftDerivation α (take v D) γ" assumes u_le_v: "u ≤ v" shows"LeftDerivation β (drop u (take v D)) γ" proof - have take_split: "take v D = take u D @ (drop u (take v D))" by (metis u_le_v add_diff_cancel_left' drop_take le_Suc_ex take_add) thenshow ?thesis using α_γ α_β by (metis (no_types, lifting) Derivation_unique_dest LeftDerivation_append
LeftDerivation_implies_Derivation) qed
lemma LeftDerivationLadder_cut_appendix_helper: assumes LDLadder: "LeftDerivationLadder (α@δ) D L γ" assumes ladder_i_in_α: "ladder_i L 0 < length α" shows"∃ E F γ1 γ2 L'. D = E@F ∧ γ = γ1 @ γ2 ∧ LeftDerivationLadder α E L' γ1 ∧ derivation_ge F (length γ1) ∧ LeftDerivation δ (derivation_shift F (length γ1) 0) γ2 ∧ L' = ladder_cut L (length E)" proof - have is_ladder_D_L: "is_ladder D L"using LDLadder LeftDerivationLadder_def by blast obtain n where n: "n = ladder_last_n L"by blast thenhave n_eq_ladder_n: "n = ladder_n L (length L - 1)"using ladder_last_n_def by blast have length_L_nonzero: "length L > 0" using LeftDerivationLadder_def assms(1) is_ladder_def by blast from LeftDerivationLadder_propagate[OF LDLadder ladder_i_in_α n_eq_ladder_n] obtain n' β δ' where finish: "(length L - 1 = 0 ∨ ladder_prev_n L (length L - 1) < n') ∧ n' ≤ n ∧ LeftDerivation α (take n' D) β ∧ LeftDerivation (α @ δ) (take n' D) (β @ δ) ∧ derivation_ge (drop n' D) (length β) ∧ LeftDerivation δ (derivation_shift (drop n' D) (length β) 0) δ' ∧ ladder_γ (α @ δ) D L (length L - 1) = β @ δ' ∧ ladder_j L (length L - 1) < length β" using length_L_nonzero by auto obtain E where E: "E = take n' D"by blast obtain F where F: "F = drop n' D"by blast obtain L' where L': "L' = ladder_cut L (length E)"by blast have γ_ladder: "γ = ladder_γ (α @ δ) D L (length L - 1)" by (metis Derive LDLadder LeftDerivationLadder_def LeftDerivation_implies_Derivation
append_Nil2 append_take_drop_id drop_eq_Nil is_ladder_def ladder_γ_def le_refl n
n_eq_ladder_n) thenhave γ: "γ = β @ δ'"using finish by auto have"is_sentence (α@δ)" using LDLadder LeftDerivationFix_is_sentence LeftDerivationLadder_def by blast thenhave is_sentence_α: "is_sentence α"using is_sentence_concat by blast have"is_sentence γ" using Derivation_implies_derives LDLadder LeftDerivationFix_is_sentence
LeftDerivationLadder_def LeftDerivation_implies_Derivation derives_is_sentence by blast thenhave is_sentence_β: "is_sentence β"using γ is_sentence_concat by blast have length_L': "length L' = length L" by (metis L' ladder_cut_def length_list_update) have ladder_last_n_L': "ladder_last_n L' = length E" using L' ladder_last_n_of_cut length_L_nonzero by blast have length_D_eq_n: "length D = n" using LDLadder LeftDerivationLadder_def is_ladder_def n by auto thenhave length_E_eq_n': "length E = n'"by (simp add: E finish min.absorb2)
{ fix u :: nat assume"u < length L'" thenhave"u < length L' - 1 ∨ u = length L' - 1"by arith thenhave"ladder_n L' u ≤ length E" proof (induct rule: disjCases2) case1 have u_bound: "u < length L - 1"using1by (simp add: length_L') thenhave L'_eq_L: "ladder_n L' u = ladder_n L u"using L' ladder_n_of_cut
length_L_nonzero length_greater_0_conv by blast from u_bound have"ladder_n L u ≤ ladder_prev_n L (length L - 1)" using ladder_n_prev_bound LeftDerivationLadder_def assms(1) by blast thenshow ?case using L'_eq_L finish length_E_eq_n' u_bound by linarith next case2 thenhave"ladder_n L' u = length E"using ladder_last_n_L' ladder_last_n_def by auto thenshow ?caseby auto qed
} note ladder_n_bound = this
{ fix u :: nat fix v :: nat assume u_less_v: "u < v" assume v_bound: "v < length L'" have"v < length L' - 1 ∨ v = length L' - 1"using v_bound by arith thenhave"ladder_n L' u < ladder_n L' v" proof (induct rule: disjCases2) case1 show ?case using"1.hyps" L' LeftDerivationLadder_def assms(1) is_ladder_def ladder_n_of_cut
length_L' u_less_v by auto next case2 note v_def = 2 have"v = 0 ∨ v ≠ 0"by arith thenshow ?case proof (induct rule: disjCases2) case1 thenshow ?caseusing u_less_v by auto next case2 thenhave"ladder_prev_n L (length L - 1) < n'"using finish v_def length_L' by linarith thenshow ?case by (metis (no_types, lifting) L' LeftDerivationLadder_def assms(1)
ladder_last_n_L' ladder_last_n_def ladder_n_of_cut ladder_n_prev_bound
le_neq_implies_less length_E_eq_n' length_L' length_greater_0_conv
less_trans u_less_v v_def) qed qed
} note ladder_n_pairwise_bound = this
have is_ladder_E_L': "is_ladder E L'" apply (auto simp add: is_ladder_def ladder_last_n_L') using length_L_nonzero length_L' apply simp using ladder_n_bound apply blast using ladder_n_pairwise_bound by blast
{ fix index :: nat assume index_bound: "index + 1 < length L" thenhave index_le: "index < length L"by arith from index_bound have len_L_minus_1: "length L - 1 ≠ 0"by arith obtain m where m: "m = ladder_n L index"by blast from LeftDerivationLadder_propagate[OF LDLadder ladder_i_in_α m index_le] obtain ψ where
ψ: "LeftDerivation α (take m D) ψ ∧ ladder_γ (α @ δ) D L index = ψ @ δ ∧ ladder_j L index < length ψ"using index_bound by auto have L'_Derive: "ladder_γ α E L' index = Derive α (take (ladder_n L' index) E)" by (simp add: ladder_γ_def) have ladder_n_L'_eq_L: "ladder_n L' index = ladder_n L index" using L' index_bound ladder_n_of_cut length_L_nonzero by auto have"ladder_prev_n L (length L - 1) < n'"using finish len_L_minus_1 by blast thenhave n'_is_upper_bound: "ladder_n L (length L - 2) < n'"using index_bound by (metis diff_diff_left ladder_prev_n_def len_L_minus_1 one_add_one) have index_upper_bound: "index ≤ length L - 2"using index_bound by linarith have ladder_n_upper_bound: "ladder_n L index ≤ ladder_n L (length L - 2)" apply (rule_tac ladder_n_monotone) apply (rule_tac is_ladder_D_L) apply (rule index_upper_bound) using length_L_nonzero by linarith with n'_is_upper_bound have m_le_n': "m ≤ n'" using dual_order.strict_implies_order le_less_trans m by linarith thenhave"take m E = take m D" by (metis E le_take_same length_E_eq_n' order_refl take_all) thenhave take_helper: "(take (ladder_n L' index) E) = take m D" by (simp add: ladder_n_L'_eq_L m) thenhave Derive_eq_ψ: "Derive α (take (ladder_n L' index) E) = ψ" by (simp add: Derive LeftDerivation_implies_Derivation ψ) thenhave t1: "ladder_γ (α@δ) D L index = (ladder_γ α E L' index) @ δ" by (simp add: L'_Derive ψ) have ψ_eq: "ψ = ladder_γ α E L' index"by (simp add: Derive_eq_ψ L'_Derive) thenhave t2: "LeftDerivation α (take (ladder_n L index) D) (ladder_γ α E L' index)" using ψ m by blast have t3: "(take (ladder_n L' index) E) = take (ladder_n L index) D" by (simp add: m take_helper) have t4: "ladder_j L index < length (ladder_γ α E L' index)" using ψ ψ_eq by blast have t5: "E ! (ladder_n L' index) = D ! (ladder_n L index)" using E ladder_n_L'_eq_L ladder_n_upper_bound n'_is_upper_bound by auto note t = t1 t2 t3 t4 t5
} note ladder_early_stage = this
{ fix index :: nat assume index_bound: "index < length L" have i: "ladder_i L' index = ladder_i L index" using L' ladder_i_cut by (simp add: index_bound) have j: "ladder_j L' index = ladder_j L index" using L' ladder_j_cut by (simp add: index_bound) have ix: "index > 0 ==> ladder_ix L' index = ladder_ix L index" using L' ladder_ix_cut by (simp add: index_bound) have α: "ladder_α (α@δ) D L index = (ladder_α α E L' index) @ δ" by (simp add: index_bound ladder_α_def ladder_early_stage(1)) have i_bound: "index > 0 ==> ladder_i L' index < length (ladder_α α E L' index)" using i index_bound ladder_α_def ladder_early_stage(4) ladder_i_def by auto note ij = i j ix α i_bound
} note ladder_every_stage = this
{ fix u :: nat fix v :: nat assume u_le_v: "u ≤ v" assume v_bound: "v < length L" have"ladder_n L u ≤ ladder_n L v" using is_ladder_D_L ladder_n_monotone u_le_v v_bound by blast
} note ladder_L_n_pairwise_le = this
{ fix index :: nat assume index_lower_bound: "index > 0" assume index_upper_bound: "index + 1 < length L" note derivation = ladder_early_stage(2) have derivation1: "LeftDerivation α (take (ladder_n L (index - Suc 0)) D) (ladder_γ α E L' (index - Suc 0))" using derivation[of "index - Suc 0"] index_lower_bound index_upper_bound using One_nat_def Suc_diff_1 Suc_eq_plus1 le_less_trans lessI less_or_eq_imp_le by linarith have derivation2: "LeftDerivation α (take (ladder_n L index) D) (ladder_γ α E L' index)" using derivation[of index] index_upper_bound by blast have ladder_α_is_γ[symmetric]: "ladder_γ α E L' (index - Suc 0) = ladder_α α E L' index" using index_lower_bound ladder_α_defby auto have ladder_n_le: "ladder_n L (index - Suc 0) ≤ ladder_n L index" apply (rule_tac ladder_L_n_pairwise_le) apply arith using index_upper_bound by arith from LeftDerivation_from_in_between[OF derivation1 derivation2 ladder_n_le] ladder_α_is_γ have"LeftDerivation (ladder_α α E L' index) (drop (ladder_n L' (index - Suc 0)) (take (ladder_n L' index) E)) (ladder_γ α E L' index)" by (metis L' Suc_leI add_lessD1 index_lower_bound index_upper_bound ladder_early_stage(3)
ladder_n_of_cut le_add_diff_inverse2 length_L_nonzero length_greater_0_conv less_diff_conv)
} note LeftDerivation_delta_early = this
have LeftDerivationFix_α_0: "LeftDerivationFix α (ladder_i L' 0) (take (ladder_n L' 0) E) (ladder_j L' 0) (ladder_γ α E L' 0)" proof - have ldfix: "LeftDerivationFix (α@δ) (ladder_i L 0) (take (ladder_n L 0) D) (ladder_j L 0) (ladder_γ (α@δ) D L 0)" using LDLadder LeftDerivationLadder_def by blast have ladder_i_L': "ladder_i L' 0 = ladder_i L 0" using L' ladder_i_of_cut_at_0 length_L_nonzero by blast have ladder_j_L': "ladder_j L' 0 = ladder_j L 0" by (metis L' ladder_cut_def ladder_j_def ladder_last_j_def ladder_last_j_of_cut
length_L' length_greater_0_conv nth_list_update_neq) have"length L = 1 ∨ length L > 1"using length_L_nonzero by linarith thenshow ?thesis proof (induct rule: disjCases2) case1 from1have ladder_n_L'_0: "ladder_n L' 0 = n'" using diff_is_0_eq' ladder_last_n_L' ladder_last_n_def length_E_eq_n'
length_L' less_or_eq_imp_le by auto have take_n'_E: "take n' E = E"by (simp add: length_E_eq_n') from ladder_n_L'_0 take_n'_E have take_ladder_n_L': "take (ladder_n L' 0) E = E"by auto have"ladder_n L 0 = length D" by (simp add: "1.hyps" length_D_eq_n n_eq_ladder_n) thenhave take_ladder_n_L_0: "take (ladder_n L 0) D = D"by simp have ladder_γ_α: "ladder_γ α E L' 0 = β" apply (simp add: ladder_γ_def take_ladder_n_L') by (simp add: Derive E LeftDerivation_implies_Derivation finish) have ladder_j_in_β: "ladder_j L 0 < length β" using finish "1.hyps"by auto have ldfix_1: "LeftDerivationFix (α@δ) (ladder_i L 0) D (ladder_j L 0) (β@δ')" using"1.hyps" γ γ_ladder ldfix take_ladder_n_L_0 by auto thenhave"LeftDerivationFix α (ladder_i L 0) E (ladder_j L 0) β" by (simp add: E LeftDerivationFix_cut_appendix finish ladder_i_in_α ladder_j_in_β
length_D_eq_n) thenshow ?case by (simp add: ladder_i_L' ladder_j_L' take_ladder_n_L' ladder_γ_α) next case2 have h: "0 + 1 < length L"using"2.hyps"by auto note stage = ladder_early_stage[of 0, OF h] have ldfix0: "LeftDerivationFix (α@δ) (ladder_i L 0) (take (ladder_n L 0) D) (ladder_j L 0) ((ladder_γ α E L' 0) @ δ)" using ladder_i_L' ladder_j_L' ldfix stage(1) stage(3) by auto from LeftDerivationFix_cut_appendix'[OF ldfix0 stage(2) ladder_i_in_α stage(4)] show ?case by (simp add: ladder_i_L' ladder_j_L' stage(3)) qed qed
{ fix index :: nat assume index_bounds: "1 ≤ index ∧ index + 1 < length L" have introsAt_appendix: "LeftDerivationIntrosAt (α@δ) D L index" using LDLadder LeftDerivationIntros_def LeftDerivationLadder_def add_lessD1 index_bounds by blast have index_plus_1_upper_bound: "index + 1 < length L"using index_bounds by arith note early_stage = ladder_early_stage[of index, OF index_plus_1_upper_bound] have ladder_i_L_index_eq_fst: "ladder_i L index = fst (D ! ladder_n L (index - Suc 0))" using introsAt_appendix LeftDerivationIntrosAt_def index_bounds by (metis One_nat_def) have E_at_D_at: "(E ! ladder_n L' (index - Suc 0)) = (D ! ladder_n L (index - Suc 0))" using ladder_early_stage[of "index - Suc 0"] by (metis One_nat_def add_lessD1 index_bounds le_add_diff_inverse2) thenhave ladder_i_L'_index_eq_fst: "ladder_i L' index = fst (E ! ladder_n L' (index - Suc 0))" using index_bounds ladder_i_L_index_eq_fst ladder_every_stage(1) le_add1 le_less_trans by auto have same_derivation: "(drop (Suc (ladder_n L' (index - Suc 0))) (take (ladder_n L' index) E)) = (drop (Suc (ladder_n L (index - Suc 0))) (take (ladder_n L index) D))" using L' early_stage(3) index_bounds ladder_n_of_cut length_L_nonzero by auto have deriv_split: "(drop (ladder_n L' (index - Suc 0)) (take (ladder_n L' index) E)) = ((ladder_i L' index, snd (E ! ladder_n L' (index - Suc 0))) # drop (Suc (ladder_n L' (index - Suc 0))) (take (ladder_n L' index) E))" by (metis Cons_nth_drop_Suc One_nat_def Suc_le_lessD add_lessD1 diff_Suc_less index_bounds
ladder_i_L'_index_eq_fst ladder_n_bound ladder_n_pairwise_bound length_L'
length_take min.absorb2 nth_take prod.collapse) have"LeftDerivationIntrosAt α E L' index" apply (auto simp add: LeftDerivationIntrosAt_def Let_def) using ladder_i_L'_index_eq_fst apply blast apply (rule_tac LeftDerivationIntro_cut_appendix'[where δ=δ and δ' = δ]) apply (metis E_at_D_at LeftDerivationIntrosAt_def One_nat_def Suc_le_lessD add_lessD1
early_stage(1) index_bounds introsAt_appendix ladder_every_stage(2)
ladder_every_stage(3) ladder_every_stage(4) ladder_i_L'_index_eq_fst same_derivation) defer1 using index_bounds ladder_every_stage(5) apply auto[1] using early_stage(4) index_bounds ladder_every_stage(2) apply auto[1] using LeftDerivation_delta_early deriv_split by (metis One_nat_def Suc_le_eq index_bounds)
} note LeftDerivationIntrosAt_early = this
{ fix index :: nat assume index_bounds: "1 ≤ index ∧ index + 1 = length L" have introsAt_appendix: "LeftDerivationIntrosAt (α@δ) D L index" using LDLadder LeftDerivationIntros_def LeftDerivationLadder_def add_lessD1 index_bounds by (metis Suc_eq_plus1 not_less_eq) have ladder_i_L_index_eq_fst: "ladder_i L index = fst (D ! ladder_n L (index - Suc 0))" using introsAt_appendix LeftDerivationIntrosAt_def index_bounds by (metis One_nat_def) have E_at_D_at: "(E ! ladder_n L' (index - Suc 0)) = (D ! ladder_n L (index - Suc 0))" using ladder_early_stage[of "index - Suc 0"] by (metis One_nat_def Suc_eq_plus1 index_bounds le_add_diff_inverse2 lessI) thenhave ladder_i_L'_index_eq_fst: "ladder_i L' index = fst (E ! ladder_n L' (index - Suc 0))" using index_bounds ladder_i_L_index_eq_fst ladder_every_stage(1) le_add1 le_less_trans by auto obtain D' where D': "D' = (drop (Suc (ladder_n L (index - Suc 0))) (take (ladder_n L index) D))" by blast obtain k where k: "k = (ladder_n L' index) - (Suc (ladder_n L' (index - Suc 0)))" by blast have ladder_n_L'_index: "ladder_n L' index = length E" by (metis diff_add_inverse2 index_bounds ladder_last_n_L' ladder_last_n_def length_L') have take_is_E: "take (ladder_n L' index) E = E"by (simp add: ladder_n_L'_index) have ladder_n_L_index: "ladder_n L index = length D" by (metis diff_add_inverse2 index_bounds length_D_eq_n n_eq_ladder_n) have take_is_D: "take (ladder_n L index) D = D" by (simp add: ladder_n_L_index) have write_as_take_k_D': "(drop (Suc (ladder_n L' (index - Suc 0))) E) = take k D'" using take_is_D by (metis D' E L' One_nat_def Suc_le_lessD add_diff_cancel_right' diff_Suc_less
drop_take index_bounds k ladder_n_L'_index ladder_n_of_cut length_E_eq_n'
length_L_nonzero length_greater_0_conv) have k_bound: "k ≤ length D'" by (metis le_iff_add append_take_drop_id k ladder_n_L'_index length_append
length_drop write_as_take_k_D') have D'_alt: "D' = drop (Suc (ladder_n L (index - Suc 0))) D" by (simp add: D' take_is_D) have"LeftDerivationIntrosAt α E L' index" apply (auto simp add: LeftDerivationIntrosAt_def Let_def) using ladder_i_L'_index_eq_fst apply blast apply (subst take_is_E) apply (subst write_as_take_k_D') apply (rule_tac LeftDerivationIntro_cut_appendix[where δ=δ and δ' = δ']) apply (metis D' Derive E E_at_D_at LeftDerivationIntrosAt_def
LeftDerivation_implies_Derivation One_nat_def Suc_le_lessD add_diff_cancel_right'
diff_Suc_less finish index_bounds introsAt_appendix ladder_γ_def ladder_every_stage(2)
ladder_every_stage(3) ladder_every_stage(4) ladder_i_L'_index_eq_fst length_L_nonzero
take_is_E) apply (metis Cons_nth_drop_Suc E L' LeftDerivation_from_in_between LeftDerivation_take_derive
One_nat_def Suc_le_lessD add_diff_cancel_right' diff_Suc_less finish index_bounds
ladder_α_def ladder_γ_def ladder_i_L'_index_eq_fst ladder_n_L'_index ladder_n_of_cut
ladder_prev_n_def length_E_eq_n' length_L_nonzero less_imp_le_nat less_numeral_extra(3)
list.size(3) prod.collapse take_is_E write_as_take_k_D') using k_bound apply blast using D'_alt apply (metis (no_types, lifting) Derive E L' LeftDerivation_implies_Derivation
One_nat_def Suc_leI Suc_le_lessD add_diff_cancel_right' diff_Suc_less drop_drop finish
index_bounds k ladder_γ_def ladder_n_L'_index ladder_n_of_cut ladder_prev_n_def
le_add_diff_inverse2 length_E_eq_n' length_L_nonzero length_greater_0_conv
less_not_refl2 take_is_E) using index_bounds ladder_every_stage(5) apply auto[1] by (metis Derive E LeftDerivation_implies_Derivation One_nat_def add_diff_cancel_right'
diff_Suc_less finish index_bounds ladder_γ_def ladder_every_stage(2) length_L_nonzero
take_is_E)
} note LeftDerivationIntrosAt_last = this
have ladder_E_L': "LeftDerivationLadder α E L' β" apply (auto simp add: LeftDerivationLadder_def) using finish E apply blast using is_ladder_E_L' apply blast using LeftDerivationFix_α_0apply blast using LeftDerivationIntros_def LeftDerivationIntrosAt_early LeftDerivationIntrosAt_last by (metis Suc_eq_plus1 Suc_leI le_neq_implies_less length_L')
show ?thesis apply (rule_tac x=E in exI) apply (rule_tac x=F in exI) apply (rule_tac x=β in exI) apply (rule_tac x=δ' in exI) apply (rule_tac x=L' in exI) apply auto using E F apply simp apply (rule γ) using ladder_E_L' apply blast using F finish apply blast using F finish apply blast by (rule L') qed
theorem LeftDerivationLadder_cut_appendix: assumes LDLadder: "LeftDerivationLadder (α@δ) D L γ" assumes ladder_i_in_α: "ladder_i L 0 < length α" shows"∃ E F γ1 γ2 L'. D = E@F ∧ γ = γ1 @ γ2 ∧ LeftDerivationLadder α E L' γ1 ∧ derivation_ge F (length γ1) ∧ LeftDerivation δ (derivation_shift F (length γ1) 0) γ2 ∧ length L' = length L ∧ ladder_i L' 0 = ladder_i L 0 ∧ ladder_last_j L' = ladder_last_j L" proof - from LeftDerivationLadder_cut_appendix_helper[OF LDLadder ladder_i_in_α] obtain E F γ1 γ2 L' where helper: "D = E @ F ∧ γ = γ1 @ γ2 ∧ LeftDerivationLadder α E L' γ1 ∧ derivation_ge F (length γ1) ∧ LeftDerivation δ (derivation_shift F (length γ1) 0) γ2 ∧ L' = ladder_cut L (length E)" by blast show ?thesis apply (rule_tac x=E in exI) apply (rule_tac x=F in exI) apply (rule_tac x=γ1in exI) apply (rule_tac x=γ2in exI) apply (rule_tac x=L' in exI) using helper LDLadder LeftDerivationLadder_def is_ladder_def ladder_i_of_cut_at_0
ladder_last_j_of_cut length_ladder_cut by force qed
definition ladder_stepdown_diff :: "ladder ==> nat"where "ladder_stepdown_diff L = Suc (ladder_n L 0)"
definition ladder_stepdown_α_0 :: "sentence ==> derivation ==> ladder ==> sentence"where "ladder_stepdown_α_0 a D L = Derive a (take (ladder_stepdown_diff L) D)"
lemma LeftDerivationIntro_LeftDerives1: assumes"LeftDerivationIntro α i r ix D j γ" assumes"splits_at α i a1 A a2" shows"LeftDerives1 α i r (a1@(snd r)@a2)" by (metis LeftDerivationIntro_def LeftDerivationIntro_examine_rule LeftDerivationIntro_is_sentence
LeftDerives1_def assms(1) assms(2) prod.collapse splits_at_implies_Derives1)
lemma LeftDerives1_Derive: assumes"LeftDerives1 α i r γ" shows"Derive α [(i, r)] = γ" by (metis Derive LeftDerivation.simps(1) LeftDerivation_LeftDerives1
LeftDerivation_implies_Derivation append_Nil assms)
lemma ladder_stepdown_α_0_altdef: assumes ladder: "LeftDerivationLadder α D L γ" assumes length_L: "length L > 1" assumes split: "splits_at (ladder_α α D L 1) (ladder_i L 1) a1 A a2" shows"ladder_stepdown_α_0 α D L = a1 @ (snd (snd (D ! (ladder_n L 0)))) @ a2" proof - have1: "ladder_α α D L 1 = Derive α (take (ladder_n L 0) D)" by (simp add: ladder_α_def ladder_γ_def) obtain rule where rule: "rule = snd (D ! (ladder_n L 0))"by blast have"∃ E ψ. LeftDerivationIntro (ladder_α α D L 1) (ladder_i L 1) rule (ladder_ix L 1) E (ladder_j L 1) ψ" by (metis LeftDerivationIntrosAt_def LeftDerivationIntros_def LeftDerivationLadder_def
One_nat_def diff_Suc_1 ladder length_L order_refl rule) thenobtain E ψ where intro: "LeftDerivationIntro (ladder_α α D L 1) (ladder_i L 1) rule (ladder_ix L 1) E (ladder_j L 1) ψ" by blast thenhave2: "LeftDerives1 (ladder_α α D L 1) (ladder_i L 1) rule (a1@(snd rule)@a2)" using LeftDerivationIntro_LeftDerives1 split by blast have fst_D: "fst (D ! (ladder_n L 0)) = ladder_i L 1" by (metis LeftDerivationIntrosAt_def LeftDerivationIntros_def LeftDerivationLadder_def
One_nat_def diff_Suc_1 ladder le_numeral_extra(4) length_L) have derive_derive: "Derive α (take (Suc (ladder_n L 0)) D) = Derive (Derive α (take (ladder_n L 0) D)) [D ! (ladder_n L 0)]" proof - have f1: "Derivation α (take (Suc (ladder_n L 0)) D) (Derive α (take (Suc (ladder_n L 0)) D))" using Derivation_take_derive LeftDerivationLadder_def LeftDerivation_implies_Derivation ladder by blast have f2: "length L - 1 < length L" using length_L by linarith have"0 < length L - 1" using length_L by linarith thenhave f3: "take (Suc (ladder_n L 0)) D = take (ladder_n L 0) D @ [D ! ladder_n L 0]" using f2 by (metis (full_types) LeftDerivationLadder_def is_ladder_def ladder ladder_last_n_def take_Suc_conv_app_nth) obtain sss :: "symbol list ==> (nat × symbol × symbol list) list ==> (nat × symbol × symbol list) list ==> symbol list ==> symbol list"where "∀x0 x1 x2 x3. (∃v4. Derivation x3 x2 v4 ∧ Derivation v4 x1 x0) = (Derivation x3 x2 (sss x0 x1 x2 x3) ∧ Derivation (sss x0 x1 x2 x3) x1 x0)" by moura thenshow ?thesis using f3 f1 Derivation_append Derive by auto qed thenhave3: "ladder_stepdown_α_0 α D L = Derive (ladder_α α D L 1) [D ! (ladder_n L 0)]" using1by (simp add: ladder_stepdown_α_0_def ladder_stepdown_diff_def) have4: "D ! (ladder_n L 0) = (ladder_i L 1, rule)" using rule fst_D by (metis prod.collapse) thenshow ?thesis using234 LeftDerives1_Derive snd_conv by auto qed
lemma ladder_i_0_bound: assumes ld: "LeftDerivationLadder α D L γ" shows"ladder_i L 0 < length α" proof - have"LeftDerivationFix α (ladder_i L 0) (take (ladder_n L 0) D) (ladder_j L 0) (ladder_γ α D L 0)" using ld LeftDerivationLadder_def by simp thenshow ?thesis using LeftDerivationFix_def by simp qed
lemma ladder_j_bound: assumes ld: "LeftDerivationLadder α D L γ" assumes index_bound: "index < length L" shows"ladder_j L index < length (ladder_γ α D L index)" proof - have ld': "LeftDerivationLadder (α@[]) D L γ"using ld by simp have ladder_i_0: "ladder_i L 0 < length α"using ladder_i_0_bound ld by auto obtain n where n: "n = ladder_n L index"by blast note propagate = LeftDerivationLadder_propagate[OF ld' ladder_i_0 n index_bound] from index_bound have"index + 1 < length L ∨ index + 1 = length L"by arith thenshow ?thesis proof (induct rule: disjCases2) case1 thenhave"∃β. LeftDerivation α (take n D) β ∧ ladder_γ (α @ []) D L index = β @ [] ∧ ladder_j L index < length β" using propagate by auto thenshow ?caseby auto next case2 thenhave" ∃n' β δ'. (index = 0 ∨ ladder_prev_n L index < n') ∧ n' ≤ n ∧ LeftDerivation α (take n' D) β ∧ LeftDerivation (α @ []) (take n' D) (β @ []) ∧ derivation_ge (drop n' D) (length β) ∧ LeftDerivation [] (derivation_shift (drop n' D) (length β) 0) δ' ∧ ladder_γ (α @ []) D L index = β @ δ' ∧ ladder_j L index < length β" using propagate by auto thenshow ?caseby auto qed qed
lemma ladder_last_j_bound: assumes ld: "LeftDerivationLadder α D L γ" shows"ladder_last_j L < length γ" proof - have"length L - 1 < length L" using LeftDerivationLadder_def assms is_ladder_def by auto from ladder_j_bound[OF ld this] show ?thesis by (metis Derive LeftDerivationLadder_def LeftDerivation_implies_Derivation One_nat_def
is_ladder_def ladder_last_j_def last_ladder_γ ld) qed
fun ladder_shift_n :: "nat ==> ladder ==> ladder"where "ladder_shift_n N [] = []"
| "ladder_shift_n N ((n, j, i)#L) = ((n - N, j, i)#(ladder_shift_n N L))"
lemma ladder_shift_n_length: "length (ladder_shift_n N L) = length L" by (induct L, auto)
lemma ladder_stepdown_prepare: assumes"length L > 1" shows"L = (ladder_n L 0, ladder_j L 0, ladder_i L 0)# (ladder_n L 1, ladder_j L 1, ladder_ix L 1)#(drop 2 L)" proof - have"∃ n0 j0 i0 n1 j1 ix1 L'. L = ((n0, j0, i0)#(n1, j1, ix1)#L')" by (metis One_nat_def Suc_eq_plus1 assms ladder_stepdown.cases less_not_refl list.size(3)
list.size(4) not_less0) thenobtain n0 j0 i0 n1 j1 ix1 L' where L': "L = ((n0, j0, i0)#(n1, j1, ix1)#L')"by blast have n0: "n0 = ladder_n L 0"using L' by (auto simp add: ladder_n_def deriv_n_def) show ?thesis using L' by (auto simp add: ladder_n_def deriv_n_def ladder_j_def deriv_j_def
ladder_i_def deriv_i_def ladder_ix_def deriv_ix_def) qed
lemma ladder_stepdown_length: assumes"length L > 1" shows"length (ladder_stepdown L) = length L - 1" apply (subst ladder_stepdown_prepare[OF assms(1)]) apply (simp add: ladder_shift_n_length) using assms apply arith done
lemma ladder_stepdown_i_0: assumes"length L > 1" shows"ladder_i (ladder_stepdown L) 0 = ladder_i L 1 + ladder_ix L 1" using ladder_stepdown_prepare[OF assms] ladder_i_def ladder_j_def deriv_j_def by (metis One_nat_def deriv_i_def diff_Suc_1 ladder_stepdown.simps(3) list.sel(1)
snd_conv zero_neq_one)
lemma ladder_shift_n_cons: "ladder_shift_n N (x#L) = (fst x - N, snd x)#(ladder_shift_n N L)" apply (induct L) by (cases x, simp)+
lemma ladder_shift_n_drop: "ladder_shift_n N (drop n L) = drop n (ladder_shift_n N L)" proof (induct L arbitrary: n) case Nil thenshow ?caseby simp next case (Cons x L) show ?case proof (cases n) case0thenshow ?thesis by simp next case (Suc n) thenshow ?thesis by (simp add: ladder_shift_n_cons Cons) qed qed
lemma drop_2_shift: assumes"index > 0" assumes"length L > 1" shows"drop 2 L ! (index - Suc 0) = L ! Suc index" proof - define l1 l2 and L' where"l1 = L ! 0""l2 = L ! 1" and"L' = drop 2 L" with‹length L > 1›have"L = l1 # l2 # L'" by (cases L) (auto simp add: neq_Nil_conv) with‹index > 0›show ?thesis by simp qed
lemma ladder_shift_n_at: "index < length L ==> (ladder_shift_n N L) ! index = (fst (L ! index) - N, snd (L ! index))" proof (induct L arbitrary: index) case Nil thenshow ?caseby auto next case (Cons x L) show ?case apply (simp add: ladder_shift_n_cons) apply (cases index) apply (auto) apply (rule_tac Cons(1)) using Cons(2) by auto qed
lemma ladder_stepdown_j: assumes length_L_greater_1: "length L > 1" assumes L': "L' = ladder_stepdown L" assumes index_bound: "index < length L'" shows"ladder_j L' index = ladder_j L (Suc index)" proof - note L_prepare = ladder_stepdown_prepare[OF length_L_greater_1] have ladder_stepdown_L_def: "ladder_stepdown L = ((ladder_n L (Suc 0) - Suc (ladder_n L 0), ladder_j L (Suc 0), ladder_j L 0 + ladder_ix L (Suc 0)) # ladder_shift_n (Suc (ladder_n L 0)) (drop 2 L))" by (subst L_prepare, simp) have"index = 0 ∨ index > 0"by arith thenshow"ladder_j L' index = ladder_j L (Suc index)" proof (induct rule: disjCases2) case1 show ?case by (simp add: L' ladder_stepdown_L_def 1 ladder_j_def deriv_j_def) next case2 have index_bound': "Suc index < length L" using index_bound L' ladder_stepdown_length length_L_greater_1 by auto show ?case apply (simp add: L' ladder_stepdown_L_def 2 ladder_j_def ladder_shift_n_drop drop_2_shift) apply (subst drop_2_shift) apply (simp add: 2) using length_L_greater_1 apply (simp add: ladder_shift_n_length) apply (simp add: deriv_j_def) apply (simp add: ladder_shift_n_at[OF index_bound']) done qed qed
lemma ladder_stepdown_last_j: assumes length_L_greater_1: "length L > 1" shows"ladder_last_j (ladder_stepdown L) = ladder_last_j L" using ladder_stepdown_j Suc_diff_Suc diff_Suc_1 ladder_last_j_def ladder_stepdown_length
length_L_greater_1 lessI by auto
lemma ladder_stepdown_n: assumes length_L_greater_1: "length L > 1" assumes L': "L' = ladder_stepdown L" assumes index_bound: "index < length L'" shows"ladder_n L' index = ladder_n L (Suc index) - ladder_stepdown_diff L" proof - note L_prepare = ladder_stepdown_prepare[OF length_L_greater_1] have ladder_stepdown_L_def: "ladder_stepdown L = ((ladder_n L (Suc 0) - Suc (ladder_n L 0), ladder_j L (Suc 0), ladder_j L 0 + ladder_ix L (Suc 0)) # ladder_shift_n (Suc (ladder_n L 0)) (drop 2 L))" by (subst L_prepare, simp) have"index = 0 ∨ index > 0"by arith thenshow"ladder_n L' index = ladder_n L (Suc index) - ladder_stepdown_diff L" proof (induct rule: disjCases2) case1 show ?case by (simp add: L' ladder_stepdown_L_def 1 ladder_n_def deriv_n_def ladder_stepdown_diff_def) next case2 have index_bound': "Suc index < length L" using index_bound L' ladder_stepdown_length length_L_greater_1 by auto show ?case apply (simp add: L' ladder_stepdown_L_def 2 ladder_n_def ladder_shift_n_drop drop_2_shift
ladder_stepdown_diff_def) apply (subst drop_2_shift) apply (simp add: 2) using length_L_greater_1 apply (simp add: ladder_shift_n_length) apply (simp add: deriv_n_def) apply (simp add: ladder_shift_n_at[OF index_bound']) done qed qed
lemma ladder_stepdown_ix: assumes length_L_greater_1: "length L > 1" assumes L': "L' = ladder_stepdown L" assumes index_lower_bound: "0 < index" assumes index_upper_bound: "index < length L'" shows"ladder_ix L' index = ladder_ix L (Suc index)" proof - note L_prepare = ladder_stepdown_prepare[OF length_L_greater_1] have ladder_stepdown_L_def: "ladder_stepdown L = ((ladder_n L (Suc 0) - Suc (ladder_n L 0), ladder_j L (Suc 0), ladder_j L 0 + ladder_ix L (Suc 0)) # ladder_shift_n (Suc (ladder_n L 0)) (drop 2 L))" by (subst L_prepare, simp)
have index_bound': "Suc index < length L" using index_upper_bound L' ladder_stepdown_length length_L_greater_1 by auto show ?thesis apply (simp add: L' ladder_stepdown_L_def index_lower_bound ladder_ix_def ladder_shift_n_drop) apply (subst drop_2_shift) apply (simp add: index_lower_bound) using length_L_greater_1 apply (simp add: ladder_shift_n_length) apply (simp add: deriv_ix_def) apply (simp add: ladder_shift_n_at[OF index_bound']) using index_lower_bound by arith qed
lemma Derive_Derive: assumes"Derivation α (D@E) γ" shows"Derive (Derive α D) E = Derive α (D@E)" using Derivation_append Derive assms by fastforce
lemma drop_at_shift: assumes"n ≤ index" assumes"index < length D" shows"drop n D ! (index - n) = D ! index" using assms(1) assms(2) by auto
theorem LeftDerivationLadder_stepdown: assumes ldl: "LeftDerivationLadder α D L γ" assumes length_L: "length L > 1" shows"∃ L'. LeftDerivationLadder (ladder_stepdown_α_0 α D L) (drop (ladder_stepdown_diff L) D) L' γ ∧ length L' = length L - 1 ∧ ladder_i L' 0 = ladder_i L 1 + ladder_ix L 1 ∧ ladder_last_j L' = ladder_last_j L" proof - obtain L' where L': "L' = ladder_stepdown L"by blast have ldl1: "LeftDerivation (ladder_stepdown_α_0 α D L) (drop (ladder_stepdown_diff L) D) γ" proof - have D_split: "D = (take (ladder_stepdown_diff L) D) @ (drop (ladder_stepdown_diff L) D)" by simp show ?thesis using D_split ldl proof - obtain sss :: "symbol list ==> (nat × symbol × symbol list) list ==> (nat × symbol × symbol list) list ==> symbol list ==> symbol list"where "∀x0 x1 x2 x3. (∃v4. LeftDerivation x3 x2 v4 ∧ LeftDerivation v4 x1 x0) = (LeftDerivation x3 x2 (sss x0 x1 x2 x3) ∧ LeftDerivation (sss x0 x1 x2 x3) x1 x0)" by moura thenhave"(¬ LeftDerivation α (take (ladder_stepdown_diff L) D @ drop (ladder_stepdown_diff L) D) γ ∨ LeftDerivation α (take (ladder_stepdown_diff L) D) (sss γ (drop (ladder_stepdown_diff L) D) (take (ladder_stepdown_diff L) D) α) ∧ LeftDerivation (sss γ (drop (ladder_stepdown_diff L) D) (take (ladder_stepdown_diff L) D) α) (drop (ladder_stepdown_diff L) D) γ) ∧ (LeftDerivation α (take (ladder_stepdown_diff L) D @ drop (ladder_stepdown_diff L) D) γ ∨ (∀ss. ¬ LeftDerivation α (take (ladder_stepdown_diff L) D) ss ∨¬ LeftDerivation ss (drop (ladder_stepdown_diff L) D) γ))" using LeftDerivation_append by blast thenshow ?thesis by (metis (no_types) D_split Derivation_take_derive Derivation_unique_dest LeftDerivationLadder_def LeftDerivation_implies_Derivation ladder_stepdown_α_0_def ldl) qed qed have L'_nonempty: "L' ≠ []"using L' ladder_stepdown_length length_L by fastforce
{ fix u :: nat assume u': "u < length L'" thenhave Suc_u: "Suc u < length L"using L' ladder_stepdown_length length_L by auto have"ladder_n L (Suc u) ≤ length D" using ldl Suc_u by (simp add: LeftDerivationLadder_ladder_n_bound) thenhave"ladder_n L' u ≤ length D - ladder_stepdown_diff L" apply (subst ladder_stepdown_n[OF length_L L' u']) by auto
} note is_ladder_prop1 = this
{ fix u :: nat fix v :: nat assume u_less_v: "u < v" assume v_L': "v < length L'" from u_less_v v_L' have u_L': "u < length L'"by arith have"ladder_n L (Suc u) < ladder_n L (Suc v)" using ldl by (metis (no_types, lifting) L' LeftDerivationLadder_def One_nat_def Suc_diff_1
Suc_lessD Suc_mono is_ladder_def ladder_stepdown_length length_L u_less_v v_L') thenhave"ladder_n L' u < ladder_n L' v" apply (simp add: ladder_stepdown_n[OF length_L L'] u_L' v_L') by (metis (no_types, lifting) L' LeftDerivationLadder_def Suc_eq_plus1 Suc_leI
diff_less_mono is_ladder_def ladder_stepdown_diff_def ladder_stepdown_length ldl
length_L less_diff_conv u_L' zero_less_Suc)
} note is_ladder_prop2 = this have is_ladder_L': "is_ladder (drop (ladder_stepdown_diff L) D) L'" apply (auto simp add: is_ladder_def) using L'_nonempty apply blast using is_ladder_prop1 apply blast using is_ladder_prop2 apply blast using ladder_last_n_def ladder_stepdown_n L' LeftDerivationLadder_def Suc_diff_Suc diff_Suc_1
ladder_n_last_is_length ladder_stepdown_length ldl length_L lessI by auto have ldfix: "LeftDerivationFix (ladder_stepdown_α_0 α D L) (ladder_i L' 0) (take (ladder_n L' 0) (drop (ladder_stepdown_diff L) D)) (ladder_j L' 0) (ladder_γ (ladder_stepdown_α_0 α D L) (drop (ladder_stepdown_diff L) D) L' 0)" proof - have introsAt_L_1: "LeftDerivationIntrosAt α D L 1" using LeftDerivationIntros_def LeftDerivationLadder_def ldl length_L by blast thm LeftDerivationIntrosAt_def obtain n where n: "n = ladder_n L 0"by blast obtain m where m: "m = ladder_n L 1"by blast have"LeftDerivationIntro (ladder_α α D L 1) (ladder_i L 1) (snd (D ! n)) (ladder_ix L 1) (drop (Suc n) (take m D)) (ladder_j L 1) (ladder_γ α D L 1)" using n m introsAt_L_1 by (metis LeftDerivationIntrosAt_def One_nat_def diff_Suc_1) from iffD1[OF LeftDerivationIntro_def this] obtain β where β: "LeftDerives1 (ladder_α α D L 1) (ladder_i L 1) (snd (D ! n)) β ∧ ladder_ix L 1 < length (snd (snd (D ! n))) ∧ snd (snd (D ! n)) ! ladder_ix L 1 = ladder_γ α D L 1 ! ladder_j L 1 ∧ LeftDerivationFix β (ladder_i L 1 + ladder_ix L 1) (drop (Suc n) (take m D)) (ladder_j L 1) (ladder_γ α D L 1)" by blast have"β = Derive (ladder_α α D L 1) [D ! n]" by (metis (no_types, opaque_lifting) LeftDerivationIntrosAt_def LeftDerives1_Derive β
cancel_comm_monoid_add_class.diff_cancel introsAt_L_1 n prod.collapse) thenhave β_def: "β = ladder_stepdown_α_0 α D L" proof - obtain sss :: "nat ==> symbol list ==> symbol list"and ss :: "nat ==> symbol list ==>symbol"and sssa :: "nat ==> symbol list ==> symbol list"where "∀x2 x3. (∃v4 v5 v6. splits_at x3 x2 v4 v5 v6) = splits_at x3 x2 (sss x2 x3) (ss x2 x3) (sssa x2 x3)" by moura thenhave f1: "∀ssa n p ssb. ¬ Derives1 ssa n p ssb ∨ splits_at ssa n (sss n ssa) (ss n ssa) (sssa n ssa)" using splits_at_ex by presburger thenhave"β = sss (ladder_i L 1) (ladder_α α D L 1) @ snd (snd (D ! n)) @ sssa (ladder_i L 1) (ladder_α α D L 1)" by (meson LeftDerives1_implies_Derives1 β splits_at_combine_dest) thenshow ?thesis using f1 by (metis (no_types) LeftDerives1_implies_Derives1 β ladder_stepdown_α_0_altdef ldl length_L n) qed have ladder_i_L'_0: "ladder_i L' 0 = ladder_i L 1 + ladder_ix L 1" using L' ladder_stepdown_i_0 length_L by blast have derivation_eq: "(take (ladder_n L' 0) (drop (ladder_stepdown_diff L) D)) = (drop (Suc n) (take m D))"using n m by (metis L' L'_nonempty One_nat_def drop_take ladder_stepdown_diff_def ladder_stepdown_n
length_L length_greater_0_conv) have ladder_j_L'_0: "ladder_j L' 0 = ladder_j L 1" using L' L'_nonempty ladder_stepdown_j length_L by auto have ladder_γ: "(ladder_γ (ladder_stepdown_α_0 α D L) (drop (ladder_stepdown_diff L) D) L' 0) = ladder_γ α D L 1" by (metis Derivation_take_derive Derivation_unique_dest LeftDerivationFix_def
LeftDerivation_implies_Derivation β β_def derivation_eq ladder_γ_def ldl1) from β_def β ladder_i_L'_0 derivation_eq ladder_j_L'_0 ladder_γ show ?thesis by auto qed
{ fix index :: nat assume index_lower_bound: "Suc 0 ≤ index" assume index_upper_bound: "index < length L'" thenhave Suc_index_upper_bound: "Suc index < length L" using L' Suc_diff_Suc Suc_less_eq diff_Suc_1 ladder_stepdown_length length_L less_Suc_eq by auto thenhave intros_at_Suc_index: "LeftDerivationIntrosAt α D L (Suc index)" by (metis LeftDerivationIntros_def LeftDerivationLadder_def Suc_eq_plus1_left ldl le_add1) from iffD1[OF LeftDerivationIntrosAt_def this] have ldintro: "let α' = ladder_α α D L (Suc index); i = ladder_i L (Suc index); j = ladder_j L (Suc index); ix = ladder_ix L (Suc index); γ = ladder_γ α D L (Suc index); n = ladder_n L (Suc index - 1); m = ladder_n L (Suc index); e = D ! n; E = drop (Suc n) (take m D) in i = fst e ∧ LeftDerivationIntro α' i (snd e) ix E j γ"by blast have index_minus_Suc_0_bound: "index - Suc 0 < length L'" by (simp add: index_upper_bound less_imp_diff_less) note helpers = length_L L' index_minus_Suc_0_bound have ladder_i_L'_index: "ladder_i L' index = fst (drop (ladder_stepdown_diff L) D ! ladder_n L' (index - Suc 0))" apply (auto simp add: ladder_i_def) using index_lower_bound apply arith apply (simp add: ladder_stepdown_n[OF helpers] ladder_stepdown_j[OF helpers]) apply (subst drop_at_shift) using LeftDerivationLadder_def Suc_index_upper_bound Suc_leI Suc_lessD is_ladder_def
ladder_stepdown_diff_def ldl apply presburger apply (metis LeftDerivationLadder_def One_nat_def Suc_eq_plus1 Suc_index_upper_bound
add.commute add_diff_cancel_right' ladder_n_minus_1_bound ldl le_add1) by (metis LeftDerivationIntrosAt_def intros_at_Suc_index diff_Suc_1 ladder_i_def nat.simps(3)) have intro_at_index: "LeftDerivationIntro (ladder_α (ladder_stepdown_α_0 α D L) (drop (ladder_stepdown_diff L) D) L' index) (ladder_i L' index) (snd (drop (ladder_stepdown_diff L) D ! ladder_n L' (index - Suc 0))) (ladder_ix L' index) (drop (Suc (ladder_n L' (index - Suc 0))) (take (ladder_n L' index) (drop (ladder_stepdown_diff L) D))) (ladder_j L' index) (ladder_γ (ladder_stepdown_α_0 α D L) (drop (ladder_stepdown_diff L) D) L' index)" proof - have arg1: "(ladder_α (ladder_stepdown_α_0 α D L) (drop (ladder_stepdown_diff L) D) L' index) = ladder_α α D L (Suc index)" apply (auto simp add: ladder_α_def ladder_γ_def) using index_lower_bound apply arith apply (simp add: ladder_stepdown_n[OF helpers] ladder_stepdown_α_0_def) apply (subst Derive_Derive[where γ="ladder_γ α D L index"]) apply (metis (no_types, lifting) Derivation_take_derive LeftDerivationLadder_def
LeftDerivation_implies_Derivation Suc_index_upper_bound Suc_leI Suc_lessD
add.commute is_ladder_def ladder_γ_def ladder_stepdown_diff_def ldl
le_add_diff_inverse2 take_add) by (metis LeftDerivationLadder_def Suc_index_upper_bound Suc_leI Suc_lessD add.commute
is_ladder_def ladder_stepdown_diff_def ldl le_add_diff_inverse2 take_add) have arg2: "ladder_i L' index = ladder_i L (Suc index)" using L' index_lower_bound index_minus_Suc_0_bound ladder_i_def ladder_stepdown_j
length_L by auto obtain n where n: "n = ladder_n L (Suc index - 1)"by blast have arg3: "(snd (drop (ladder_stepdown_diff L) D ! ladder_n L' (index - Suc 0))) = snd (D ! n)" apply (simp add: ladder_stepdown_n[OF helpers] index_lower_bound) apply (subst drop_at_shift) using index_lower_bound apply (metis (no_types, opaque_lifting) L' LeftDerivationLadder_def One_nat_def Suc_eq_plus1
add.commute diff_Suc_1 index_upper_bound is_ladder_def ladder_stepdown_diff_def
ladder_stepdown_length ldl le_add_diff_inverse2 length_L less_or_eq_imp_le n
nat.simps(3) neq0_conv not_less not_less_eq_eq) using index_lower_bound apply (metis LeftDerivationLadder_def One_nat_def Suc_index_upper_bound Suc_le_lessD
Suc_pred diff_Suc_1 ladder_n_minus_1_bound ldl le_imp_less_Suc less_imp_le) using index_lower_bound n by (simp add: Suc_diff_le) have arg4: "ladder_ix L' index = ladder_ix L (Suc index)" using ladder_stepdown_ix L' Suc_le_lessD index_lower_bound index_upper_bound length_L by auto obtain m where m: "m = ladder_n L (Suc index)"by blast have Suc_index_Suc: "Suc (index - Suc 0) = index" using index_lower_bound by arith have arg5: "(drop (Suc (ladder_n L' (index - Suc 0))) (take (ladder_n L' index) (drop (ladder_stepdown_diff L) D))) = drop (Suc n) (take m D)" apply (simp add: ladder_stepdown_n[OF helpers]
ladder_stepdown_n[OF length_L L' index_upper_bound] n m Suc_index_Suc) by (metis (no_types, lifting) LeftDerivationLadder_def Suc_eq_plus1_left
Suc_index_upper_bound Suc_leI Suc_le_lessD Suc_lessD drop_drop drop_take
index_lower_bound is_ladder_def ladder_stepdown_diff_def ldl le_add_diff_inverse2) have arg6: "ladder_j L' index = ladder_j L (Suc index)" using L' index_upper_bound ladder_stepdown_j length_L by blast have arg7: "(ladder_γ (ladder_stepdown_α_0 α D L) (drop (ladder_stepdown_diff L) D) L' index) = ladder_γ α D L (Suc index)" apply (simp add: ladder_γ_def) apply (simp add: ladder_stepdown_n[OF length_L L' index_upper_bound] ladder_stepdown_α_0_def) apply (subst Derive_Derive[where γ="ladder_γ α D L (Suc index)"]) apply (metis (no_types, lifting) L' LeftDerivationLadder_def
LeftDerivation_implies_Derivation LeftDerivation_take_derive Suc_le_lessD
add_diff_inverse_nat diff_is_0_eq index_lower_bound index_upper_bound is_ladder_L'
is_ladder_def ladder_γ_def ladder_stepdown_n ldl le_0_eq length_L less_numeral_extra(3)
less_or_eq_imp_le take_add) by (metis (no_types, lifting) L' One_nat_def add_diff_inverse_nat diff_is_0_eq
index_lower_bound index_upper_bound is_ladder_L' is_ladder_def ladder_stepdown_n le_0_eq
le_neq_implies_less length_L less_numeral_extra(3) less_or_eq_imp_le take_add zero_less_one) from ldintro arg1 arg2 arg3 arg4 arg5 arg6 arg7 show ?thesis by (metis m n) qed have"LeftDerivationIntrosAt (ladder_stepdown_α_0 α D L) (drop (ladder_stepdown_diff L) D) L' index" apply (auto simp add: LeftDerivationIntrosAt_def Let_def) using ladder_i_L'_index apply blast using intro_at_index by blast
} note introsAt = this show ?thesis apply (rule_tac x="L'"in exI) apply auto defer1 using L' ladder_stepdown_length length_L apply auto[1] using ladder_stepdown_i_0 length_L L' apply auto[1] using ladder_stepdown_last_j L' length_L apply auto[1] apply (auto simp add: LeftDerivationLadder_def) using ldl1 apply blast using is_ladder_L' apply blast using ldfix apply blast apply (auto simp add: LeftDerivationIntros_def) apply (simp add: introsAt) done qed
fun ladder_shift_j :: "nat ==> ladder ==> ladder"where "ladder_shift_j d [] = []"
| "ladder_shift_j d ((n, j, i)#L) = ((n, j - d, i)#(ladder_shift_j d L))"
definition ladder_cut_prefix :: "nat ==> ladder ==> ladder" where "ladder_cut_prefix d L = (ladder_shift_j d L)[0 := (ladder_n L 0, ladder_j L 0 - d, ladder_i L 0 - d)]"
lemma ladder_shift_j_length: "length (ladder_shift_j d L) = length L" by (induct L, auto)
lemma ladder_shift_j_cons: "ladder_shift_j d (x#L) = (fst x, fst (snd x) - d, snd(snd x))# (ladder_shift_j d L)" apply (induct L) by (cases x, simp)+
lemma deriv_j_ladder_shift_j: "index < length L ==> deriv_j (ladder_shift_j d L ! index) = deriv_j (L ! index) - d" proof (induct L arbitrary: index) case Nil thenshow ?caseby auto next case (Cons x L) show ?case apply (subst ladder_shift_j_cons) apply (cases index) using Cons by (auto simp add: deriv_j_def) qed
lemma deriv_n_ladder_shift_j: "index < length L ==> deriv_n (ladder_shift_j d L ! index) = deriv_n (L ! index)" proof (induct L arbitrary: index) case Nil thenshow ?caseby auto next case (Cons x L) show ?case apply (subst ladder_shift_j_cons) apply (cases index) using Cons by (auto simp add: deriv_n_def) qed
lemma deriv_ix_ladder_shift_j: "index < length L ==> deriv_ix (ladder_shift_j d L ! index) = deriv_ix (L ! index)" proof (induct L arbitrary: index) case Nil thenshow ?caseby auto next case (Cons x L) show ?case apply (subst ladder_shift_j_cons) apply (cases index) using Cons by (auto simp add: deriv_ix_def) qed
lemma ladder_cut_prefix_j: assumes index_bound: "index < length L" assumes length_L: "length L > 0" shows"ladder_j (ladder_cut_prefix d L) index = ladder_j L index - d" apply (simp add: ladder_j_def ladder_cut_prefix_def) apply (cases index) apply (auto simp add: length_L) apply (subst nth_list_update_eq) apply (simp only: ladder_shift_j_length length_L) apply (simp add: deriv_j_def) apply (subst deriv_j_ladder_shift_j) using index_bound apply arith by blast
lemma hd_0_subst: "length L > 0 ==> hd (L [0 := x]) = x" using hd_conv_nth by (simp add: upd_conv_take_nth_drop)
lemma ladder_cut_prefix_i: assumes index_bound: "index < length L" assumes length_L: "length L > 0" shows"ladder_i (ladder_cut_prefix d L) index = ladder_i L index - d" apply (simp add: ladder_i_def ladder_cut_prefix_def) apply (cases index) apply auto[1] apply (subst hd_0_subst) using length_L ladder_shift_j_length apply metis apply (auto simp add: deriv_i_def) apply (case_tac nat) apply (simp add: ladder_j_def deriv_j_def) apply auto apply (subst nth_list_update_eq) using length_L ladder_shift_j_length apply auto[1] apply simp apply (simp add: ladder_j_def) apply (subst deriv_j_ladder_shift_j) using index_bound apply arith apply simp done
lemma ladder_cut_prefix_n: assumes index_bound: "index < length L" assumes length_L: "length L > 0" shows"ladder_n (ladder_cut_prefix d L) index = ladder_n L index" apply (simp add: ladder_cut_prefix_def) apply (cases index) apply (auto simp add: ladder_n_def) apply (subst nth_list_update_eq) apply (simp add: ladder_shift_j_length) using length_L apply blast apply (simp add: deriv_n_def ) apply (rule_tac deriv_n_ladder_shift_j) using index_bound by arith
lemma ladder_cut_prefix_ix: assumes index_bound: "index < length L" assumes length_L: "length L > 0" shows"ladder_ix (ladder_cut_prefix d L) index = ladder_ix L index" apply (simp add: ladder_cut_prefix_def) apply (cases index) apply (auto simp add: ladder_ix_def) apply (rule_tac deriv_ix_ladder_shift_j) using index_bound by arith
lemma LeftDerivationFix_derivation_ge_is_nonterminal: assumes ldfix: "LeftDerivationFix α i D j γ" assumes derivation_ge_d: "derivation_ge D d" assumes is_nonterminal: "is_nonterminal (γ ! j)" shows"(D = [] ∧ α = γ ∧ i = j) ∨ (i > d ∧ j ≥ d)" proof - have"is_nonterminal (α ! i)"using ldfix is_nonterminal by (simp add: LeftDerivationFix_def) from LeftDerivationFix_splits_at_nonterminal[OF ldfix this] obtain U a1 a2 b1 where U: "splits_at α i a1 U a2 ∧ splits_at γ j b1 U a2 ∧ LeftDerivation a1 D b1"by blast have"D = [] ∨ D ≠ []"by auto thenshow ?thesis proof (induct rule: disjCases2) case1 thenhave"a1 = b1"using U by auto thenhave i_eq_j: "i = j"using U by (metis dual_order.strict_implies_order length_take min.absorb2 splits_at_def) from1have"α = γ"using ldfix LeftDerivationFix_def by auto with1 i_eq_j show ?caseby blast next case2 have"∃ a1'. LeftDerives1 a1 (fst (hd D)) (snd (hd D)) a1'"using U 2 by (metis LeftDerivation.elims(2) list.sel(1)) thenobtain a1' where a1': "LeftDerives1 a1 (fst (hd D)) (snd (hd D)) a1'"by blast thenhave"(fst (hd D)) < length a1"using Derives1_bound LeftDerives1_implies_Derives1 by blast thenhave fst_less_i: "(fst (hd D)) < i"using U by (simp add: leD min.absorb2 nat_le_linear splits_at_def) have d_le_fst: "d ≤ fst (hd D)"using derivation_ge_d 2by (simp add: derivation_ge_def) with fst_less_i have d_less_i: "d < i"using le_less_trans by blast have"∃ b1'. LeftDerives1 b1' (fst (last D)) (snd (last D)) b1"using U 2 by (metis Derive LeftDerivation_Derive_take_LeftDerives1 LeftDerivation_implies_Derivation
last_conv_nth length_0_conv order_refl take_all) thenobtain b1' where b1': "LeftDerives1 b1' (fst (last D)) (snd (last D)) b1"by blast thenhave"fst (last D) ≤ length b1" using Derives1_bound' LeftDerives1_implies_Derives1 by blast thenhave fst_le_j: "fst (last D) ≤ j"using U splits_at_def by auto have"d ≤ fst (last D)"using derivation_ge_d 2using derivation_ge_def last_in_set by blast with fst_le_j have"d ≤ j"using order.trans by blast with d_less_i show ?thesis by auto qed qed
lemma LeftDerivationFix_derivation_ge: assumes ldfix: "LeftDerivationFix α i D j γ" assumes derivation_ge_d: "derivation_ge D d" shows"i = j ∨ (i > d ∧ j ≥ d)" proof - from LeftDerivationFix_splits_at_symbol[OF ldfix] obtain U a1 a2 b1 b2 n where U: "splits_at α i a1 U a2 ∧ splits_at γ j b1 U b2 ∧ n ≤ length D ∧ LeftDerivation a1 (take n D) b1 ∧ derivation_ge (drop n D) (Suc (length b1)) ∧ LeftDerivation a2 (derivation_shift (drop n D) (Suc (length b1)) 0) b2 ∧ (n = length D ∨ n < length D ∧ is_word (b1 @ [U]))"by blast have"n = 0 ∨ n > 0"by auto thenshow ?thesis proof (induct rule: disjCases2) case1 thenhave"a1 = b1"using U by auto thenhave i_eq_j: "i = j"using U by (metis dual_order.strict_implies_order length_take min.absorb2 splits_at_def) thenshow ?caseby blast next case2 obtain E where E: "E = take n D"by blast have E_nonempty: "E ≠ []"using E 2 using U less_nat_zero_code list.size(3) take_eq_Nil by auto have"∃ a1'. LeftDerives1 a1 (fst (hd E)) (snd (hd E)) a1'"using U E E_nonempty by (metis LeftDerivation.simps(2) list.exhaust list.sel(1)) thenobtain a1' where a1': "LeftDerives1 a1 (fst (hd E)) (snd (hd E)) a1'"by blast thenhave"(fst (hd E)) < length a1"using Derives1_bound LeftDerives1_implies_Derives1 by blast thenhave fst_less_i: "(fst (hd E)) < i"using U by (simp add: leD min.absorb2 nat_le_linear splits_at_def) have d_le_fst: "d ≤ fst (hd E)"using derivation_ge_d E_nonempty E by (simp add: LeftDerivation.elims(2) U derivation_ge_def hd_conv_nth) with fst_less_i have d_less_i: "d < i"using le_less_trans by blast have"∃ b1'. LeftDerives1 b1' (fst (last E)) (snd (last E)) b1"using E_nonempty U E by (metis LeftDerivation_append1 append_butlast_last_id prod.collapse) thenobtain b1' where b1': "LeftDerives1 b1' (fst (last E)) (snd (last E)) b1"by blast thenhave"fst (last E) ≤ length b1" using Derives1_bound' LeftDerives1_implies_Derives1 by blast thenhave fst_le_j: "fst (last E) ≤ j"using U splits_at_def by auto have"d ≤ fst (last E)"using derivation_ge_d E_nonempty E using derivation_ge_d last_in_set by (metis derivation_ge_def set_take_subset subsetCE) with fst_le_j have"d ≤ j"using order.trans by blast with d_less_i show ?thesis by auto qed qed
lemma LeftDerivationIntro_derivation_ge: assumes ldintro: "LeftDerivationIntro α i r ix D j γ" assumes i_ge_d: "i ≥ d" assumes derivation_ge_d: "derivation_ge D d" shows"j ≥ d" proof - from iffD1[OF LeftDerivationIntro_def ldintro] obtain β where β: "LeftDerives1 α i r β ∧ ix < length (snd r) ∧ snd r ! ix = γ ! j ∧ LeftDerivationFix β (i + ix) D j γ"by blast thenhave"(i + ix = j) ∨ (i + ix > d ∧ j ≥ d)" using LeftDerivationFix_derivation_ge derivation_ge_d by blast thenshow ?thesis proof (induct rule: disjCases2) case1thenshow ?caseusing i_ge_d trans_le_add1 by blast next case2thenshow ?caseby simp qed qed
lemma derivation_ge_LeftDerivationLadder: assumes derivation_ge_d: "derivation_ge D d" assumes ladder: "LeftDerivationLadder α D L γ" assumes ladder_i_0: "ladder_i L 0 ≥ d" shows"index < length L ==> ladder_i L index ≥ d ∧ ladder_j L index ≥ d" proof (induct index) case0 from iffD1[OF LeftDerivationLadder_def ladder] have ldfix: "LeftDerivationFix α (ladder_i L 0) (take (ladder_n L 0) D) (ladder_j L 0) (ladder_γ α D L 0)"by blast have"derivation_ge (take (ladder_n L 0) D) d" using derivation_ge_d by (metis append_take_drop_id derivation_ge_append) from ladder_i_0 derivation_ge_d LeftDerivationFix_derivation_ge[OF ldfix this] show ?caseby linarith next case (Suc n) have ladder_i_Suc: "ladder_i L (Suc n) ≥ d" apply (auto simp add: ladder_i_def) using Suc by auto from iffD1[OF LeftDerivationLadder_def ladder] have"LeftDerivationIntros α D L" by blast thenhave"LeftDerivationIntrosAt α D L (Suc n)" using Suc.prems by (metis LeftDerivationIntros_def Suc_eq_plus1_left le_add1) from iffD1[OF LeftDerivationIntrosAt_def this] show ?caseusing ladder_i_Suc LeftDerivationIntro_derivation_ge by (metis append_take_drop_id derivation_ge_append derivation_ge_d) qed
lemma derivation_shift_append: "derivation_shift (A@B) left right = (derivation_shift A left right) @ (derivation_shift B left right)" by (induct A, simp+)
lemma derivation_shift_right_left_subtract: "right ≥ left ==> derivation_shift (derivation_shift L 0 right) left 0 = derivation_shift L 0 (right - left)" by (induct L, simp+)
lemma LeftDerivationFix_cut_prefix: assumes"LeftDerivationFix (δ@α) i D j γ" assumes"derivation_ge D (length δ)" assumes"i ≥ length δ" assumes is_word_δ: "is_word δ" shows"∃ γ'. γ = δ @ γ' ∧ LeftDerivationFix α (i - length δ) (derivation_shift D (length δ) 0) (j - length δ) γ'" proof - have j_ge_d: "j ≥ length δ" using assms(3) LeftDerivationFix_derivation_ge[OF assms(1) assms(2)] by arith obtain γ' where γ': "γ' = drop (length δ) γ"by blast from iffD1[OF LeftDerivationFix_def assms(1)] obtain E F where EF: "is_sentence (δ @ α) ∧ is_sentence γ ∧ LeftDerivation (δ @ α) D γ ∧ i < length (δ @ α) ∧ j < length γ ∧ (δ @ α) ! i = γ ! j ∧ D = E @ derivation_shift F 0 (Suc j) ∧ LeftDerivation (take i (δ @ α)) E (take j γ) ∧ LeftDerivation (drop (Suc i) (δ @ α)) F (drop (Suc j) γ)"by blast thenhave"LeftDerivation (δ @ α) D γ"by blast from LeftDerivation_skip_prefixword_ex[OF this is_word_δ] obtain γ' where γ': "γ = δ @ γ' ∧ LeftDerivation α (derivation_shift D (length δ) 0) γ'"by blast have ldf1: "is_sentence α"using EF is_sentence_concat by blast have ldf2: "is_sentence γ'"using EF γ' is_sentence_concat by blast have ldf3: "i - length δ < length α" by (metis EF append_Nil assms(3) drop_append drop_eq_Nil not_le) have ldf4: "j - length δ < length γ'" by (metis EF append_Nil j_ge_d γ' drop_append drop_eq_Nil not_le) have ldf5: "α ! (i - length δ) = γ' ! (j - length δ)" by (metis γ' EF assms(3) j_ge_d leD nth_append) have D_split: "D = E @ derivation_shift F 0 (Suc j)"using EF by blast show ?thesis apply (rule_tac x=γ' in exI) apply (auto simp add: γ') apply (auto simp add: LeftDerivationFix_def) using ldf1 apply blast using ldf2 apply blast using γ' apply blast using ldf3 apply blast using ldf4 apply blast using ldf5 apply blast apply (rule_tac x="derivation_shift E (length δ) 0"in exI) apply (rule_tac x="F"in exI) apply auto apply (subst D_split) apply (simp add: derivation_shift_append) apply (subst derivation_shift_right_left_subtract) apply (simp add: j_ge_d le_Suc_eq) using j_ge_d apply (simp add: Suc_diff_le) apply (metis EF LeftDerivation_implies_Derivation LeftDerivation_skip_prefix γ'
append_eq_conv_conj assms(3) drop_take is_word_Derivation_derivation_ge is_word_δ
take_all take_append) using EF Suc_diff_le γ' assms(3) j_ge_d by auto qed
lemma LeftDerives1_propagate_prefix: "LeftDerives1 (δ @ α) i r β ==> i ≥ length δ ==> is_prefix δ β" proof - assume a1: "LeftDerives1 (δ @ α) i r β" assume a2: "length δ ≤ i" have f3: "take i (δ @ α) = take i β" using a1 Derives1_take LeftDerives1_implies_Derives1 by blast thenhave f4: "length (take i β) = i" using a1 by (metis (no_types) Derives1_bound LeftDerives1_implies_Derives1 dual_order.strict_implies_order length_take min.absorb2) have"take (length δ) (take i β) = δ" using f3 a2 by (simp add: append_eq_conv_conj) thenshow ?thesis using f4 a2 by (metis (no_types) append_Nil2 append_eq_conv_conj diff_is_0_eq' is_prefix_take take_0 take_append) qed
lemma LeftDerivationIntro_cut_prefix: assumes"LeftDerivationIntro (δ@α) i r ix D j γ" assumes"derivation_ge D (length δ)" assumes"i ≥ length δ" assumes is_word_δ: "is_word δ" shows"∃ γ'. γ = δ @ γ' ∧ LeftDerivationIntro α (i - length δ) r ix (derivation_shift D (length δ) 0) (j - length δ) γ'" proof - from iffD1[OF LeftDerivationIntro_def assms(1)] obtain β where β: "LeftDerives1 (δ @ α) i r β ∧ ix < length (snd r) ∧ snd r ! ix = γ ! j ∧ LeftDerivationFix β (i + ix) D j γ"by blast have"∃ β'. β = δ @ β'" using LeftDerives1_propagate_prefix β assms(3) by (metis append_dropped_prefix) thenobtain β' where β': "β = δ @ β'"by blast with β have"LeftDerives1 (δ @ α) i r (δ @ β')"by simp from LeftDerives1_skip_prefix[OF assms(3) this] have α_β': "LeftDerives1 α (i - length δ) r β'"by blast have ldfix: "LeftDerivationFix (δ @ β') (i + ix) D j γ"using β β' by auto have δ_le_i_plus_ix: "length δ ≤ i + ix"using assms(3) by arith from LeftDerivationFix_cut_prefix[OF ldfix assms(2) δ_le_i_plus_ix assms(4)] obtain γ' where γ': "γ = δ @ γ' ∧ LeftDerivationFix β' (i + ix - length δ) (derivation_shift D (length δ) 0) (j - length δ) γ'" by blast have same_symbol: "γ ! j = γ' ! (j - length δ)" by (metis LeftDerivationFix_def β β' δ_le_i_plus_ix γ' leD nth_append) have β'_γ': "LeftDerivationFix β' (i - length δ + ix) (derivation_shift D (length δ) 0) (j - length δ) γ'"by (simp add: γ' assms(3)) show ?thesis apply (simp add: LeftDerivationIntro_def) apply (rule_tac x=γ' in exI) apply (auto simp add: γ') apply (rule_tac x=β' in exI) by (auto simp add: β α_β' same_symbol β'_γ') qed
lemma LeftDerivationLadder_implies_LeftDerivation_at_index: assumes"LeftDerivationLadder α D L γ" assumes"index < length L" shows"LeftDerivation α (take (ladder_n L index) D) (ladder_γ α D L index)" using LeftDerivationLadder_def LeftDerivation_take_derive assms(1) ladder_γ_defby auto
lemma LeftDerivationLadder_cut_prefix_propagate: assumes ladder: "LeftDerivationLadder (δ@α) D L γ" assumes is_word_δ: "is_word δ" assumes derivation_ge_δ: "derivation_ge D (length δ)" assumes ladder_i_0: "ladder_i L 0 ≥ length δ" assumes L': "L' = ladder_cut_prefix (length δ) L" assumes D': "D' = derivation_shift D (length δ) 0" shows"index < length L ==> LeftDerivation α (take (ladder_n L' index) D') (ladder_γ α D' L' index) ∧ ladder_α (δ@α) D L index = δ@(ladder_α α D' L' index) ∧ ladder_γ (δ@α) D L index = δ@(ladder_γ α D' L' index)" proof (induct index) case0 have ladder_α: "ladder_α (δ@α) D L 0 = δ@(ladder_α α D' L' 0)" by (simp add: ladder_α_def) have ldfix: "LeftDerivationFix (δ@α) (ladder_i L 0) (take (ladder_n L 0) D) (ladder_j L 0) (ladder_γ (δ@α) D L 0)"using ladder LeftDerivationLadder_def by blast have dge_take: "derivation_ge (take (ladder_n L 0) D) (length δ)" using derivation_ge_δ by (metis append_take_drop_id derivation_ge_append) from LeftDerivationFix_cut_prefix[OF ldfix dge_take ladder_i_0 is_word_δ] obtain γ' where γ': "ladder_γ (δ @ α) D L 0 = δ @ γ' ∧ LeftDerivationFix α (ladder_i L 0 - length δ) (derivation_shift (take (ladder_n L 0) D) (length δ) 0) (ladder_j L 0 - length δ) γ'"by blast have ladder_γ: "ladder_γ (δ@α) D L 0 = δ@(ladder_γ α D' L' 0)" using γ' by (metis "0.prems" D' Derive L' LeftDerivationFix_def
LeftDerivation_implies_Derivation ladder_γ_def ladder_cut_prefix_n take_derivation_shift) have"LeftDerivation α (take (ladder_n L' 0) D') (ladder_γ α D' L' 0)" proof - have"LeftDerivation (δ@α) (take (ladder_n L 0) D) (ladder_γ (δ@α) D L 0)" using LeftDerivationLadder_implies_LeftDerivation_at_index ladder "0.prems"by blast thenshow ?thesis by (metis D' LeftDerivationLadder_def LeftDerivation_skip_prefix
LeftDerivation_take_derive derivation_ge_δ ladder ladder_γ_def) qed thenshow ?caseusing ladder_α ladder_γ by auto next case (Suc index) have index_less_L: "index < length L"using Suc(2) by arith thenhave induct: "ladder_γ (δ@α) D L index = δ@(ladder_γ α D' L' index)" using Suc by blast thenhave ladder_α: "ladder_α (δ@α) D L (Suc index) = δ@(ladder_α α D' L' (Suc index))" by (simp add: ladder_α_def) have introsAt: "LeftDerivationIntrosAt (δ@α) D L (Suc index)" using Suc(2) ladder by (metis LeftDerivationIntros_def LeftDerivationLadder_def Suc_eq_plus1_left le_add1) obtain n m e E where n: "n = ladder_n L (Suc index - 1)"and
m: "m = ladder_n L (Suc index)"and e: "e = D ! n"and E: "E = drop (Suc n) (take m D)" by blast from iffD1[OF LeftDerivationIntrosAt_def introsAt] have "LeftDerivationIntro (ladder_α (δ @ α) D L (Suc index)) (ladder_i L (Suc index)) (snd e) (ladder_ix L (Suc index)) E (ladder_j L (Suc index)) (ladder_γ (δ @ α) D L (Suc index))" using n m e E Let_def by meson thenhave ldintro: "LeftDerivationIntro (δ@(ladder_α α D' L' (Suc index))) (ladder_i L (Suc index)) (snd e) (ladder_ix L (Suc index)) E (ladder_j L (Suc index)) (ladder_γ (δ @ α) D L (Suc index))" by (simp add: ladder_α) have dge_E_δ: "derivation_ge E (length δ)" apply (simp add: E) using derivation_ge_δ by (metis append_take_drop_id derivation_ge_append) have ladder_i_Suc: "length δ ≤ ladder_i L (Suc index)" using Suc.prems derivation_ge_LeftDerivationLadder derivation_ge_δ ladder ladder_i_0 by blast from LeftDerivationIntro_cut_prefix[OF ldintro dge_E_δ ladder_i_Suc is_word_δ] obtain γ' where γ': "ladder_γ (δ @ α) D L (Suc index) = δ @ γ' ∧ LeftDerivationIntro (ladder_α α D' L' (Suc index)) (ladder_i L (Suc index) - length δ) (snd e) (ladder_ix L (Suc index)) (derivation_shift E (length δ) 0) (ladder_j L (Suc index) - length δ) γ'" by blast thenhave"LeftDerivation (ladder_α α D' L' (Suc index)) ((ladder_i L (Suc index) - length δ, snd e) # (derivation_shift E (length δ) 0)) γ'" using LeftDerivationIntro_implies_LeftDerivation by blast thenhave"LeftDerivation (ladder_γ α D' L' index) ((ladder_i L (Suc index) - length δ, snd e) # (derivation_shift E (length δ) 0)) γ'" by (auto simp add: ladder_α_def) have ld: "LeftDerivation α (take (ladder_n L' (Suc index)) D') (ladder_γ α D' L' (Suc index))" proof - have"LeftDerivation (δ@α) (take (ladder_n L (Suc index)) D) (ladder_γ (δ@α) D L (Suc index))" using LeftDerivationLadder_implies_LeftDerivation_at_index ladder Suc.prems by blast thenshow ?thesis by (metis D' LeftDerivationLadder_def LeftDerivation_skip_prefix
LeftDerivation_take_derive derivation_ge_δ ladder ladder_γ_def) qed thenshow ?case using γ' D' Derive L' LeftDerivationIntro_def n m e E ld
LeftDerivation_implies_Derivation ladder_γ_def ladder_cut_prefix_n take_derivation_shift by (metis (no_types, lifting) LeftDerivationLadder_implies_LeftDerivation_at_index
LeftDerivation_skip_prefixword_ex Suc.prems Suc_leI index_less_L is_word_δ ladder
ladder_α le_0_eq neq0_conv) qed
theorem LeftDerivationLadder_cut_prefix: assumes ladder: "LeftDerivationLadder (δ@α) D L γ" assumes is_word_δ: "is_word δ" assumes ladder_i_0: "ladder_i L 0 ≥ length δ" shows"∃ D' L' γ'. γ = δ @ γ' ∧ LeftDerivationLadder α D' L' γ' ∧ D' = derivation_shift D (length δ) 0 ∧ length L' = length L ∧ ladder_i L' 0 + length δ = ladder_i L 0 ∧ ladder_last_j L' + length δ = ladder_last_j L" proof - obtain D' where D': "D' = derivation_shift D (length δ) 0"by blast obtain L' where L': "L' = ladder_cut_prefix (length δ) L"by blast obtain γ' where γ': "γ' = drop (length δ) γ"by blast have ladder_last_j_upper_bound: "ladder_last_j L < length γ"using ladder using ladder_last_j_bound by blast have derivation_ge_δ: "derivation_ge D (length δ)"using is_word_δ LeftDerivationLadder_def
LeftDerivation_implies_Derivation is_word_Derivation_derivation_ge ladder by blast note derivation_ge_ladder =
derivation_ge_LeftDerivationLadder[OF derivation_ge_δ ladder ladder_i_0] have ladder_last_j_lower_bound: "ladder_last_j L ≥ length δ" using LeftDerivationLadder_def derivation_ge_ladder is_ladder_def ladder
ladder_last_j_def by auto from ladder_last_j_upper_bound ladder_last_j_lower_bound have δ_less_γ: "length δ < length γ"by arith thenhave γ_def: "γ = δ @ γ'" by (metis LeftDerivation.simps(1) LeftDerivationLadder_def LeftDerivation_ge_take γ'
append_eq_conv_conj derivation_ge_δ ladder) have length_L_nonzero: "length L ≠ 0" using LeftDerivationLadder_def is_ladder_def ladder by auto have ladder_i_L'_thm: "∧ index. index < length L ==> ladder_i L' index + length δ = ladder_i L index" apply (simp add: L') apply (subst ladder_cut_prefix_i) apply simp using length_L_nonzero apply blast using derivation_ge_ladder by auto have ladder_j_L'_thm: "∧ index. index < length L ==> ladder_j L' index + length δ = ladder_j L index" apply (simp add: L') apply (subst ladder_cut_prefix_j) using LeftDerivationLadder_def is_ladder_def ladder apply blast using LeftDerivationLadder_def is_ladder_def ladder apply blast using derivation_ge_ladder by auto have length_L': "length L' = length L"using L' ladder_cut_prefix_length by simp have α_γ': "LeftDerivation α D' γ'" using D' LeftDerivationLadder_def LeftDerivation_skip_prefix γ' derivation_ge_δ ladder by blast have length_D': "length D' = length D"by (simp add: D') have is_ladder_D_L: "is_ladder D L"using LeftDerivationLadder_def ladder by blast
{ fix u :: nat assume u_bound_L': "u < length L'" have u_bound_L: "u < length L"using length_L' using u_bound_L' by simp have"ladder_n L' u ≤ length D'" apply (simp add: length_D' L') apply (subst ladder_cut_prefix_n) apply (simp add: u_bound_L) using length_L_nonzero apply arith using u_bound_L is_ladder_D_L by (simp add: is_ladder_def)
} note is_ladder_1 = this
{ fix u :: nat fix v :: nat assume u_less_v: "u < v" assume v_bound_L': "v < length L'" thenhave v_bound_L: "v < length L"by (simp add: length_L') with u_less_v have u_bound_L: "u < length L"by arith have"ladder_n L' u < ladder_n L' v" apply (simp add: L') apply (subst ladder_cut_prefix_n) using u_bound_L apply blast using length_L_nonzero apply blast apply (subst ladder_cut_prefix_n) using v_bound_L apply blast using length_L_nonzero apply blast using u_less_v v_bound_L is_ladder_D_L by (simp add: is_ladder_def)
} note is_ladder_2 = this have is_ladder_3: "ladder_last_n L' = length D'" apply (simp add: length_D' ladder_last_n_def L') apply (subst ladder_cut_prefix_n) apply (simp add: ladder_cut_prefix_length) using length_L_nonzero apply auto[1] using length_L_nonzero apply blast apply (simp add: ladder_cut_prefix_length) using is_ladder_D_L by (simp add: is_ladder_def ladder_last_n_def) have is_ladder_4: "LeftDerivationFix α (ladder_i L' 0) (take (ladder_n L' 0) D') (ladder_j L' 0) (ladder_γ α D' L' 0)" proof - have ldfix: "LeftDerivationFix (δ@α) (ladder_i L 0) (take (ladder_n L 0) D) (ladder_j L 0) (ladder_γ (δ@α) D L 0)" using ladder LeftDerivationLadder_def by blast have dge: "derivation_ge (take (ladder_n L 0) D) (length δ)" using derivation_ge_δ by (metis append_take_drop_id derivation_ge_append) from LeftDerivationFix_cut_prefix[OF ldfix dge ladder_i_0 is_word_δ] obtain γ' where γ': "ladder_γ (δ @ α) D L 0 = δ @ γ' ∧ LeftDerivationFix α (ladder_i L 0 - length δ) (derivation_shift (take (ladder_n L 0) D) (length δ) 0) (ladder_j L 0 - length δ) γ'"by blast thenshow ?thesis using LeftDerivationLadder_cut_prefix_propagate D' L' append_eq_conv_conj derivation_ge_δ
is_word_δ ladder ladder_cut_prefix_i ladder_cut_prefix_j ladder_cut_prefix_n ladder_i_0
length_0_conv length_L_nonzero length_greater_0_conv take_derivation_shift by auto qed
{ fix index :: nat assume index_lower_bound: "Suc 0 ≤ index" assume index_upper_bound: "index < length L'" have introsAt: "LeftDerivationIntrosAt (δ@α) D L index" by (metis LeftDerivationIntros_def LeftDerivationLadder_def One_nat_def index_lower_bound
index_upper_bound ladder length_L') thenhave ladder_i_L: "ladder_i L index = fst (D ! ladder_n L (index - Suc 0))" by (metis LeftDerivationIntrosAt_def One_nat_def ‹LeftDerivationIntrosAt (δ @ α) D L index›) have ladder_i_L'_as_L: "ladder_i L' index = ladder_i L index - (length δ)" using ladder_cut_prefix_i L' index_upper_bound is_ladder_D_L is_ladder_not_empty length_L'
length_greater_0_conv by auto have length_L_gr_0: "length L > 0"using length_L' length_L_nonzero by arith have index_Suc_upper_bound_L: "index - Suc 0 < length L"using index_upper_bound length_L' by arith have"fst (D' ! ladder_n L' (index - Suc 0)) = fst (D ! ladder_n L (index - Suc 0)) - (length δ)" apply (subst D', subst L') apply (subst ladder_cut_prefix_n[OF index_Suc_upper_bound_L length_L_gr_0]) apply (simp add: derivation_shift_def) using index_lower_bound index_upper_bound is_ladder_D_L ladder_n_minus_1_bound length_L' by auto thenhave ladder_i_L': "ladder_i L' index = fst (D' ! ladder_n L' (index - Suc 0))" using ladder_i_L ladder_i_L'_as_L by auto have"LeftDerivationIntro (ladder_α α D' L' index) (ladder_i L' index) (snd (D' ! ladder_n L' (index - Suc 0))) (ladder_ix L' index) (drop (Suc (ladder_n L' (index - Suc 0))) (take (ladder_n L' index) D')) (ladder_j L' index) (ladder_γ α D' L' index)" proof - have"LeftDerivationIntro (ladder_α (δ@α) D L index) (ladder_i L index) (snd (D ! ladder_n L (index - Suc 0))) (ladder_ix L index) (drop (Suc (ladder_n L (index - Suc 0))) (take (ladder_n L index) D)) (ladder_j L index) (ladder_γ (δ@α) D L index)"using introsAt by (metis LeftDerivationIntrosAt_def One_nat_def) thenhave ldintro: "LeftDerivationIntro (δ@(ladder_α α D' L' index)) (ladder_i L index) (snd (D ! ladder_n L (index - Suc 0))) (ladder_ix L index) (drop (Suc (ladder_n L (index - Suc 0))) (take (ladder_n L index) D)) (ladder_j L index) (ladder_γ (δ@α) D L index)" using D' L' LeftDerivationLadder_cut_prefix_propagate derivation_ge_δ index_upper_bound
is_word_δ ladder ladder_i_0 length_L' by auto have dge: "derivation_ge (drop (Suc (ladder_n L (index - Suc 0))) (take (ladder_n L index) D)) (length δ)"using derivation_ge_δ by (metis append_take_drop_id derivation_ge_append) have δ_le_i_L: "length δ ≤ ladder_i L index" using derivation_ge_ladder index_upper_bound length_L' by auto from LeftDerivationIntro_cut_prefix[OF ldintro dge δ_le_i_L is_word_δ] obtain γ' where γ': "ladder_γ (δ @ α) D L index = δ @ γ' ∧ LeftDerivationIntro (ladder_α α D' L' index) (ladder_i L index - length δ) (snd (D ! ladder_n L (index - Suc 0))) (ladder_ix L index) (derivation_shift (drop (Suc (ladder_n L (index - Suc 0))) (take (ladder_n L index) D)) (length δ) 0) (ladder_j L index - length δ) γ'"by blast have h1: "ladder_i L' index = ladder_i L index - length δ" using L' ladder_cut_prefix_i ladder_i_L'_as_L by blast have h2: "(snd (D' ! ladder_n L' (index - Suc 0))) = (snd (D ! ladder_n L (index - Suc 0)))" apply (subst L', subst ladder_cut_prefix_n) apply (simp add: index_Suc_upper_bound_L) using length_L_gr_0 apply auto[1] apply (subst D') apply (simp add: derivation_shift_def) using index_lower_bound index_upper_bound is_ladder_D_L ladder_n_minus_1_bound
length_L' by auto have h3: "ladder_ix L' index = ladder_ix L index" using ladder_cut_prefix_ix L' index_upper_bound length_L' length_L_gr_0 by auto have h4: "(drop (Suc (ladder_n L' (index - Suc 0))) (take (ladder_n L' index) D')) = (derivation_shift (drop (Suc (ladder_n L (index - Suc 0))) (take (ladder_n L index) D)) (length δ) 0)" apply (subst D') apply (subst L')+ apply (subst ladder_cut_prefix_n, simp add: index_Suc_upper_bound_L) using length_L_gr_0 apply blast apply (subst ladder_cut_prefix_n) using index_upper_bound length_L' apply arith using length_L_gr_0 apply blast apply (simp add: derivation_shift_def) by (simp add: drop_map take_map) have h5: "ladder_j L' index = ladder_j L index - length δ" using ladder_cut_prefix_j L' index_upper_bound length_L' length_L_gr_0 by auto have h6: "ladder_γ α D' L' index = γ'" using D' L' LeftDerivationLadder_cut_prefix_propagate γ' derivation_ge_δ index_upper_bound
is_word_δ ladder ladder_i_0 length_L' by auto show ?thesis using h1 h2 h3 h4 h5 h6 γ' by simp qed thenhave"LeftDerivationIntrosAt α D' L' index" apply (auto simp add: LeftDerivationIntrosAt_def Let_def) using ladder_i_L' by blast
} note is_ladder_5 = this show ?thesis apply (rule_tac x="D'"in exI) apply (rule_tac x="L'"in exI) apply (rule_tac x="γ'"in exI) apply auto using γ_defapply blast defer1 using D' apply blast using L' ladder_cut_prefix_length apply auto[1] apply (subst ladder_i_L'_thm) using LeftDerivationLadder_def is_ladder_def ladder apply blast apply simp apply (simp add: ladder_last_j_def) apply (subst ladder_j_L'_thm) apply (simp add: length_L') using length_L_nonzero apply arith apply (simp add: length_L') apply (auto simp add: LeftDerivationLadder_def) using α_γ' apply blast apply (auto simp add: is_ladder_def) using length_L_nonzero length_L' apply auto[1] using is_ladder_1 apply blast using is_ladder_2 apply blast using is_ladder_3 apply blast using is_ladder_4 apply blast by (auto simp add: LeftDerivationIntros_def is_ladder_5) qed
end
end
Messung V0.5 in Prozent
¤ 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.0.176Bemerkung:
¤
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 und die Messung sind noch experimentell.