Langlib

Langlib.Classes.ContextSensitive.Basics.NonContracting

ε-elimination of context-sensitive grammars #

Every context-sensitive language (in the broad S → ε-optional grammar_context_sensitive sense) admits an equivalent — off the empty word — non-contracting grammar with finitely many nonterminals (exists_noncontracting_offEmpty_of_CS). This is the structural normal form used, e.g., in the CS = LBA (Kuroda) construction and in establishing CS ⊆ Recursive.

Strategy #

With the standard definition of grammar_context_sensitive, the start symbol S never occurs on a right-hand side once the optional S → ε rule is present. This makes ε-elimination elementary: simply delete every contracting rule (i.e. keep only the non-contracting ones). Concretely, set

g' := { nt := g.nt, initial := g.initial,
        rules := g.rules.filter (fun r => decide (grule_noncontracting r)) }.

g' is non-contracting by construction, and grammar_language g' = grammar_language g \ {[]}. The non-obvious inclusion is : starting from the single start symbol [S] (with the target word ≠ []), the very first rule fired has empty context and input_N = S; it cannot be the S → ε rule (that yields [], which is stuck), so it is non-contracting and its output is S-free (by initial_not_on_rhs). From there every sentential form stays S-free, and on an S-free form the matched rule is never the S → ε rule, hence non-contracting and kept in g'. So the whole g-derivation is in fact a g'-derivation.

Main declarations #

The key language identity #

ε-elimination #

ε-elimination. Every broadly-context-sensitive grammar admits an equivalent (off the empty word) ε-free non-contracting grammar with finitely many nonterminals. We take gFilter g (delete the contracting rules) and finitize its nonterminals with restrictGrammar.