import Langlib.Classes.ContextSensitive.Inclusion.RecursivelyEnumerable /-! # Non-Contracting Grammar Definitions This file defines non-contracting grammars as unrestricted grammars whose rules never decrease the length of the rewritten sentential form. It also contains the grammar-level translation machinery relating non-contracting grammars to context-sensitive grammars. ## Overview A **non-contracting grammar** (also called monotone grammar) is an unrestricted grammar where every rule satisfies `|output| ≥ |input|`, i.e., the right-hand side is at least as long as the left-hand side. The equivalence of these two formulations is a classical result in formal language theory. Every context-sensitive grammar is non-contracting (easy direction), and every non-contracting grammar can in principle be converted to an equivalent context-sensitive grammar (hard direction). ## Main declarations - `grammar_noncontracting` — predicate for non-contracting unrestricted grammars - `is_noncontracting` — language class of non-contracting grammars ## References The equivalence is standard; see e.g. Hopcroft, Motwani, Ullman, "Introduction to Automata Theory, Languages, and Computation", Chapter 9. -/ open List Relation variable {T : Type} /-! ## Non-contracting grammars -/ /-- An unrestricted grammar is *non-contracting* (monotone) if for every rule, the output string is at least as long as the full input pattern `input_L ++ [input_N] ++ input_R`. -/ def grammar_noncontracting (g : grammar T) : Prop := ∀ r ∈ g.rules, r.output_string.length ≥ r.input_L.length + 1 + r.input_R.length /-- Predicate: a language is generated by some non-contracting grammar. -/ def is_noncontracting (L : Language T) : Prop := ∃ g : grammar T, grammar_noncontracting g ∧ grammar_language g = L