import Langlib.Grammars.ContextSensitive.Toolbox import Langlib.Classes.ContextSensitive.Inclusion.RecursivelyEnumerable import Langlib.Grammars.ContextSensitive.UnrestrictedCharacterization import Langlib.Classes.RecursivelyEnumerable.Closure.Reverse import Langlib.Utilities.LanguageOperations import Langlib.Utilities.ListUtils import Langlib.Utilities.ClosurePredicates /-! # Context-Sensitive Closure Under Reversal This file proves that context-sensitive languages are closed under word reversal. ## Strategy We reuse `grammar_language_reversal_grammar` (the unrestricted result) together with a commutation lemma showing that reversing a CS grammar and embedding it as an unrestricted grammar gives the same result as embedding first and then reversing. ## Main declarations - `reversal_csrule` — reverse a single CS rule - `reversal_CS_grammar` — reverse every rule of a CS grammar - `grammar_of_csg_reversal_comm` — commutation with the CS→unrestricted embedding - `CS_of_reverse_CS` - `CS_of_reverse_CS_rev` - `CS_reverse_iff_CS` -/ variable {T : Type} section reversal_defs /-- Reverse a single context-sensitive rule: swap and reverse the contexts, reverse the output string. -/ def reversal_csrule {N : Type} (r : csrule T N) : csrule T N := csrule.mk r.context_right.reverse r.input_nonterminal r.context_left.reverse r.output_string.reverse private lemma dual_of_reversal_csrule {N : Type} (r : csrule T N) : reversal_csrule (reversal_csrule r) = r := by cases r unfold reversal_csrule simp [List.reverse_reverse] private lemma reversal_csrule_reversal_csrule {N : Type} : @reversal_csrule T N ∘ @reversal_csrule T N = id := by ext; apply dual_of_reversal_csrule /-- Reverse every rule of a context-sensitive grammar. -/ def reversal_CS_grammar (g : CS_grammar T) : CS_grammar T := CS_grammar.mk g.nt g.initial (List.map reversal_csrule g.rules) ( by intros r rh have x := g.output_nonempty simp only [List.mem_map] at rh rcases rh with ⟨a, ha_rules, ha_eq⟩ unfold reversal_csrule at ha_eq simp only [ha_eq.symm, ne_eq, List.reverse_eq_nil_iff] exact g.output_nonempty a ha_rules ) lemma dual_of_reversal_CS_grammar (g : CS_grammar T) : reversal_CS_grammar (reversal_CS_grammar g) = g := by cases g unfold reversal_CS_grammar simp [List.map_map, reversal_csrule_reversal_csrule] end reversal_defs section commutation /-- Reversing a CS grammar and then embedding it as an unrestricted grammar gives the same grammar as embedding first and then applying the unrestricted reversal. -/ theorem grammar_of_csg_reversal_comm (g : CS_grammar T) : grammar_of_csg (reversal_CS_grammar g) = reversal_grammar (grammar_of_csg g) := by cases g with | mk nt initial rules => simp only [reversal_CS_grammar, grammar_of_csg, reversal_grammar] congr 1 rw [List.map_map, List.map_map] congr 1 ext r simp [reversal_grule, reversal_csrule, List.reverse_append] end commutation section closure /-- The class of context-sensitive languages is closed under reversal. -/ theorem CS_of_reverse_CS (L : Language T) : is_CS L → is_CS (L.reverse) := by intro h obtain ⟨g, hgL⟩ := is_CS_implies_is_CS_via_csg h apply is_CS_via_csg_implies_is_CS refine ⟨reversal_CS_grammar g, ?_⟩ rw [CS_language_eq_grammar_language, grammar_of_csg_reversal_comm, grammar_language_reversal_grammar, ← CS_language_eq_grammar_language, hgL] /-- The converse direction: if the reversal is CS then so is the original. -/ theorem CS_of_reverse_CS_rev (L : Language T) : is_CS (L.reverse) → is_CS L := by intro h have h' := CS_of_reverse_CS L.reverse h simpa using h' /-- A language is context-sensitive iff its reversal is. -/ @[simp] theorem CS_reverse_iff_CS (L : Language T) : is_CS (L.reverse) ↔ is_CS L := by constructor · exact CS_of_reverse_CS_rev L · exact CS_of_reverse_CS L end closure /-- The class of context-sensitive languages is closed under reversal. -/ theorem CS_closedUnderReverse : ClosedUnderReverse (α := T) is_CS := fun L hL => CS_of_reverse_CS L hL