Theory TheoremD14

theory TheoremD14
imports TheoremD13
begin

context LocalLexing begin

lemma empty_tokens_of_empty[simp]: "empty_tokens {} = {}"
  using empty_tokens_is_filter by blast

lemma items_le_split_via_eq: "items_le (Suc k) J = items_le k J  items_eq (Suc k) J"
  by (auto simp add: items_le_def items_eq_def)

lemma paths_le_split_via_eq: "paths_le (Suc k) P = paths_le k P  paths_eq (Suc k) P"
  by (auto simp add: paths_le_def paths_eq_def)

lemma natUnion_superset:
  shows "g i  natUnion g"
by (meson natUnion_elem subset_eq)

definition indexle :: "nat  nat  nat  nat  bool" where
  "indexle k' u' k u = ((indexlt k' u' k u)  (k' = k  u' = u))"

definition produced_by_scan_step :: "item  nat  nat  bool" where
  "produced_by_scan_step x k u = ( k' u' y X. indexle k' u' k u  y  𝒥 k' u'  
   item_end y = k'  X  (𝒯 k' u')  x = inc_item y (k' + length (chars_of_token X))  
   next_symbol y = Some (terminal_of_token X))"

lemma indexle_trans: "indexle k'' u'' k' u'  indexle k' u' k u  indexle k'' u'' k u"
  using indexle_def indexlt_trans
proof -
  assume a1: "indexle k'' u'' k' u'"
  assume a2: "indexle k' u' k u"
  then have f3: "n na. u' = u  indexlt n na k u  ¬ indexlt n na k' u'"
    by (meson indexle_def indexlt_trans)
  have "n na. k' = k  indexlt n na k u  ¬ indexlt n na k' u'"
    using a2 by (meson indexle_def indexlt_trans)
  then show ?thesis
    using f3 a2 a1 indexle_def by auto
qed 

lemma produced_by_scan_step_trans:
  assumes "indexle k' u' k u"
  assumes "produced_by_scan_step x k' u'"
  shows "produced_by_scan_step x k u"
proof -
  from iffD1[OF produced_by_scan_step_def assms(2)] obtain k'a u'a y X where produced_k'_u':
    "indexle k'a u'a k' u' 
     y  𝒥 k'a u'a 
     item_end y = k'a 
     X  𝒯 k'a u'a 
     x = inc_item y (k'a + length (chars_of_token X))  next_symbol y = Some (terminal_of_token X)"
     by blast
  then show ?thesis using indexle_trans assms(1) produced_by_scan_step_def by blast 
qed

lemma 𝒥_induct[consumes 1, case_names Induct]:
  assumes "x  𝒥 k u"
  assumes induct: " x k u . ( x' k' u'. x'  𝒥 k' u'  indexlt k' u' k u  P x' k' u') 
                      x  𝒥 k u  P x k u"
  shows "P x k u"
proof -
  let ?R = "indexlt_rel <*lex*> {}"
  have wf_R: "wf ?R" by (auto simp add: wf_indexlt_rel)
  let ?P = "λ a. snd a  𝒥 (fst (fst a)) (snd (fst a))  P (snd a) (fst (fst a)) (snd (fst a))"
  have "x  𝒥 k u  P x k u"
    apply (rule wf_induct[OF wf_R, where P = ?P and a = "((k, u), x)", simplified])
    apply (auto simp add: indexlt_def[symmetric])
    apply (rule_tac x=ba and k=a and u=b in induct)
    by auto
  thus ?thesis using assms by auto 
qed

lemma π_no_tokens_item_end: 
  assumes x_in_π: "x  π k {} I"
  shows "item_end x = k  x  I"
proof -
  have x_in_limit: "x  limit (λI. Complete k (Predict k I)) I"
    using x_in_π π_no_tokens by auto  
  then show ?thesis
  proof (induct rule: limit_induct)
    case (Init x) then show ?case by auto
  next
    case (Iterate x J)
      from Iterate(2) have "item_end x = k  x  Predict k J"
        using Complete_item_end by auto
      then show ?case 
      proof (induct rule: disjCases2)
        case 1 then show ?case by blast
      next
        case 2 
          then have "item_end x = k  x  J" 
            using Predict_item_end by auto
          then show ?case
          proof (induct rule: disjCases2)
            case 1 then show ?case by blast
          next
            case 2 then show ?case using Iterate(1)[OF 2] by blast
          qed
      qed 
  qed
qed 

lemma natUnion_ex: "x  natUnion f   i. x  f i"
  by (metis (no_types, opaque_lifting) mk_disjoint_insert natUnion_superset natUnion_upperbound 
    subsetCE subset_insert)

lemma locate_in_limit:
  assumes x_in_limit: "x  limit f X"
  assumes x_notin_X: "x  X"
  shows " n. x  funpower f (Suc n) X  x  funpower f n X"
proof -
  have " N. x  funpower f N X" using x_in_limit limit_def natUnion_ex by fastforce
  then obtain N where N: "x  funpower f N X" by blast
  {
    fix n :: nat
    have "x  funpower f n X   m < n. x  funpower f (Suc m) X  x  funpower f m X"
    proof (induct n)
      case 0 
        with x_notin_X show ?case by auto
    next
      case (Suc n)
        have "x  funpower f n X  x  funpower f n X" by blast
        then show ?case
        proof (induct rule: disjCases2)
          case 1     
            then show ?case using Suc by fastforce
        next
          case 2
            from Suc(1)[OF 2] show ?case using less_SucI by blast 
        qed 
    qed
  }
  with N show ?thesis by auto
qed

lemma produced_by_scan_step: 
  "x  𝒥 k u  item_end x > k  produced_by_scan_step x k u"
proof (induct rule: 𝒥_induct)
  case (Induct x k u)
    have "(k = 0  u = 0)  (k > 0  u = 0)  (u > 0)" by arith
    then show ?case
    proof (induct rule: disjCases3)
      case 1
        with Induct have "item_end x = 0" using 𝒥_0_0_item_end by blast  
        with Induct have "False" by arith
        then show ?case by  blast
    next
      case 2
        then obtain k' where k': "k = Suc k'" using Suc_pred' by blast 
        with Induct 2 have "x  𝒥 (Suc k') 0" by auto
        then have "x  π k {} ( k')" by (simp add: k') 
        then have "item_end x = k  x   k'" using π_no_tokens_item_end by blast
        then show ?case
        proof (induct rule: disjCases2)
          case 1
            with Induct have "False" by auto
            then show ?case by blast
        next
          case 2
            then have " u'. x  𝒥 k' u'" using ℐ.simps natUnion_ex by fastforce
            then obtain u' where u': "x  𝒥 k' u'" by blast
            have k'_bound: "k' < item_end x" using k' Induct by arith
            have indexlt: "indexlt k' u' k u" by (simp add: indexlt_simp k') 
            from Induct(1)[OF u' this k'_bound] 
            have pred_produced: "produced_by_scan_step x k' u'" .
            then show ?case using indexlt produced_by_scan_step_trans indexle_def by blast 
        qed
    next
      case 3
        then have ex_u': " u'. u = Suc u'" by arith
        then obtain u' where u': "u = Suc u'" by blast
        with Induct have "x  𝒥 k (Suc u')" by metis
        then have x_in_π: "x  π k (𝒯 k u) (𝒥 k u')" using u' 𝒥.simps by metis
        have "x  𝒥 k u'  x  𝒥 k u'" by blast
        then show ?case
        proof (induct rule: disjCases2)
          case 1
            have indexlt: "indexlt k u' k u" by (simp add: indexlt_simp u')             
            with Induct(1)[OF 1 indexlt Induct(3)] show ?case
              using indexle_def produced_by_scan_step_trans by blast
        next
          case 2
            have item_end_x: "k < item_end x" using Induct by auto
            obtain f where f: "f = Scan (𝒯 k u) k  Complete k  Predict k" by blast
            have "x  limit f (𝒥 k u')"
              using x_in_π π_functional f by simp
            from locate_in_limit[OF this 2] obtain n where n:
              "x  funpower f (Suc n) (𝒥 k u') 
               x  funpower f n (𝒥 k u')" by blast
            obtain Y where Y: "Y = funpower f n (𝒥 k u')"
              by blast
            have x_f_Y: "x  f Y  x  Y" using Y n by auto
            then have "x  Scan (𝒯 k u) k (Complete k (Predict k Y))" using comp_apply f by simp
            then have "x  (Complete k (Predict k Y)) 
              x  { inc_item x' (k + length c) | x' t c. x'  bin (Complete k (Predict k Y)) k  
                    (t, c)  (𝒯 k u)  next_symbol x' = Some t }" using Scan_def by simp
            then show ?case
            proof (induct rule: disjCases2)
              case 1
                then have "False" using item_end_x x_f_Y Complete_item_end Predict_item_end
                  using less_not_refl3 by blast
                then show ?case by auto
            next
              case 2
                have "Y  limit f (𝒥 k u')" using Y limit_def natUnion_superset by fastforce
                then have "Y  π k (𝒯 k u) (𝒥 k u')" using f by (simp add: π_functional)  
                then have Y_in_𝒥: "Y  𝒥 k u" using u' by simp
                then have in_𝒥: "Complete k (Predict k Y)  𝒥 k u"
                proof - (* automatically generated *)
                  have f1: "f I Ia i. (¬ mono f  ¬ (I::item set)  Ia  (i::item)  f I)  i  f Ia"
                    by (meson mono_subset_elem)
                  obtain ii :: "item set  item set  item" where
                    "x0 x1. (v2. v2  x1  v2  x0) = (ii x0 x1  x1  ii x0 x1  x0)"
                    by moura
                  then have f2: "I Ia. ii Ia I  I  ii Ia I  Ia  I  Ia"
                    by blast
                  obtain nn :: nat where
                    f3: "u = Suc nn"
                    using ex_u' by presburger
                  moreover
                  { assume "ii (𝒥 k u) (Complete k (Predict k Y))  Complete k (π k (𝒯 k (Suc nn)) (𝒥 k nn))"
                    then have ?thesis
                      using f3 f2 Complete_π_fix by auto }
                  ultimately show ?thesis
                    using f2 f1 by (metis (full_types) Complete_regular Predict_π_fix Predict_regular 
                      𝒥.simps(2) Y_in_𝒥 regular_implies_mono)
                qed 
                from 2 obtain  x' t c where x'_t_c:
                  "x = inc_item x' (k + length c)  x'  bin (Complete k (Predict k Y)) k  
                    (t, c)  𝒯 k u  next_symbol x' = Some t" by blast
                show ?case
                  apply (simp add: produced_by_scan_step_def)
                  apply (rule_tac x=k in exI)
                  apply (rule_tac x=u in exI)
                  apply (simp add: indexle_def)
                  apply (rule_tac x=x' in exI)
                  apply auto
                  using x'_t_c bin_def in_𝒥 apply auto[1]
                  using x'_t_c bin_def apply blast
                  apply (rule_tac x=t in exI)
                  apply (rule_tac x=c in exI)
                  using x'_t_c by auto
            qed      
        qed
    qed  
qed

lemma limit_single_step:
  assumes "x  f X"
  shows "x  limit f X"
by (metis assms elem_limit_simp funpower.simps(1) funpower.simps(2))

lemma Gen_union: "Gen (A  B) = Gen A  Gen B"
  by (simp add: Gen_def, blast)

lemma is_prefix_Prefixes_subset:
  assumes "is_prefix q p"
  shows "Prefixes q  Prefixes p"
proof -
  show ?thesis
    apply (auto simp add: Prefixes_def)
    using assms by (metis is_prefix_append is_prefix_def) 
qed

lemma Prefixes_subset_𝒫:
  assumes "p  𝒫 k u"
  shows "Prefixes p  𝒫 k u"
using Prefixes_is_prefix assms prefixes_are_paths by blast

lemma Prefixes_subset_paths_le:
  assumes "Prefixes p  P"
  shows "Prefixes p  paths_le (charslength p) P"
using Prefixes_is_prefix assms charslength_of_prefix paths_le_def by auto

lemma Scan_𝒥_subset_𝒥:
  "Scan (𝒯 k (Suc u)) k (𝒥 k u)  𝒥 k (Suc u)"
by (metis (no_types, lifting) Scan_π_fix 𝒥.simps(2) 𝒥_subset_Suc_u monoD mono_Scan)

lemma subset_𝒥k: "u  v  𝒥 k u  𝒥 k v"
  thm 𝒥_subset_Suc_u
  by (rule subset_fSuc, rule 𝒥_subset_Suc_u) 

lemma subset_𝒥ℐk: "𝒥 k u   k" by (auto simp add: natUnion_def)

lemma subset_ℐ𝒥Suc: " k  𝒥 (Suc k) u" 
proof -
  have a: " k  𝒥 (Suc k) 0" 
    apply (simp only: 𝒥.simps)
    using π_apply_setmonotone by blast    
  show ?thesis 
    apply (case_tac "u = 0")
    apply (simp only: a)
    apply (rule subset_trans[OF a subset_𝒥k])
    by auto
qed

lemma subset_ℐSuc: " k   (Suc k)"
  by (rule subset_trans[OF subset_ℐ𝒥Suc subset_𝒥ℐk])

lemma subset_ℐ: "i  j   i   j"
  by (rule subset_fSuc[where u=i and v=j and f = , OF subset_ℐSuc])

lemma subset_𝒥 :
  assumes leq: "k' < k  (k' = k  u'  u)"
  shows "𝒥 k' u'  𝒥 k u"
proof -
  from leq show ?thesis
  proof (induct rule: disjCases2)
    case 1
    have s1: "𝒥 k' u'   k'" by (rule_tac subset_𝒥ℐk) 
    have s2: " k'   (k - 1)" 
      apply (rule_tac subset_ℐ)
      using 1 by arith
    from subset_ℐ𝒥Suc[where k="k - 1"] 1 have s3: " (k - 1)  𝒥 k 0"
      by simp
    have s4: "𝒥 k 0  𝒥 k u" by (rule_tac subset_𝒥k, simp)
    from s1 s2 s3 s4 subset_trans show ?case by blast
  next
    case 2 thus ?case by (simp add : subset_𝒥k)
  qed
qed  

lemma 𝒥_subset:
  assumes "indexle k' u' k u"
  shows "𝒥 k' u'  𝒥 k u"
using subset_𝒥 indexle_def indexlt_simp
by (metis assms less_imp_le_nat order_refl) 

lemma Scan_items_le:
  assumes bounded_T: " t . t  T  length (chars_of_token t)  l"
  shows "Scan T k (items_le k P)  items_le (k + l) (Scan T k P)"
proof -
  {
    fix x :: item
    assume x_dom: "x  Scan T k (items_le k P)"
    then have x_dom': "x  Scan T k P"
      by (meson items_le_is_filter mono_Scan mono_subset_elem)
    from x_dom have "x  items_le k P  
      ( y t c. x = inc_item y (k + length c)  y  bin (items_le k P) k  (t, c)  T
        next_symbol y = Some t)" 
      using Scan_def using UnE mem_Collect_eq by auto 
    then have "item_end x  k + l"
    proof (induct rule: disjCases2)
      case 1 then show ?case
        by (meson items_le_fix_D items_le_idempotent trans_le_add1)
    next
      case 2 
        then obtain y t c where y: "x = inc_item y (k + length c)  y  bin (items_le k P) k  
          (t, c)  T  next_symbol y = Some t" by blast
        then have item_end_x: "item_end x = (k + length c)" by simp
        from bounded_T y have "length c  l"
          using chars_of_token_simp by auto 
        with item_end_x show ?case by arith
    qed
    with x_dom' have "x  items_le (k + l) (Scan T k P)"
      using items_le_def mem_Collect_eq by blast
  }
  then show ?thesis by blast      
qed

lemma Scan_mono_tokens:
  "P  Q  Scan P k I  Scan Q k I"
by (auto simp add: Scan_def)

theorem thmD14: "k  length Doc  items_le k (𝒥 k u) = Gen (paths_le k (𝒫 k u))  𝒯 k u = 𝒵 k u 
     items_le k ( k) = Gen (paths_le k (𝒬 k))"
proof (induct k arbitrary: u rule: less_induct)
  case (less k)
    have "k = 0  k  0" by arith
    then show ?case 
    proof (induct rule: disjCases2)
      case 1
        have 𝒥_eq_𝒫: "items_le k (𝒥 k 0) = Gen (paths_le k (𝒫 k 0))" 
          by (simp only: 1 thmD8 items_le_paths_le)
        show ?case using thmD13[OF 𝒥_eq_𝒫 less.prems] by blast
    next
      case 2
        have " k'. k = Suc k'" using 2 by arith
        then obtain k' where k': "k = Suc k'" by blast
        have k'_less_k: "k' < k" using k' by arith
        have "items_le k (𝒥 k 0) = Gen (paths_le k (𝒫 k 0))"          
        proof -
          have simp_left: "items_le k (𝒥 k 0) = π k {} (items_le k ( k'))"
            using items_le_π_swap k' wellformed_items_ℐ by auto 
          have simp_right: "Gen (paths_le k (𝒫 k 0)) = natUnion (λ v. Gen (paths_le k (𝒫 k' v)))"
            by (simp add: k' paths_le_pointwise pointwise_Gen pointwise_natUnion_swap)            
          {
            fix v :: nat
            have split_𝒥: "items_le k (𝒥 k' v) = items_le k' (𝒥 k' v)  items_eq k (𝒥 k' v)" 
              using k'  items_le_split_via_eq by blast
            have sub1: "items_le k' (𝒥 k' v)  natUnion (λ v. Gen (paths_le k (𝒫 k' v)))"
            proof -
              have h: "items_le k' (𝒥 k' v)  Gen (paths_le k (𝒫 k' v))"
              proof - (* automatically generated *)
                have f1: "items_le k' (Gen (𝒫 k' v))  items_eq (Suc k') (Gen (𝒫 k' v)) = 
                  Gen (paths_le k (𝒫 k' v))"
                  using LocalLexing.items_le_split_via_eq LocalLexing_axioms items_le_paths_le k' 
                  by blast
                have "k'  length Doc"
                  by (metis (no_types) dual_order.trans k' less.prems lessI less_imp_le_nat)
                then have "items_le k' (𝒥 k' v) = items_le k' (Gen (𝒫 k' v))"
                  by (simp add: items_le_paths_le k' less.hyps)
                then show ?thesis
                  using f1 by blast
              qed
              have "Gen (paths_le k (𝒫 k' v))  natUnion (λ v. Gen (paths_le k (𝒫 k' v)))"
                using natUnion_superset by fastforce
              then show ?thesis using h by blast
            qed
            {
              fix x :: item
              assume x_dom: "x  items_eq k (𝒥 k' v)"
              have x_in_𝒥: "x  𝒥 k' v" using x_dom items_eq_def by auto
              have item_end_x: "item_end x = k" using x_dom items_eq_def by auto
              then have k'_bound: "k' < item_end x" using k' by arith
              from produced_by_scan_step[OF x_in_𝒥 k'_bound]
              have "produced_by_scan_step x k' v" .
              from iffD1[OF produced_by_scan_step_def this] obtain k'' v'' y X where scan_step:
                "indexle k'' v'' k' v  y  𝒥 k'' v''  item_end y = k''  X  𝒯 k'' v'' 
                 x = inc_item y (k'' + length (chars_of_token X))  
                 next_symbol y = Some (terminal_of_token X)" by blast
              then have y_in_items_le: "y  items_le k'' (𝒥 k'' v'')"
                using items_le_def LocalLexing_axioms le_refl mem_Collect_eq by blast 
              have y_in_Gen: "y  Gen(paths_le k'' (𝒫 k'' v''))"
              proof - (* automatically generated *)
                have f1: "n. k' < n  ¬ k < n"
                  using Suc_lessD k' by blast
                have f2: "k'' = k'  k'' < k'"
                  using indexle_def indexlt_simp scan_step by force
                have f3: "k' < k"
                  using k' by blast
                have f4: "k'  length Doc"
                  using f1 by (meson less.prems less_Suc_eq_le)
                have "k''  length Doc  k' = k''"
                  using f2 f1 by (meson Suc_lessD less.prems less_Suc_eq_le less_trans_Suc)
                then show ?thesis
                  using f4 f3 f2 Suc_lessD y_in_items_le less.hyps less_trans_Suc by blast
              qed
              then have " p. p  𝒫 k'' v''  pvalid p y"
                by (meson Gen_implies_pvalid paths_le_is_filter rev_subsetD)
              then obtain p where p: "p  𝒫 k'' v''  pvalid p y" by blast
              then have charslength_p: "charslength p = k''" using pvalid_item_end scan_step by auto 
              have pvalid_p_y: "pvalid p y" using p by blast
              have "admissible (p@[(fst X, snd X)])"
                apply (rule pvalid_next_terminal_admissible)
                apply (rule pvalid_p_y)
                using scan_step apply (simp add: terminal_of_token_def) 
                using scan_step by (metis TokensAt_subset_𝒳 𝒯_subset_TokensAt 𝒳_are_terminals 
                  rev_subsetD terminal_of_token_def) 
              then have admissible_p_X: "admissible (p@[X])" by simp
              have X_in_𝒵: "X  𝒵 k'' (Suc v'')" by (metis (no_types, lifting) Suc_lessD 𝒵_subset_Suc 
                k'_bound dual_order.trans indexle_def indexlt_simp item_end_of_inc_item item_end_x 
                le_add1 le_neq_implies_less less.hyps less.prems not_less_eq scan_step subsetCE) 
              have pX_in_𝒫_k''_v'': "p@[X]  𝒫 k'' (Suc v'')"   
                apply (simp only: 𝒫.simps)
                apply (rule limit_single_step)
                apply (auto simp only: Append_def)
                apply (rule_tac x=p in exI)
                apply (rule_tac x=X in exI)
                apply (simp only: admissible_p_X X_in_𝒵)
                using charslength_p p by auto
              have "indexle k'' v'' k' v" using scan_step by simp
              then have "indexle k'' (Suc v'') k' (Suc v)"
                by (simp add: indexle_def indexlt_simp)               
              then have "𝒫 k'' (Suc v'')  𝒫 k' (Suc v)"
                by (metis indexle_def indexlt_simp less_or_eq_imp_le subset_𝒫) 
              with pX_in_𝒫_k''_v'' have pX_in_𝒫_k': "p@[X]  𝒫 k' (Suc v)" by blast
              have "charslength (p@[X]) = k'' +  length (chars_of_token X)"
                using charslength_p by auto
              then have "charslength (p@[X]) = item_end x" using scan_step by simp
              then have charslength_p_X: "charslength (p@[X]) = k" using item_end_x by simp
              then have pX_dom: "p@[X]  paths_le k (𝒫 k' (Suc v))"
                using lessI less_Suc_eq_le mem_Collect_eq pX_in_𝒫_k' paths_le_def by auto
              have wellformed_x: "wellformed_item x"
                using item_end_x less.prems scan_step wellformed_inc_item wellformed_items_𝒥 
                  wellformed_items_def by auto
              have wellformed_p_X: "wellformed_tokens (p@[X])"
                using 𝒫_wellformed pX_in_𝒫_k''_v'' by blast
              from iffD1[OF pvalid_def pvalid_p_y] obtain r γ where r_γ:
                "wellformed_tokens p 
                 wellformed_item y 
                 r  length p 
                 charslength p = item_end y 
                 charslength (take r p) = item_origin y 
                 is_derivation (terminals (take r p) @ [item_nonterminal y] @ γ) 
                 derives (item_α y) (terminals (drop r p))" by blast
              have r_le_p: "r  length p" by (simp add: r_γ)
              have item_nonterminal_x: "item_nonterminal x = item_nonterminal y" 
                by (simp add: scan_step)
              have item_α_x: "item_α x = (item_α y) @ [terminal_of_token X]"
                by (simp add: item_α_of_inc_item r_γ scan_step)              
              have pvalid_x: "pvalid (p@[X]) x"                
                apply (auto simp add: pvalid_def wellformed_x wellformed_p_X)
                apply (rule_tac x=r in exI)
                apply auto
                apply (simp add: le_SucI r_γ)
                using r_γ scan_step apply auto[1]
                using r_γ scan_step apply auto[1]
                apply (rule_tac x=γ in exI)
                apply (simp add: r_le_p item_nonterminal_x)
                using r_γ apply simp
                apply (simp add: r_le_p item_α_x)
                by (metis terminals_singleton append_Nil2 
                  derives_implies_leftderives derives_is_sentence is_sentence_concat 
                  is_sentence_cons is_symbol_def is_word_append is_word_cons is_word_terminals 
                  is_word_terminals_drop leftderives_implies_derives leftderives_padback 
                  leftderives_refl r_γ terminals_append terminals_drop wellformed_p_X)
              then have "x  Gen (paths_le k (𝒫 k' (Suc v)))" using pX_dom Gen_def 
                LocalLexing_axioms mem_Collect_eq by auto 
            }
            then have sub2: "items_eq k (𝒥 k' v)  natUnion (λ v. Gen (paths_le k (𝒫 k' v)))"
              by (meson dual_order.trans natUnion_superset subsetI)                                       
            have suffices3: "items_le k (𝒥 k' v)  natUnion (λ v. Gen (paths_le k (𝒫 k' v)))"
              using split_𝒥 sub1 sub2 by blast
            have "items_le k (𝒥 k' v)  Gen (paths_le k (𝒫 k 0))"
              using suffices3 simp_right by blast
          }
          note suffices2 = this
          have items_le_natUnion_swap: "items_le k ( k') = natUnion(λ v. items_le k (𝒥 k' v))"
            by (simp add: items_le_pointwise pointwise_natUnion_swap)            
          then have suffices1: "items_le k ( k')  Gen (paths_le k (𝒫 k 0))"
            using suffices2 natUnion_upperbound by metis    
          have sub_lemma: "items_le k (𝒥 k 0)  Gen (paths_le k (𝒫 k 0))"
          proof -
            have "items_le k (𝒥 k 0)  Gen (𝒫 k 0)"
              apply (subst simp_left)
              apply (rule thmD5)
              apply (auto simp only: less)
              using suffices1 items_le_is_filter items_le_paths_le subsetCE by blast 
            then show ?thesis
              by (simp add: items_le_idempotent remove_paths_le_in_subset_Gen)
          qed          
          have eq1: "π k {} (items_le k ( k')) = π k {} (items_le k (natUnion (𝒥 k')))" by simp
          then have eq2: "π k {} (items_le k (natUnion (𝒥 k'))) = 
            π k {} (natUnion (λ v. items_le k (𝒥 k' v)))"
            using items_le_natUnion_swap by auto
          from simp_left eq1 eq2 
          have simp_left': "items_le k (𝒥 k 0) = π k {} (natUnion (λ v. items_le k (𝒥 k' v)))"
            by metis
          {
            fix v :: nat
            fix q :: "token list"
            fix x :: item
            assume q_dom: "q  paths_eq k (𝒫 k' v)"
            assume pvalid_q_x: "pvalid q x"
            have q_in_𝒫: "q  𝒫 k' v" using q_dom paths_eq_def by auto
            have charslength_q: "charslength q = k" using q_dom paths_eq_def by auto
            with k'_less_k have q_nonempty: "q  []"
              using "2.hyps" chars.simps(1) charslength.simps list.size(3) by auto 
            then have " p X. q = p @ [X]" by (metis append_butlast_last_id) 
            then obtain p X where pX: "q = p @ [X]" by blast
            from last_step_of_path[OF q_in_𝒫 pX] obtain k'' v'' where k'':
              "indexlt k'' v'' k' v  q  𝒫 k'' (Suc v'')  charslength p = k''  
               X  𝒵 k'' (Suc v'')" by blast
            have h1: "p  𝔓"
              by (metis (no_types, lifting) LocalLexing.𝔓_covers_𝒫 LocalLexing_axioms 
                append_Nil2 is_prefix_cancel is_prefix_empty pX prefixes_are_paths q_in_𝒫 subsetCE) 
            have h2: "charslength p = k''" using k'' by blast
            obtain T where T: "T = {X}" by blast
            have h3: "X  T" using T by blast
            have h4: "T  𝒳 k''" using 𝒵_subset_𝒳 T k'' by blast 
            obtain N where N: "N = item_nonterminal x" by blast
            obtain α where α: "α = item_α x" by blast
            obtain β where β: "β = item_β x" by blast
            have wellformed_x: "wellformed_item x" using pvalid_def pvalid_q_x by blast 
            then have h5: "(N, α @ β)  "
              using N α β item_nonterminal_def item_rhs_def item_rhs_split prod.collapse 
                wellformed_item_def by auto 
            have pvalid_left_q_x: "pvalid_left q x" using pvalid_q_x by (simp add: pvalid_left) 
            from iffD1[OF pvalid_left_def pvalid_left_q_x] obtain r γ where r_γ: 
              "wellformed_tokens q 
               wellformed_item x 
               r  length q 
               charslength q = item_end x 
               charslength (take r q) = item_origin x 
               is_leftderivation (terminals (take r q) @ [item_nonterminal x] @ γ) 
               leftderives (item_α x) (terminals (drop r q))" by blast
            have h6: "r  length q" using r_γ by blast
            have h7: "leftderives [𝔖] (terminals (take r q) @ [N] @ γ)"
              using r_γ N is_leftderivation_def by blast 
            have h8: "leftderives α (terminals (drop r q))" using r_γ α by metis
            have h9: "k = k'' + length (chars_of_token X)" using r_γ
              using charslength_q h2 pX by auto 
            have h10: "x = Item (N, α @ β) (length α) (charslength (take r q)) k"
              by (metis N α β charslength_q item.collapse item_dot_is_α_length item_nonterminal_def 
                item_rhs_def item_rhs_split prod.collapse r_γ)             
            from thmD11[OF h1 h2 h3 h4 pX h5 h6 h7 h8 h9 h10] 
            have "x  items_le k (π k {} (Scan T k'' (Gen (Prefixes p))))" 
              by blast
            then have x_in: "x  π k {} (Scan T k'' (Gen (Prefixes p)))"
              using items_le_is_filter by blast             
            have subset1: "Prefixes p  Prefixes q"
              apply (rule is_prefix_Prefixes_subset)
              by (simp add: pX is_prefix_def)
            have subset2: "Prefixes q  𝒫 k'' (Suc v'')" 
              apply (rule Prefixes_subset_𝒫)
              using k'' by blast
            from subset1 subset2 have "Prefixes p  𝒫 k'' (Suc v'')" by blast
            then have "Prefixes p  paths_le k'' (𝒫 k'' (Suc v''))" 
              using k'' Prefixes_subset_paths_le by blast            
            then have subset3: "Gen (Prefixes p)  Gen (paths_le k'' (𝒫 k'' (Suc v'')))"
              using Gen_def LocalLexing_axioms by auto
            have k''_less_k: "k'' < k" using k'' k' using indexlt_simp less_Suc_eq by auto 
            then have k''_Doc_bound: "k''  length Doc" using less by auto
            from less(1)[OF k''_less_k k''_Doc_bound, of "Suc v''"]
            have induct1: "items_le k'' (𝒥 k'' (Suc v'')) = Gen (paths_le k'' (𝒫 k'' (Suc v'')))"
              by blast
            from less(1)[OF k''_less_k k''_Doc_bound, of "Suc(Suc v'')"]
            have induct2: "𝒯 k'' (Suc (Suc v'')) = 𝒵 k'' (Suc (Suc v''))" by blast
            have subset4: "Gen (Prefixes p)  items_le k'' (𝒥 k'' (Suc v''))"
              using subset3 induct1 by auto
            from induct1 subset4
            have subset6: "Scan T k'' (Gen (Prefixes p))  
              Scan T k'' (items_le k'' (𝒥 k'' (Suc v'')))"
              apply (rule_tac monoD[OF mono_Scan])
              by blast
            have "k'' + length (chars_of_token X) = k"
              by (simp add: h9)
            have " t. t  T  length (chars_of_token t)  length (chars_of_token X)"
              using T by auto
            from Scan_items_le[of T, OF this, simplified, of k'' "𝒥 k'' (Suc v'')"] h9
            have subset7: "Scan T k'' (items_le k'' (𝒥 k'' (Suc v'')))
               items_le k (Scan T k'' (𝒥 k'' (Suc v'')))" by simp
            have "T  𝒵 k'' (Suc (Suc v''))" using T k''
              using 𝒵_subset_Suc rev_subsetD singletonD subsetI by blast 
            then have T_subset_𝒯: "T  𝒯 k'' (Suc (Suc v''))" using induct2 by auto
            have subset8: "Scan T k'' (𝒥 k'' (Suc v'')) 
              Scan (𝒯 k'' (Suc (Suc v''))) k'' (𝒥 k'' (Suc v''))" 
              using T_subset_𝒯 Scan_mono_tokens by blast
            have subset9: "Scan (𝒯 k'' (Suc (Suc v''))) k'' (𝒥 k'' (Suc v''))  𝒥 k'' (Suc (Suc v''))"
              by (rule Scan_𝒥_subset_𝒥)
            have subset10: "(Scan T k'' (𝒥 k'' (Suc v'')))  𝒥 k'' (Suc (Suc v''))"
              using subset8 subset9 by blast
            have "k''  k'" using k'' indexlt_simp by auto
            then have "indexle k'' (Suc (Suc v'')) k' (Suc (Suc v''))" using indexlt_simp
              using indexle_def le_neq_implies_less by auto
            then have subset11: "𝒥 k'' (Suc (Suc v''))  𝒥 k' (Suc (Suc v''))"
              using 𝒥_subset by blast
            have subset12: "Scan T k'' (𝒥 k'' (Suc v''))  𝒥 k' (Suc (Suc v''))"
              using subset8 subset9 subset10 subset11 by blast
            then have subset13: "items_le k (Scan T k'' (𝒥 k'' (Suc v''))) 
              items_le k (𝒥 k' (Suc (Suc v'')))"
              using items_le_def mem_Collect_eq rev_subsetD subsetI by auto 
            have subset14: "Scan T k'' (Gen (Prefixes p))  items_le k (𝒥 k' (Suc (Suc v'')))"
              using subset6 subset7 subset13 by blast
            then have x_in': "x  π k {} (items_le k (𝒥 k' (Suc (Suc v''))))"
              using x_in
              by (meson π_apply_setmonotone π_subset_elem_trans subsetCE subsetI)
            from x_in' have "x  π k {} (natUnion (λ v. items_le k (𝒥 k' v)))"
              by (meson k' mono_π mono_subset_elem natUnion_superset)
          }
          note suffices6 = this
          {
            fix v :: nat
            have "Gen (paths_eq k (𝒫 k' v))  π k {} (natUnion (λ v. items_le k (𝒥 k' v)))"
              using suffices6 by (meson Gen_implies_pvalid subsetI) 
          }
          note suffices5 = this
          {
            fix v :: nat
            have "paths_le k (𝒫 k' v) = paths_le k' (𝒫 k' v)  paths_eq k (𝒫 k' v)"
              using  paths_le_split_via_eq k' by metis
            then have Gen_split: "Gen (paths_le k (𝒫 k' v)) = 
              Gen (paths_le k' (𝒫 k' v))  Gen(paths_eq k (𝒫 k' v))" using Gen_union by metis
            have case_le: "Gen (paths_le k' (𝒫 k' v))   π k {} (natUnion (λ v. items_le k (𝒥 k' v)))"
            proof -
              from less k'_less_k have "k'  length Doc" by arith
              from less(1)[OF k'_less_k this]
              have "items_le k' (𝒥 k' v) = Gen (paths_le k' (𝒫 k' v))" by blast
              then have "Gen (paths_le k' (𝒫 k' v))  natUnion (λ v. items_le k (𝒥 k' v))"
                using items_le_def LocalLexing_axioms k'_less_k natUnion_superset by fastforce
              then show ?thesis using π_apply_setmonotone by blast
            qed
            have "Gen (paths_le k (𝒫 k' v))  π k {} (natUnion (λ v. items_le k (𝒥 k' v)))"
              using Gen_split case_le suffices5 UnE rev_subsetD subsetI by blast 
          }
          note suffices4 = this
          have super_lemma: "Gen (paths_le k (𝒫 k 0))  items_le k (𝒥 k 0)"
            apply (subst simp_right)
            apply (subst simp_left')
            using suffices4 by (meson natUnion_ex rev_subsetD subsetI) 
          from super_lemma sub_lemma show ?thesis by blast
        qed             
        then show ?case using thmD13 less.prems by blast   
    qed
qed

end

end