import Mathlib import Langlib.Grammars.Indexed.Definition import Langlib.Classes.Indexed.Definition import Langlib.Classes.ContextFree.Definition import Langlib.Classes.ContextFree.Closure.Intersection import Langlib.Classes.ContextFree.Inclusion.Indexed /-! # Strict Inclusion: CF ⊊ Indexed This file proves that the class of indexed languages strictly contains the class of context-free languages, by exhibiting a witness: the language `{aⁿbⁿcⁿ | n ∈ ℕ}` is indexed but not context-free. The indexed grammar uses a stack-bottom marker to ensure that each nonterminal consumes exactly as many flags as were pushed. ## Main declarations - `is_Indexed_lang_eq_eq` — `{aⁿbⁿcⁿ}` is an indexed language - `CF_strict_subclass_Indexed` — CF ⊊ Indexed -/ open List section anbncn /-- Nonterminals for the aⁿbⁿcⁿ indexed grammar. -/ inductive ANBNCN_NT where | S | T | A | B | C deriving DecidableEq /-- Flags for the aⁿbⁿcⁿ indexed grammar. -/ inductive ANBNCN_Flag where | count | bottom deriving DecidableEq def grammar_anbncn_indexed : IndexedGrammar (Fin 3) where nt := ANBNCN_NT flag := ANBNCN_Flag initial := .S rules := [ { lhs := .S, consume := none, rhs := [IRhsSymbol.nonterminal .T (some .bottom)] }, { lhs := .T, consume := none, rhs := [IRhsSymbol.nonterminal .T (some .count)] }, { lhs := .T, consume := none, rhs := [IRhsSymbol.nonterminal .A none, IRhsSymbol.nonterminal .B none, IRhsSymbol.nonterminal .C none] }, { lhs := .A, consume := some .count, rhs := [IRhsSymbol.terminal 0, IRhsSymbol.nonterminal .A none] }, { lhs := .A, consume := some .bottom, rhs := [] }, { lhs := .B, consume := some .count, rhs := [IRhsSymbol.terminal 1, IRhsSymbol.nonterminal .B none] }, { lhs := .B, consume := some .bottom, rhs := [] }, { lhs := .C, consume := some .count, rhs := [IRhsSymbol.terminal 2, IRhsSymbol.nonterminal .C none] }, { lhs := .C, consume := some .bottom, rhs := [] } ] private abbrev G := grammar_anbncn_indexed private abbrev iS (σ : List ANBNCN_Flag) : G.ISym := .indexed .S σ private abbrev iT (σ : List ANBNCN_Flag) : G.ISym := .indexed .T σ private abbrev iA (σ : List ANBNCN_Flag) : G.ISym := .indexed .A σ private abbrev iB (σ : List ANBNCN_Flag) : G.ISym := .indexed .B σ private abbrev iC (σ : List ANBNCN_Flag) : G.ISym := .indexed .C σ private abbrev ia : G.ISym := .terminal 0 private abbrev ib : G.ISym := .terminal 1 private abbrev ic : G.ISym := .terminal 2 private abbrev stk (n : ℕ) : List ANBNCN_Flag := replicate n .count ++ [.bottom] private lemma stk_succ (n : ℕ) : stk (n + 1) = .count :: stk n := by simp [stk, replicate_succ] -- ==================== Forward direction ==================== private lemma step_S_to_T : G.Transforms [iS []] [iT [.bottom]] := ⟨⟨.S, none, [.nonterminal .T (some .bottom)]⟩, [], [], [], by simp [G, grammar_anbncn_indexed], rfl, rfl⟩ private lemma push_counts (n : ℕ) : G.Derives [iT (stk 0)] [iT (stk n)] := by induction n with | zero => exact Relation.ReflTransGen.refl | succ n ih => apply ih.tail refine ⟨⟨.T, none, [.nonterminal .T (some .count)]⟩, [], [], stk n, by simp [G, grammar_anbncn_indexed], rfl, ?_⟩ simp [IndexedGrammar.expandRhs, stk_succ] private lemma step_T_to_ABC (σ : List ANBNCN_Flag) : G.Transforms [iT σ] [iA σ, iB σ, iC σ] := ⟨⟨.T, none, [.nonterminal .A none, .nonterminal .B none, .nonterminal .C none]⟩, [], [], σ, by simp [G, grammar_anbncn_indexed], rfl, rfl⟩ private lemma consume_A (n : ℕ) (suffix : List G.ISym) : G.Derives ([iA (stk n)] ++ suffix) (replicate n ia ++ suffix) := by induction' n with n ih generalizing suffix; · convert Relation.ReflTransGen.single _ using 1; use ⟨ .A, some .bottom, [ ] ⟩; use [], suffix, [] simp [G]; exact ⟨ by tauto, rfl ⟩; · -- Apply the rule 3 (A consume count): Transforms ([iA (.count :: stk n)] ++ suffix) ([ia, iA (stk n)] ++ suffix). have step_A_count : G.Transforms ([iA (.count :: stk n)] ++ suffix) ([ia, iA (stk n)] ++ suffix) := by use ⟨ .A, some .count, [IRhsSymbol.terminal 0, IRhsSymbol.nonterminal .A none] ⟩, [], suffix, stk n; exact ⟨ by tauto, by tauto ⟩; have step_A_count : G.Derives ([ia, iA (stk n)] ++ suffix) (replicate (n + 1) ia ++ suffix) := by have step_A_count : G.Derives ([iA (stk n)] ++ suffix) (replicate n ia ++ suffix) := by exact ih suffix; convert G.deri_with_prefix [ia] step_A_count using 1; exact .single ‹_› |> Relation.ReflTransGen.trans <| step_A_count private lemma consume_B (n : ℕ) (suffix : List G.ISym) : G.Derives ([iB (stk n)] ++ suffix) (replicate n ib ++ suffix) := by -- We proceed by induction on $n$. induction' n with n ih generalizing suffix; · exact .single ( by use ⟨ .B, some .bottom, [ ] ⟩; unfold G; simp +decide [ stk ] ; exact ⟨ by simp +decide [ grammar_anbncn_indexed ], [ ], suffix, [ ], rfl, rfl ⟩ ); · -- Apply rule 5 (B consume count): r = {.B, some .count, [terminal 1, nonterminal .B none]}, u=[], v=suffix, σ=stk n. have h_rule5 : G.Transforms ([iB (stk (n + 1))] ++ suffix) ([ib, iB (stk n)] ++ suffix) := by use ⟨.B, some .count, [IRhsSymbol.terminal 1, IRhsSymbol.nonterminal .B none]⟩, [], suffix, stk n; simp +decide [ grammar_anbncn_indexed ]; exact ⟨ rfl, rfl ⟩; -- By the induction hypothesis, we can derive [ib, iB (stk n)] ++ suffix to replicate n ib ++ suffix. have h_ind : G.Derives ([ib, iB (stk n)] ++ suffix) (replicate (n + 1) ib ++ suffix) := by convert G.deri_with_prefix [ib] (ih suffix) using 1; exact .single h_rule5 |> Relation.ReflTransGen.trans <| h_ind private lemma consume_C (n : ℕ) : G.Derives [iC (stk n)] (replicate n ic) := by induction' n with n ih; · constructor; constructor; exists ⟨ .C, some .bottom, [ ] ⟩, [ ], [ ], [ ]; simp +decide [ G ]; exact?; · -- Apply the transformation from iC (stk (n + 1)) to ic :: iC (stk n). have h_transform : G.Transforms [iC (stk (n + 1))] (ic :: iC (stk n) :: []) := by use ⟨.C, some .count, [IRhsSymbol.terminal 2, IRhsSymbol.nonterminal .C none]⟩; use [], [], stk n; simp +decide [ grammar_anbncn_indexed ]; exact ⟨ rfl, rfl ⟩; convert G.deri_of_deri_deri _ _ using 1; exact [ ic, iC ( stk n ) ]; · exact .single h_transform; · convert G.deri_with_prefix [ ic ] ih using 1 private lemma anbncn_generates (n : ℕ) : replicate n (0 : Fin 3) ++ replicate n 1 ++ replicate n 2 ∈ G.Language := by show G.Generates _ unfold IndexedGrammar.Generates apply IndexedGrammar.deri_of_tran_deri step_S_to_T apply IndexedGrammar.deri_of_deri_deri (push_counts n) apply IndexedGrammar.deri_of_tran_deri (step_T_to_ABC (stk n)) apply IndexedGrammar.deri_of_deri_deri (consume_A n [iB (stk n), iC (stk n)]) apply IndexedGrammar.deri_of_deri_deri (IndexedGrammar.deri_with_prefix (replicate n ia) (consume_B n [iC (stk n)])) convert IndexedGrammar.deri_with_prefix (replicate n ia ++ replicate n ib) (consume_C n) using 1 · simp [List.append_assoc] · simp [List.map_append, List.map_replicate] -- ==================== Backward direction ==================== /-- Structural invariant for reachable sentential forms. -/ private inductive GoodForm : List G.ISym → Prop where | start : GoodForm [iS []] | withT (n : ℕ) : GoodForm [iT (stk n)] | withABC (n ja jb jc : ℕ) (doneA doneB doneC : Bool) (hja : ja ≤ n) (hjb : jb ≤ n) (hjc : jc ≤ n) (hdA : doneA = true → ja = n) (hdB : doneB = true → jb = n) (hdC : doneC = true → jc = n) : GoodForm (replicate ja ia ++ (if doneA then [] else [iA (stk (n - ja))]) ++ replicate jb ib ++ (if doneB then [] else [iB (stk (n - jb))]) ++ replicate jc ic ++ (if doneC then [] else [iC (stk (n - jc))])) /- Case 1: form = [iS []] -/ private lemma goodForm_step_case1 {form' : List G.ISym} (ht : G.Transforms [iS []] form') : GoodForm form' := by cases ht; rename_i r hr; obtain ⟨ u, v, σ, hr₁, hr₂, rfl ⟩ := hr; rcases u with ( _ | ⟨ x, u ⟩ ) <;> rcases v with ( _ | ⟨ y, v ⟩ ) <;> simp_all +decide [ List.append_eq_append_iff ]; · rcases r with ⟨ _ | _, _ | _, _ | _ ⟩ <;> simp_all +decide [ G ]; · contradiction; · cases hr₁; · exact GoodForm.withT 0; · contradiction; · cases r_consume : r.consume <;> simp_all +decide; · cases r : r.consume <;> simp_all +decide; · cases r : r.consume <;> simp_all +decide /- Case 2: form = [iT (stk n)] -/ private lemma goodForm_step_case2 {n : ℕ} {form' : List G.ISym} (ht : G.Transforms [iT (stk n)] form') : GoodForm form' := by obtain ⟨ r, u, v, σ, hr, h₁, h₂ ⟩ := ht; rcases r with ⟨ lhs, consume, rhs ⟩; rcases u with ( _ | ⟨ _, _ | u ⟩ ) <;> simp_all +decide [ G ]; · unfold grammar_anbncn_indexed at *; rcases consume with ( _ | _ | consume ) <;> simp_all +decide; · rcases hr with ( ⟨ rfl, rfl ⟩ | rfl | rfl ) <;> simp_all +decide [ IndexedGrammar.expandRhs ]; · convert GoodForm.withT ( n + 1 ) using 1; aesop; · convert GoodForm.withABC n 0 0 0 false false false _ _ _ _ _ _ using 1 <;> simp +decide [ h₁ ]; · grind; · grind; · cases consume <;> contradiction; · cases consume <;> contradiction /- Splitting a list at a unique nonterminal type. If both sides split at the first occurrence of an `indexed nt` symbol, then the prefixes, the symbol, and the suffixes agree. -/ private lemma split_unique_nt {nt : ANBNCN_NT} {σ₁ σ₂ : List ANBNCN_Flag} {u₁ u₂ v₁ v₂ : List G.ISym} (h₁ : ∀ x ∈ u₁, ∀ σ, x ≠ IndexedGrammar.ISym.indexed nt σ) (h₂ : ∀ x ∈ u₂, ∀ σ, x ≠ IndexedGrammar.ISym.indexed nt σ) (heq : u₁ ++ IndexedGrammar.ISym.indexed nt σ₁ :: v₁ = u₂ ++ IndexedGrammar.ISym.indexed nt σ₂ :: v₂) : u₁ = u₂ ∧ σ₁ = σ₂ ∧ v₁ = v₂ := by induction' u₁ with a u₁ ih generalizing u₂ v₁ v₂ <;> induction' u₂ with b u₂ ih' <;> simp +decide at heq ⊢; · tauto; · exact h₂ _ ( List.mem_cons_self ) _ heq.1.symm; · exact h₁ _ ( List.mem_cons_self ) _ heq.1; · grind +ring /-- Terminals are never indexed symbols. -/ private lemma terminal_ne_indexed (t : Fin 3) (nt : ANBNCN_NT) (σ : List ANBNCN_Flag) : (IndexedGrammar.ISym.terminal t : G.ISym) ≠ IndexedGrammar.ISym.indexed nt σ := by intro h; cases h /-- No element of `replicate k (terminal t)` is an indexed symbol. -/ private lemma no_indexed_in_replicate (k : ℕ) (t : Fin 3) (nt : ANBNCN_NT) : ∀ x ∈ replicate k (IndexedGrammar.ISym.terminal t : G.ISym), ∀ σ, x ≠ IndexedGrammar.ISym.indexed nt σ := by intro x hx σ; rw [eq_of_mem_replicate hx]; exact terminal_ne_indexed t nt σ /-- Distinct nonterminal types give distinct indexed symbols. -/ private lemma indexed_ne_of_nt_ne {nt₁ nt₂ : ANBNCN_NT} (hne : nt₁ ≠ nt₂) (σ₁ σ₂ : List ANBNCN_Flag) : (IndexedGrammar.ISym.indexed nt₁ σ₁ : G.ISym) ≠ IndexedGrammar.ISym.indexed nt₂ σ₂ := by intro h; cases h; exact hne rfl /-- No A-indexed symbol in `replicate k ia ++ oA_or_empty` when `oA_or_empty` has no A (e.g. when doneA = true, or when looking for B/C). -/ private lemma no_A_before_A (ja : ℕ) : ∀ x ∈ replicate ja ia, ∀ σ, x ≠ IndexedGrammar.ISym.indexed ANBNCN_NT.A σ := no_indexed_in_replicate ja 0 .A /- No B-indexed symbol in the prefix before B in the form. -/ private lemma no_B_before_B (ja : ℕ) (doneA : Bool) (n jb : ℕ) (hja : ja ≤ n) : ∀ x ∈ replicate ja ia ++ (if doneA then [] else [iA (stk (n - ja))]) ++ replicate jb ib, ∀ σ, x ≠ IndexedGrammar.ISym.indexed ANBNCN_NT.B σ := by grind /- No C-indexed symbol in the prefix before C in the form. -/ private lemma no_C_before_C (ja : ℕ) (doneA : Bool) (n jb : ℕ) (doneB : Bool) (jc : ℕ) (hja : ja ≤ n) (hjb : jb ≤ n) : ∀ x ∈ replicate ja ia ++ (if doneA then [] else [iA (stk (n - ja))]) ++ replicate jb ib ++ (if doneB then [] else [iB (stk (n - jb))]) ++ replicate jc ic, ∀ σ, x ≠ IndexedGrammar.ISym.indexed ANBNCN_NT.C σ := by grind /- No S-indexed symbol in the ABC form. -/ private lemma no_S_in_abc_form (ja jb jc : ℕ) (n : ℕ) (doneA doneB doneC : Bool) (hja : ja ≤ n) (hjb : jb ≤ n) (hjc : jc ≤ n) : ∀ x ∈ replicate ja ia ++ (if doneA then [] else [iA (stk (n - ja))]) ++ replicate jb ib ++ (if doneB then [] else [iB (stk (n - jb))]) ++ replicate jc ic ++ (if doneC then [] else [iC (stk (n - jc))]), ∀ σ, x ≠ IndexedGrammar.ISym.indexed ANBNCN_NT.S σ := by grind /- No T-indexed symbol in the ABC form. -/ private lemma no_T_in_abc_form (ja jb jc : ℕ) (n : ℕ) (doneA doneB doneC : Bool) (hja : ja ≤ n) (hjb : jb ≤ n) (hjc : jc ≤ n) : ∀ x ∈ replicate ja ia ++ (if doneA then [] else [iA (stk (n - ja))]) ++ replicate jb ib ++ (if doneB then [] else [iB (stk (n - jb))]) ++ replicate jc ic ++ (if doneC then [] else [iC (stk (n - jc))]), ∀ σ, x ≠ IndexedGrammar.ISym.indexed ANBNCN_NT.T σ := by aesop ( simp_config := { singlePass := true } ) ; /- Sub-case: an A-type rule fires on the ABC form (doneA = false). -/ private lemma goodForm_step_on_A {n ja jb jc : ℕ} {doneB doneC : Bool} {form' : List G.ISym} (hja : ja ≤ n) (hjb : jb ≤ n) (hjc : jc ≤ n) (hdB : doneB = true → jb = n) (hdC : doneC = true → jc = n) {f : ANBNCN_Flag} {rhs : List (IRhsSymbol (Fin 3) ANBNCN_NT ANBNCN_Flag)} {u v : List G.ISym} {σ : List ANBNCN_Flag} (hr : ⟨ANBNCN_NT.A, some f, rhs⟩ ∈ G.rules) (heq : u ++ IndexedGrammar.ISym.indexed ANBNCN_NT.A (f :: σ) :: v = replicate ja ia ++ [iA (stk (n - ja))] ++ replicate jb ib ++ (if doneB then [] else [iB (stk (n - jb))]) ++ replicate jc ic ++ (if doneC then [] else [iC (stk (n - jc))])) (hform' : form' = u ++ IndexedGrammar.expandRhs G rhs σ ++ v) : GoodForm form' := by -- Prove that $u = \text{replicate } ja \, ia$. have hu : u = replicate ja ia := by have h_u : ∃ a, replicate ja ia = u ++ a ∧ iA (stk (n - ja)) :: replicate jb ib ++ (if doneB = true then [] else [iB (stk (n - jb))]) ++ replicate jc ic ++ (if doneC = true then [] else [iC (stk (n - jc))]) = a ++ IndexedGrammar.ISym.indexed ANBNCN_NT.A (f :: σ) :: v ∨ ∃ a, u = replicate ja ia ++ a ∧ iA (stk (n - ja)) :: replicate jb ib ++ (if doneB = true then [] else [iB (stk (n - jb))]) ++ replicate jc ic ++ (if doneC = true then [] else [iC (stk (n - jc))]) = a ++ IndexedGrammar.ISym.indexed ANBNCN_NT.A (f :: σ) :: v := by have h_u : u ++ IndexedGrammar.ISym.indexed ANBNCN_NT.A (f :: σ) :: v = replicate ja ia ++ (iA (stk (n - ja)) :: replicate jb ib ++ (if doneB = true then [] else [iB (stk (n - jb))]) ++ replicate jc ic ++ (if doneC = true then [] else [iC (stk (n - jc))])) := by grind; rw [ List.append_eq_append_iff ] at h_u; rcases h_u with ( ⟨ as, has₁, has₂ ⟩ | ⟨ bs, hbs₁, hbs₂ ⟩ ) <;> simp_all +decide [ List.append_assoc ]; rcases as with ( _ | ⟨ a, as ⟩ ) <;> simp_all +decide [ List.append_assoc ]; have h_contra : ∀ x ∈ replicate ja ia, x ≠ IndexedGrammar.ISym.indexed ANBNCN_NT.A (f :: σ) := by intro x hx; rw [ List.eq_of_mem_replicate hx ] ; exact terminal_ne_indexed _ _ _; grind; obtain ⟨ a, ha ⟩ := h_u; rcases ha with ( ⟨ ha₁, ha₂ ⟩ | ⟨ a, rfl, ha₂ ⟩ ); · replace ha₂ := congr_arg List.reverse ha₂ ; simp_all +decide [ List.reverse_append ]; · rcases a with ( _ | ⟨ x, a ⟩ ) <;> simp_all +decide [ List.append_assoc ]; have h_contradiction : ∀ x ∈ replicate jb ib ++ (if doneB = true then [] else [iB (stk (n - jb))]) ++ replicate jc ic ++ (if doneC = true then [] else [iC (stk (n - jc))]), ∀ σ, x ≠ IndexedGrammar.ISym.indexed ANBNCN_NT.A σ := by grind +splitIndPred; grind +ring; -- Prove that $f :: σ = stk (n - ja)$. have hfs : f :: σ = stk (n - ja) := by replace heq := congr_arg ( fun x => x.drop ja ) heq ; simp_all +decide [ List.drop_append ] ; rcases k : n - ja with ( _ | k ) <;> simp_all +decide [ stk_succ ]; · unfold G at *; simp_all +decide [ grammar_anbncn_indexed ] ; cases hr <;> simp_all +decide [ stk ]; convert GoodForm.withABC n n jb jc true doneB doneC _ _ _ _ _ _ using 1 <;> norm_num [ Nat.sub_eq_zero_iff_le.mpr hja ]; · rw [ Nat.sub_eq_iff_eq_add ] at k <;> first | linarith | aesop; · linarith; · linarith; · exact hdB; · exact hdC; · unfold G at hr; simp_all +decide [ grammar_anbncn_indexed ] ; convert GoodForm.withABC n ( ja + 1 ) jb jc Bool.false doneB doneC _ _ _ _ _ _ using 1 <;> norm_num [ Nat.succ_eq_add_one, Nat.add_sub_add_right ]; all_goals norm_cast; · simp +decide [ ← k, List.replicate_add, IndexedGrammar.expandRhs ]; omega; · omega /- Sub-case: a B-type rule fires on the ABC form (doneB = false). -/ private lemma goodForm_step_on_B {n ja jb jc : ℕ} {doneA doneC : Bool} {form' : List G.ISym} (hja : ja ≤ n) (hjb : jb ≤ n) (hjc : jc ≤ n) (hdA : doneA = true → ja = n) (hdC : doneC = true → jc = n) {f : ANBNCN_Flag} {rhs : List (IRhsSymbol (Fin 3) ANBNCN_NT ANBNCN_Flag)} {u v : List G.ISym} {σ : List ANBNCN_Flag} (hr : ⟨ANBNCN_NT.B, some f, rhs⟩ ∈ G.rules) (heq : u ++ IndexedGrammar.ISym.indexed ANBNCN_NT.B (f :: σ) :: v = replicate ja ia ++ (if doneA then [] else [iA (stk (n - ja))]) ++ replicate jb ib ++ [iB (stk (n - jb))] ++ replicate jc ic ++ (if doneC then [] else [iC (stk (n - jc))])) (hform' : form' = u ++ IndexedGrammar.expandRhs G rhs σ ++ v) : GoodForm form' := by have h_split : ∃ u' v', u = replicate ja ia ++ (if doneA then [] else [iA (stk (n - ja))]) ++ replicate jb ib ++ u' ∧ v = v' ++ replicate jc ic ++ (if doneC then [] else [iC (stk (n - jc))]) := by have h_split : u ++ IndexedGrammar.ISym.indexed ANBNCN_NT.B (f :: σ) :: v = (replicate ja ia ++ if doneA = true then [] else [iA (stk (n - ja))]) ++ replicate jb ib ++ ([iB (stk (n - jb))] ++ replicate jc ic ++ if doneC = true then [] else [iC (stk (n - jc))]) := by simpa only [ List.append_assoc ] using heq; rw [ List.append_eq_append_iff ] at h_split; rcases h_split with ( ⟨ as, has₁, has₂ ⟩ | ⟨ bs, has₁, has₂ ⟩ ) <;> simp_all +decide [ List.append_assoc ]; · rcases as with ( _ | ⟨ a, as ⟩ ) <;> simp_all +decide [ List.append_assoc ]; have := no_B_before_B ja doneA n jb hja; simp_all +decide [ List.append_assoc ] ; exact this _ ( Or.inr <| Or.inl rfl ) _ has₂.1.symm; · rcases bs with ( _ | ⟨ x, bs ⟩ ) <;> simp_all +decide [ List.append_assoc ]; have h_split : ∀ x ∈ replicate jc ic ++ (if doneC then [] else [iC (stk (n - jc))]), ∀ σ, x ≠ IndexedGrammar.ISym.indexed ANBNCN_NT.B σ := by split_ifs <;> simp_all +decide [ List.mem_append, List.mem_replicate ]; rintro x ( ⟨ _, rfl ⟩ | rfl ) σ <;> simp +decide [ IndexedGrammar.ISym ]; grind; obtain ⟨ u', v', rfl, rfl ⟩ := h_split; simp_all +decide [ List.append_assoc ] ; rcases u' with ( _ | ⟨ _, _ | u' ⟩ ) <;> simp_all +decide [ List.append_assoc ] ; · rcases n' : n - jb with ( _ | n' ) <;> simp_all +decide [ stk_succ ]; · unfold G at hr; simp_all +decide [ stk ] ; unfold grammar_anbncn_indexed at hr; simp_all +decide [ List.mem_cons ] ; convert GoodForm.withABC n ja n jc doneA true doneC _ _ _ _ _ _ using 1 <;> simp_all +decide [ Nat.sub_eq_iff_eq_add ]; · rcases hr' : rhs with ( _ | ⟨ x, _ | ⟨ y, rhs ⟩ ⟩ ) <;> simp_all +decide [ G ] ; · contradiction; · rcases x with ( _ | _ | x ) <;> simp_all +decide [ grammar_anbncn_indexed ]; · unfold grammar_anbncn_indexed at hr; simp_all +decide ; unfold grammar_anbncn_indexed; simp +decide [ IndexedGrammar.expandRhs ] ; convert GoodForm.withABC n ja ( jb + 1 ) jc doneA false doneC ( by linarith ) ( by omega ) ( by omega ) ( by aesop ) ( by aesop ) using 1 ; simp +decide [ List.replicate_add ] ; ring; rw [ show n - ( 1 + jb ) = n - jb - 1 by rw [ Nat.sub_sub, add_comm ] ] ; simp +decide [ n', heq ] ; aesop; · replace heq := congr_arg List.length heq.2 ; simp_all +arith +decide [ List.length_append ] ; · replace heq := congr_arg List.length heq.2 ; simp_all +arith +decide; /- Sub-case: a C-type rule fires on the ABC form (doneC = false). -/ private lemma goodForm_step_on_C {n ja jb jc : ℕ} {doneA doneB : Bool} {form' : List G.ISym} (hja : ja ≤ n) (hjb : jb ≤ n) (hjc : jc ≤ n) (hdA : doneA = true → ja = n) (hdB : doneB = true → jb = n) {f : ANBNCN_Flag} {rhs : List (IRhsSymbol (Fin 3) ANBNCN_NT ANBNCN_Flag)} {u v : List G.ISym} {σ : List ANBNCN_Flag} (hr : ⟨ANBNCN_NT.C, some f, rhs⟩ ∈ G.rules) (heq : u ++ IndexedGrammar.ISym.indexed ANBNCN_NT.C (f :: σ) :: v = replicate ja ia ++ (if doneA then [] else [iA (stk (n - ja))]) ++ replicate jb ib ++ (if doneB then [] else [iB (stk (n - jb))]) ++ replicate jc ic ++ [iC (stk (n - jc))]) (hform' : form' = u ++ IndexedGrammar.expandRhs G rhs σ ++ v) : GoodForm form' := by have h_split : u = replicate ja ia ++ (if doneA then [] else [iA (stk (n - ja))]) ++ replicate jb ib ++ (if doneB then [] else [iB (stk (n - jb))]) ++ replicate jc ic := by have hu : ∀ x ∈ u, ∀ σ, x ≠ IndexedGrammar.ISym.indexed ANBNCN_NT.C σ := by rw [ List.append_eq_append_iff ] at heq; rcases heq with ( ⟨ as, has₁, has₂ ⟩ | ⟨ bs, rfl, hbs ⟩ ) <;> simp_all +decide [ List.append_assoc ]; · have := no_C_before_C ja doneA n jb doneB jc hja hjb; aesop; · cases bs <;> aesop; apply (split_unique_nt ?_ ?_ heq).left; · assumption; · apply_rules [ no_C_before_C ]; rcases f with ( _ | _ ) <;> simp_all +decide [ G ]; · rcases k : n - jc with ( _ | k ) <;> simp_all +decide [ stk ]; simp_all +decide [ replicate ]; convert GoodForm.withABC n ja jb ( jc + 1 ) doneA doneB false _ _ _ _ _ _ using 1 <;> simp_all +decide [ Nat.sub_succ ]; · simp_all +decide [ replicate_add, grammar_anbncn_indexed, IndexedGrammar.expandRhs ]; · omega; · rcases k : n - jc with ( _ | _ | k ) <;> simp_all +decide [ stk ]; · unfold grammar_anbncn_indexed at hr; simp_all +decide ; split_ifs <;> simp_all +decide [ GoodForm ]; · convert GoodForm.withABC n n n n Bool.true Bool.true Bool.true _ _ _ _ _ _ using 1 <;> simp +decide [ * ]; rw [ Nat.sub_eq_iff_eq_add ] at k <;> aesop; · convert GoodForm.withABC n n jb jc doneA doneB true _ _ _ _ _ _ using 1 <;> simp +decide [ *, Nat.sub_eq_iff_eq_add' hjc ]; omega; · convert GoodForm.withABC n ja n jc doneA true true _ _ _ _ _ _ using 1 <;> simp +decide [ *, Nat.sub_eq_iff_eq_add ]; omega; · convert GoodForm.withABC n ja jb jc doneA doneB true _ _ _ _ _ _ using 1 <;> simp +decide [ *, Nat.sub_eq_iff_eq_add ]; omega; · cases heq.1 /- Case 3: ABC form -/ set_option maxHeartbeats 400000 in private lemma goodForm_step_case3 {n ja jb jc : ℕ} {doneA doneB doneC : Bool} {form' : List G.ISym} (hja : ja ≤ n) (hjb : jb ≤ n) (hjc : jc ≤ n) (hdA : doneA = true → ja = n) (hdB : doneB = true → jb = n) (hdC : doneC = true → jc = n) (ht : G.Transforms (replicate ja ia ++ (if doneA then [] else [iA (stk (n - ja))]) ++ replicate jb ib ++ (if doneB then [] else [iB (stk (n - jb))]) ++ replicate jc ic ++ (if doneC then [] else [iC (stk (n - jc))])) form') : GoodForm form' := by obtain ⟨ r, u, v, σ, hr, heq, rfl ⟩ := ht; by_cases hA : r.lhs = .A; · rcases r_consume : r.consume with ( _ | _ | _ ) <;> simp_all +decide; · rcases r with ⟨ lhs, consume, rhs ⟩ ; simp_all +decide [ grammar_anbncn_indexed ] ; · by_cases hdoneA : doneA = true; · replace heq := congr_arg ( fun x => ∀ y ∈ x, ∀ σ : List ANBNCN_Flag, y ≠ IndexedGrammar.ISym.indexed ANBNCN_NT.A σ ) heq ; simp_all +decide [ List.mem_append, List.mem_replicate ]; grind; · convert goodForm_step_on_A hja hjb hjc hdB hdC _ _ _; exact ANBNCN_Flag.count; exact r.rhs; exact u; exact v; exact σ; · cases r ; aesop; · grind; · rw [ List.append_assoc ]; · rcases doneA with ( _ | _ | _ ) <;> simp_all +decide [ add_assoc ]; · apply goodForm_step_on_A hja hjb hjc hdB hdC; rotate_left; convert heq.symm using 1; grind; rw [ List.append_assoc ]; cases r ; aesop; · replace heq := congr_arg ( fun x => x.map ( fun y => y ≠ IndexedGrammar.ISym.indexed ANBNCN_NT.A ( ANBNCN_Flag.bottom :: σ ) ) ) heq ; simp_all +decide [ List.map_append, List.map_replicate ]; no_nonterminal (False) at heq · by_cases hB : r.lhs = .B; · by_cases hC : doneB = true; · have h_no_B : ∀ x ∈ replicate ja ia ++ (if doneA then [] else [iA (stk (n - ja))]) ++ replicate jb ib ++ (if doneB then [] else [iB (stk (n - jb))]) ++ replicate jc ic ++ (if doneC then [] else [iC (stk (n - jc))]), ∀ σ, x ≠ IndexedGrammar.ISym.indexed ANBNCN_NT.B σ := by grind +splitIndPred; cases r_consume : r.consume <;> simp_all +decide; · exact False.elim <| h_no_B _ ( Or.inr <| Or.inl rfl ) _ rfl; · exact False.elim <| h_no_B _ ( Or.inr <| Or.inl rfl ) _ rfl; · cases r_consume : r.consume <;> simp_all +decide; · unfold G at hr; simp_all +decide [ grammar_anbncn_indexed ] ; rcases hr with ( rfl | rfl | rfl | rfl | rfl | rfl | rfl | rfl | rfl ) <;> simp_all +decide; · convert goodForm_step_on_B hja hjb hjc hdA hdC _ _ _; exact ‹G.flag›; exact r.rhs; exact u; exact v; exact σ; · cases r ; aesop; · grind; · rw [ List.append_assoc ]; · by_cases hC : r.lhs = .C; · by_cases hC' : doneC = true <;> simp_all +decide; · cases r_consume : r.consume <;> simp_all +decide; · unfold G at hr; simp_all +decide [ grammar_anbncn_indexed ] ; rcases hr with ( rfl | rfl | rfl | rfl | rfl | rfl | rfl | rfl | rfl ) <;> simp_all +decide; · have := no_C_before_C ja doneA n jb doneB jc hja hjb; simp_all +decide [ List.mem_append, List.mem_replicate ] ; exact False.elim <| this _ ( Or.inr <| Or.inl rfl ) _ rfl; · cases r_consume : r.consume <;> simp_all +decide [ G ]; · unfold grammar_anbncn_indexed at hr; aesop; · apply goodForm_step_on_C hja hjb hjc hdA hdB; rotate_left; convert heq.symm using 1; grind; rw [ List.append_assoc ]; cases r ; aesop; · rcases r with ⟨ lhs, consume, rhs ⟩; cases lhs <;> cases consume <;> simp_all +decide [ G ]; · have := no_S_in_abc_form ja jb jc n doneA doneB doneC hja hjb hjc; simp_all +decide [ List.mem_append, List.mem_replicate ] ; exact False.elim <| this _ ( Or.inr <| Or.inl rfl ) _ rfl; · cases hr; contradiction; · have := no_T_in_abc_form ja jb jc n doneA doneB doneC hja hjb hjc; simp_all +decide [List.mem_append, List.mem_replicate]; exact False.elim <| this _ (Or.inr <| Or.inl rfl) _ rfl; · cases hr; contradiction private lemma goodForm_step {form form' : List G.ISym} (hg : GoodForm form) (ht : G.Transforms form form') : GoodForm form' := by cases hg with | start => exact goodForm_step_case1 ht | withT n => exact goodForm_step_case2 ht | withABC n ja jb jc doneA doneB doneC hja hjb hjc hdA hdB hdC => exact goodForm_step_case3 hja hjb hjc hdA hdB hdC ht private lemma goodForm_derives {form : List G.ISym} (hd : G.Derives [iS []] form) : GoodForm form := by induction hd with | refl => exact GoodForm.start | tail _ ht ih => exact goodForm_step ih ht private lemma goodForm_terminal {w : List (Fin 3)} (hg : GoodForm (w.map IndexedGrammar.ISym.terminal)) : ∃ n, w = replicate n 0 ++ replicate n 1 ++ replicate n 2 := by contrapose hg; -- By cases on hg, we can derive a contradiction with the assumption that w is not of the form replicate n 0 ++ replicate n 1 ++ replicate n 2. intro h obtain ⟨n, hn⟩ : ∃ n : ℕ, w = List.replicate n 0 ++ List.replicate n 1 ++ List.replicate n 2 := by have h_form : ∀ {w : List G.ISym}, GoodForm w → (∀ s ∈ w, s ∈ Set.range (fun t : Fin 3 => IndexedGrammar.ISym.terminal t)) → ∃ n : ℕ, w = List.map (fun t : Fin 3 => IndexedGrammar.ISym.terminal t) (List.replicate n 0 ++ List.replicate n 1 ++ List.replicate n 2) := by intros w hw hw_terminal induction' hw with w hw ih; · cases hw_terminal _ ( List.mem_singleton_self _ ); cases ‹_›; · cases hw_terminal _ ( List.mem_singleton_self _ ) ; aesop; · split_ifs at hw_terminal <;> simp_all +decide [ Set.range ]; grind; any_goals have := hw_terminal _ ( Or.inr <| Or.inr <| Or.inr <| rfl ) ; obtain ⟨ y, hy ⟩ := this; cases y ; cases hy; any_goals have := hw_terminal _ ( Or.inr <| Or.inl rfl ) ; obtain ⟨ y, hy ⟩ := this; cases y ; cases hy; · have := hw_terminal _ ( Or.inr <| Or.inr <| Or.inl rfl ) ; obtain ⟨ y, hy ⟩ := this; cases y ; cases hy; · have := hw_terminal _ ( Or.inr <| Or.inr <| Or.inl rfl ) ; obtain ⟨ y, hy ⟩ := this; cases y ; cases hy; obtain ⟨ n, hn ⟩ := h_form h ( by aesop ); exact ⟨ n, by simpa using List.map_injective_iff.mpr ( show Function.Injective ( fun t : Fin 3 => IndexedGrammar.ISym.terminal t ) from fun a b h => by cases a ; cases b ; cases h ; trivial ) hn ⟩; exact hg ⟨ n, hn ⟩ theorem is_Indexed_lang_eq_eq : is_Indexed lang_eq_eq := by refine ⟨G, ?_⟩ ext w; constructor · intro hw exact goodForm_terminal (goodForm_derives hw) · intro hw obtain ⟨n, rfl⟩ := hw exact anbncn_generates n end anbncn