Langlib

Langlib.Grammars.NonContracting.Equivalence.ContextSensitive

Non-Contracting and Context-Sensitive #

This file contains class-level comparison results between non-contracting grammars and context-sensitive grammars.

main results

The unrestricted grammar obtained from a context-sensitive grammar (via grammar_of_csg) is non-contracting.

Every non-contracting language is context-sensitive in the broader definition.

theorem noncontracting_transforms_length_le {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {w₁ w₂ : List (symbol T g.nt)} (h : grammar_transforms g w₁ w₂) :
w₁.length w₂.length

A single transformation step in a non-contracting grammar does not decrease the length of the sentential form.

Non-contracting → CS #

The conversion from a non-contracting grammar to a context-sensitive grammar is a classical construction. Given a non-contracting rule L ++ [A] ++ R → output with |output| ≥ |L| + 1 + |R|, we simulate it using context-sensitive rules with fresh auxiliary nonterminals.

Construction #

The nonterminal type of the constructed CS grammar is g.nt ⊕ (T ⊕ (ℕ × ℕ)):

The sentential forms in the CS grammar always consist entirely of nonterminals (either Sum.inl n or Sum.inr (Sum.inl t)), except at the very end when un-lifting rules convert Sum.inr (Sum.inl t) to terminal t.

The rules are:

  1. Un-lifting rules: Sum.inr (Sum.inl t) → [terminal t]
  2. Direct rules (n = 1): Sum.inl A → map liftSym output
  3. Phase 1 (n ≥ 2, marking): Replace pattern symbols with auxiliaries left-to-right
  4. Phase 2 (n ≥ 2, output): Replace auxiliaries with output symbols right-to-left
@[reducible, inline]
abbrev NC_NT {T : Type} (g : grammar T) :

Nonterminal type for the CS grammar constructed from a non-contracting grammar.

Equations
Instances For
    def nc_symToNT {T : Type} {g : grammar T} :
    symbol T g.ntNC_NT g

    Convert a symbol to a nonterminal in the new grammar (lifting terminals).

    Equations
    Instances For
      def nc_liftSym {T : Type} {g : grammar T} (s : symbol T g.nt) :

      Lift a symbol: all symbols become nonterminal symbols in the new grammar.

      Equations
      Instances For
        def nc_aux {T : Type} {g : grammar T} (ri k : ) :

        Auxiliary nonterminal symbol for rule index ri, step k.

        Equations
        Instances For
          def nc_collectTerminals {T N : Type} :
          List (symbol T N)List T

          Collect all terminals from a list of symbols.

          Equations
          Instances For
            def nc_grammarTerminals {T : Type} (g : grammar T) :

            All terminals appearing in the grammar's rules (inputs and outputs).

            Equations
            Instances For
              def nc_unliftRules {T : Type} (g : grammar T) :
              List (csrule T (NC_NT g))

              Un-lifting rules: convert lifted terminal nonterminals back to actual terminals.

              Equations
              • One or more equations did not get rendered due to their size.
              Instances For
                def nc_simRules {T : Type} {g : grammar T} (ri : ) (r : grule T g.nt) :
                List (csrule T (NC_NT g))

                Generate CS rules for simulating one grammar rule at index ri.

                Equations
                • One or more equations did not get rendered due to their size.
                Instances For
                  def nc_allRules {T : Type} (g : grammar T) :
                  List (csrule T (NC_NT g))

                  All CS rules: un-lifting rules plus simulation rules for each grammar rule.

                  Equations
                  Instances For

                    Every rule in nc_unliftRules has nonempty output.

                    theorem nc_simRules_output_nonempty {T : Type} (g : grammar T) (hg : grammar_noncontracting g) (ri : ) (grule : grule T g.nt) (hgrule : grule g.rules) (r : csrule T (NC_NT g)) (hr : r nc_simRules ri grule) :

                    Every rule in nc_simRules has nonempty output, provided the non-contracting property.

                    noncomputable def csg_of_noncontracting {T : Type} (g : grammar T) (hg : grammar_noncontracting g) :

                    Construct a context-sensitive grammar equivalent to a given non-contracting grammar.

                    Equations
                    Instances For

                      Helper lemmas for language equivalence #

                      theorem CS_deri_with_context {T : Type} {g : CS_grammar T} {w₁ w₂ : List (symbol T g.nt)} (p s : List (symbol T g.nt)) (h : CS_derives g w₁ w₂) :
                      CS_derives g (p ++ w₁ ++ s) (p ++ w₂ ++ s)
                      theorem CS_transform_removed_symbol_is_input_general {T : Type} {g : CS_grammar T} {s₁ s₂ : List (symbol T g.nt)} {x : symbol T g.nt} (h : CS_transforms g s₁ s₂) (hx₁ : x s₁) (hx₂ : xs₂) :
                      theorem CS_transform_removed_symbol_actual_input {T : Type} {g : CS_grammar T} {s₁ s₂ : List (symbol T g.nt)} {x : symbol T g.nt} (h : CS_transforms g s₁ s₂) (hx₁ : x s₁) (hx₂ : xs₂) :
                      theorem CS_transform_removed_symbol_is_input_with_output_mem {T : Type} {g : CS_grammar T} {s₁ s₂ : List (symbol T g.nt)} {x : symbol T g.nt} (h : CS_transforms g s₁ s₂) (hx₁ : x s₁) (hx₂ : xs₂) :
                      rg.rules, x = symbol.nonterminal r.input_nonterminal yr.output_string, y s₂
                      theorem CS_transform_added_symbol_is_output_general {T : Type} {g : CS_grammar T} {s₁ s₂ : List (symbol T g.nt)} {x : symbol T g.nt} (h : CS_transforms g s₁ s₂) (hx₂ : x s₂) (hx₁ : xs₁) :
                      rg.rules, x r.output_string
                      theorem CS_transform_added_symbol_is_output_with_input_mem {T : Type} {g : CS_grammar T} {s₁ s₂ : List (symbol T g.nt)} {x : symbol T g.nt} (h : CS_transforms g s₁ s₂) (hx₂ : x s₂) (hx₁ : xs₁) :
                      theorem nc_unlift_all {T : Type} (g : grammar T) (hg : grammar_noncontracting g) (w : List T) (hw : tw, t nc_grammarTerminals g) :
                      theorem nc_simRule_mem {T : Type} (g : grammar T) (hg : grammar_noncontracting g) (ri : ) (r : grule T g.nt) (hri : ri < g.rules.length) (hr : g.rules[ri] = r) (cr : csrule T (NC_NT g)) (hcr : cr nc_simRules ri r) :
                      theorem nc_rule_zip_mem_get {T : Type} (g : grammar T) {ri : } {r : grule T g.nt} (hpair : (ri, r) (List.range g.rules.length).zip g.rules) :
                      ∃ (hri : ri < g.rules.length), g.rules[ri] = r

                      Membership in the zipped rule-index list recovers the indexed rule.

                      theorem nc_rule_zip_rule_unique {T : Type} (g : grammar T) {ri : } {r₁ r₂ : grule T g.nt} (h₁ : (ri, r₁) (List.range g.rules.length).zip g.rules) (h₂ : (ri, r₂) (List.range g.rules.length).zip g.rules) :
                      r₁ = r₂

                      The rule component for a fixed simulation-rule index is unique.

                      theorem list_append_singleton_eq_of_not_mem {α : Type} {x : α} {a b c d : List α} (ha : xa) (hc : xc) (h : a ++ [x] ++ b = c ++ [x] ++ d) :
                      a = c b = d

                      A list decomposition around the first occurrence of a marker is unique.

                      theorem list_prefix_not_mem_of_unique_singleton_decomp {α : Type} {x : α} {u w a b : List α} (hu : xu) (hw : xw) (h : u ++ [x] ++ w = a ++ [x] ++ b) :
                      xa

                      If u ++ [x] ++ w has no x in u or w, then any decomposition of the same list as a ++ [x] ++ b has no x in a.

                      theorem nc_sim_one_transform {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {w₁ w₂ : List (symbol T g.nt)} (h : grammar_transforms g w₁ w₂) :

                      A single grammar step can be simulated by CS derivation on lifted forms.

                      theorem nc_sim_derives {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {w₁ w₂ : List (symbol T g.nt)} (h : grammar_derives g w₁ w₂) :
                      theorem nc_derived_terminal_in_grammarTerminals {T : Type} (g : grammar T) (w : List T) (hw : w grammar_language g) (t : T) (ht : t w) :

                      Forward correctness of the non-contracting-to-CS construction.

                      Every terminal word generated by the original non-contracting unrestricted grammar is generated by the constructed context-sensitive grammar. The reverse containment is the remaining hard direction because derivations in the constructed grammar may pass through auxiliary nonterminals before returning to clean sentential forms.

                      Locked non-contracting → CS construction #

                      The first construction above is convenient for forward simulation, but its phase-2 cleanup rules use clean output symbols as right context. That is too permissive for the reverse direction: a cleanup rule can match symbols from the surrounding sentential context and skip the locked output phase. The locked construction below uses fresh output markers for every produced output position, and only erases those markers to clean lifted symbols after the simulated rule has completed.

                      inductive NC_LockedNT {T : Type} (g : grammar T) :

                      Nonterminals for the locked CS construction.

                      Instances For
                        def nc_locked_symToNT {T : Type} {g : grammar T} :

                        Convert an original symbol to a locked-construction nonterminal.

                        Equations
                        Instances For
                          theorem nc_locked_symToNT_ne_out {T : Type} {g : grammar T} (s : symbol T g.nt) (ri k : ) (a : symbol T g.nt) :
                          def nc_locked_liftSym {T : Type} {g : grammar T} (s : symbol T g.nt) :

                          Lift an original symbol into the locked construction.

                          Equations
                          Instances For
                            def nc_locked_mark {T : Type} {g : grammar T} (ri k : ) :

                            Input-position marker for a simulated rule.

                            Equations
                            Instances For
                              def nc_locked_out {T : Type} {g : grammar T} (ri k : ) (s : symbol T g.nt) :

                              Output-position marker for a simulated rule.

                              Equations
                              Instances For
                                def nc_locked_outputSuffix {T : Type} {g : grammar T} (ri : ) (out : List (symbol T g.nt)) (dflt : symbol T g.nt) (k : ) :

                                Marked output suffix beginning at position k.

                                Equations
                                Instances For
                                  def nc_locked_outputFrom {T : Type} {g : grammar T} (ri : ) (out : List (symbol T g.nt)) (dflt : symbol T g.nt) (k : ) :

                                  Marked output suffix beginning at position k, forced syntactically nonempty. For non-contracting rules the head index is in bounds; the default only keeps the definition total.

                                  Equations
                                  Instances For

                                    Un-lifting rules for the locked construction.

                                    Equations
                                    • One or more equations did not get rendered due to their size.
                                    Instances For
                                      def nc_locked_simRules {T : Type} {g : grammar T} (ri : ) (r : grule T g.nt) :

                                      Simulation rules for one original non-contracting rule in the locked construction.

                                      Equations
                                      • One or more equations did not get rendered due to their size.
                                      Instances For

                                        All locked-construction CS rules.

                                        Equations
                                        • One or more equations did not get rendered due to their size.
                                        Instances For
                                          theorem nc_locked_simRules_output_nonempty {T : Type} (g : grammar T) (ri : ) (grule : grule T g.nt) (r : csrule T (NC_LockedNT g)) (hr : r nc_locked_simRules ri grule) :
                                          noncomputable def locked_csg_of_noncontracting {T : Type} (g : grammar T) (_hg : grammar_noncontracting g) :

                                          Locked CS grammar for a non-contracting grammar.

                                          Equations
                                          Instances For
                                            theorem nc_locked_simRule_mem {T : Type} (g : grammar T) (hg : grammar_noncontracting g) (ri : ) (r : grule T g.nt) (hri : ri < g.rules.length) (hr : g.rules[ri] = r) (cr : csrule T (NC_LockedNT g)) (hcr : cr nc_locked_simRules ri r) :

                                            A locked simulation rule is a rule of the locked constructed CS grammar.

                                            theorem nc_locked_unliftRule_mem {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {t : T} (ht : t nc_grammarTerminals g) :
                                            { context_left := [], input_nonterminal := NC_LockedNT.term t, context_right := [], output_string := [symbol.terminal t] } (locked_csg_of_noncontracting g hg).rules

                                            An un-lifting rule is a rule of the locked constructed CS grammar.

                                            Un-lift one locked terminal marker to the actual terminal.

                                            Un-lift all locked terminal markers in a terminal word.

                                            Clean up one locked output marker into the corresponding lifted output symbol.

                                            theorem nc_locked_outputSuffix_nil_of_len_le {T : Type} (g : grammar T) (ri : ) (out : List (symbol T g.nt)) (dflt : symbol T g.nt) (k : ) (hk : out.length k) :
                                            theorem nc_locked_outputSuffix_cons {T : Type} (g : grammar T) (ri : ) (out : List (symbol T g.nt)) (dflt : symbol T g.nt) (k : ) (hk : k < out.length) :
                                            nc_locked_outputSuffix ri out dflt k = [nc_locked_out ri k (out.getD k dflt)] ++ nc_locked_outputSuffix ri out dflt (k + 1)
                                            theorem nc_locked_outputFrom_eq_suffix {T : Type} (g : grammar T) (ri : ) (out : List (symbol T g.nt)) (dflt : symbol T g.nt) (k : ) (hk : k < out.length) :
                                            nc_locked_outputFrom ri out dflt k = nc_locked_outputSuffix ri out dflt k
                                            theorem nc_locked_outputSuffix_mem_out_shape {T : Type} (g : grammar T) {ri ri' k k' : } {out : List (symbol T g.nt)} {dflt a : symbol T g.nt} (hmem : nc_locked_out ri' k' a nc_locked_outputSuffix ri out dflt k) :
                                            ri' = ri k k' k' < out.length a = out.getD k' dflt
                                            theorem nc_locked_outputFrom_mem_out_shape {T : Type} (g : grammar T) {ri ri' k k' : } {out : List (symbol T g.nt)} {dflt a : symbol T g.nt} (hk : k < out.length) (hmem : nc_locked_out ri' k' a nc_locked_outputFrom ri out dflt k) :
                                            ri' = ri k k' k' < out.length a = out.getD k' dflt
                                            theorem nc_locked_outputSuffix_head_mem {T : Type} (g : grammar T) (ri : ) (out : List (symbol T g.nt)) (dflt : symbol T g.nt) (k : ) (hk : k < out.length) :
                                            nc_locked_out ri k (out.getD k dflt) nc_locked_outputSuffix ri out dflt k
                                            theorem nc_locked_take_succ_map {T : Type} (g : grammar T) (out : List (symbol T g.nt)) (dflt : symbol T g.nt) (k : ) (hk : k < out.length) :

                                            Forward correctness of the locked non-contracting-to-CS construction.

                                            def nc_locked_proj {T : Type} (g : grammar T) (s : List (symbol T (NC_LockedNT g))) :
                                            List (symbol T g.nt)

                                            Project a locked-construction sentential form back to original grammar symbols.

                                            Equations
                                            Instances For
                                              def nc_locked_is_clean {T : Type} (g : grammar T) (s : List (symbol T (NC_LockedNT g))) :

                                              A locked sentential form is clean if it contains no input or output markers.

                                              Equations
                                              Instances For
                                                theorem nc_locked_is_clean_of_subset {T : Type} (g : grammar T) {s t : List (symbol T (NC_LockedNT g))} (hclean : nc_locked_is_clean g t) (hsub : xs, x t) :
                                                theorem nc_locked_not_clean_iff_exists_marker {T : Type} (g : grammar T) (s : List (symbol T (NC_LockedNT g))) :
                                                ¬nc_locked_is_clean g s (∃ (ri : ) (k : ), nc_locked_mark ri k s) ∃ (ri : ) (k : ) (a : symbol T g.nt), nc_locked_out ri k a s
                                                theorem nc_locked_clean_step_proj_eq {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : CS_transforms (locked_csg_of_noncontracting g hg) s₁ s₂) (hclean₁ : nc_locked_is_clean g s₁) (hclean₂ : nc_locked_is_clean g s₂) :
                                                theorem nc_locked_clean_step_grammar_derives {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : CS_transforms (locked_csg_of_noncontracting g hg) s₁ s₂) (hclean₁ : nc_locked_is_clean g s₁) (hclean₂ : nc_locked_is_clean g s₂) :
                                                theorem nc_locked_clean_step_dirty_mark_zero_shape {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : CS_transforms (locked_csg_of_noncontracting g hg) s₁ s₂) (hclean : nc_locked_is_clean g s₁) (hdirty : ¬nc_locked_is_clean g s₂) :
                                                ∃ (simRi : ) (grule : grule T g.nt) (u : List (symbol T (NC_LockedNT g))) (v : List (symbol T (NC_LockedNT g))), (simRi, grule) (List.range g.rules.length).zip g.rules have pattern := grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R; have dflt := symbol.nonterminal grule.input_N; s₁ = u ++ [nc_locked_liftSym (pattern.getD 0 dflt)] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v s₂ = u ++ [nc_locked_mark simRi 0] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v
                                                theorem nc_locked_dirty_step_clean_cleanup_shape {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : CS_transforms (locked_csg_of_noncontracting g hg) s₁ s₂) (hdirty : ¬nc_locked_is_clean g s₁) (hclean : nc_locked_is_clean g s₂) :
                                                ∃ (simRi : ) (grule : grule T g.nt) (k : ) (u : List (symbol T (NC_LockedNT g))) (v : List (symbol T (NC_LockedNT g))), (simRi, grule) (List.range g.rules.length).zip g.rules k < grule.output_string.length have dflt := symbol.nonterminal grule.input_N; s₁ = u ++ [nc_locked_out simRi k (grule.output_string.getD k dflt)] ++ v s₂ = u ++ [nc_locked_liftSym (grule.output_string.getD k dflt)] ++ v
                                                theorem nc_locked_rule_mem_cases {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {cr : csrule T (NC_LockedNT g)} (hcr : cr (locked_csg_of_noncontracting g hg).rules) :
                                                (∃ tnc_grammarTerminals g, cr = { context_left := [], input_nonterminal := NC_LockedNT.term t, context_right := [], output_string := [symbol.terminal t] }) ∃ (simRi : ) (grule : grule T g.nt), (simRi, grule) (List.range g.rules.length).zip g.rules have pattern := grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R; have dflt := symbol.nonterminal grule.input_N; (∃ k < pattern.length, cr = { context_left := List.map (nc_locked_mark simRi) (List.range k), input_nonterminal := nc_locked_symToNT (pattern.getD k dflt), context_right := List.map nc_locked_liftSym (List.drop (k + 1) pattern), output_string := [nc_locked_mark simRi k] }) cr = { context_left := List.map (nc_locked_mark simRi) (List.range (pattern.length - 1)), input_nonterminal := NC_LockedNT.mark simRi (pattern.length - 1), context_right := [], output_string := nc_locked_outputFrom simRi grule.output_string dflt (pattern.length - 1) } (∃ k < pattern.length - 1, cr = { context_left := List.map (nc_locked_mark simRi) (List.range k), input_nonterminal := NC_LockedNT.mark simRi k, context_right := nc_locked_outputSuffix simRi grule.output_string dflt (k + 1), output_string := [nc_locked_out simRi k (grule.output_string.getD k dflt)] }) k < grule.output_string.length, cr = { context_left := [], input_nonterminal := NC_LockedNT.out simRi k (grule.output_string.getD k dflt), context_right := [], output_string := [nc_locked_liftSym (grule.output_string.getD k dflt)] }
                                                theorem nc_locked_rule_input_mark_shape {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {cr : csrule T (NC_LockedNT g)} (hcr : cr (locked_csg_of_noncontracting g hg).rules) {ri k : } (hinput : cr.input_nonterminal = NC_LockedNT.mark ri k) :
                                                ∃ (simRi : ) (grule : grule T g.nt), (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi have pattern := grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R; have dflt := symbol.nonterminal grule.input_N; k = pattern.length - 1 cr = { context_left := List.map (nc_locked_mark simRi) (List.range (pattern.length - 1)), input_nonterminal := NC_LockedNT.mark simRi (pattern.length - 1), context_right := [], output_string := nc_locked_outputFrom simRi grule.output_string dflt (pattern.length - 1) } k < pattern.length - 1 cr = { context_left := List.map (nc_locked_mark simRi) (List.range k), input_nonterminal := NC_LockedNT.mark simRi k, context_right := nc_locked_outputSuffix simRi grule.output_string dflt (k + 1), output_string := [nc_locked_out simRi k (grule.output_string.getD k dflt)] }
                                                theorem nc_locked_rule_input_out_shape {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {cr : csrule T (NC_LockedNT g)} (hcr : cr (locked_csg_of_noncontracting g hg).rules) {ri k : } {a : symbol T g.nt} (hinput : cr.input_nonterminal = NC_LockedNT.out ri k a) :
                                                ∃ (simRi : ) (grule : grule T g.nt), (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi k < grule.output_string.length a = grule.output_string.getD k (symbol.nonterminal grule.input_N) cr = { context_left := [], input_nonterminal := NC_LockedNT.out simRi k (grule.output_string.getD k (symbol.nonterminal grule.input_N)), context_right := [], output_string := [nc_locked_liftSym (grule.output_string.getD k (symbol.nonterminal grule.input_N))] }
                                                theorem nc_locked_rule_output_mark_shape {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {cr : csrule T (NC_LockedNT g)} (hcr : cr (locked_csg_of_noncontracting g hg).rules) {ri k : } (hout : nc_locked_mark ri k cr.output_string) :
                                                ∃ (simRi : ) (grule : grule T g.nt), (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi have pattern := grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R; have dflt := symbol.nonterminal grule.input_N; k < pattern.length cr = { context_left := List.map (nc_locked_mark simRi) (List.range k), input_nonterminal := nc_locked_symToNT (pattern.getD k dflt), context_right := List.map nc_locked_liftSym (List.drop (k + 1) pattern), output_string := [nc_locked_mark simRi k] }
                                                theorem nc_locked_rule_output_out_shape {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {cr : csrule T (NC_LockedNT g)} (hcr : cr (locked_csg_of_noncontracting g hg).rules) {ri k : } {a : symbol T g.nt} (hout : nc_locked_out ri k a cr.output_string) :
                                                ∃ (simRi : ) (grule : grule T g.nt), (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi k < grule.output_string.length a = grule.output_string.getD k (symbol.nonterminal grule.input_N) have pattern := grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R; have dflt := symbol.nonterminal grule.input_N; pattern.length - 1 k cr = { context_left := List.map (nc_locked_mark simRi) (List.range (pattern.length - 1)), input_nonterminal := NC_LockedNT.mark simRi (pattern.length - 1), context_right := [], output_string := nc_locked_outputFrom simRi grule.output_string dflt (pattern.length - 1) } k < pattern.length - 1 cr = { context_left := List.map (nc_locked_mark simRi) (List.range k), input_nonterminal := NC_LockedNT.mark simRi k, context_right := nc_locked_outputSuffix simRi grule.output_string dflt (k + 1), output_string := [nc_locked_out simRi k (grule.output_string.getD k dflt)] }
                                                theorem nc_locked_transform_added_mark_shape {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : CS_transforms (locked_csg_of_noncontracting g hg) s₁ s₂) {ri k : } (htgt : nc_locked_mark ri k s₂) (hsrc : nc_locked_mark ri ks₁) :
                                                ∃ (simRi : ) (grule : grule T g.nt), (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi have pattern := grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R; have dflt := symbol.nonterminal grule.input_N; k < pattern.length cr(locked_csg_of_noncontracting g hg).rules, cr.context_left = List.map (nc_locked_mark simRi) (List.range k) cr.input_nonterminal = nc_locked_symToNT (pattern.getD k dflt) cr.context_right = List.map nc_locked_liftSym (List.drop (k + 1) pattern) cr.output_string = [nc_locked_mark simRi k]
                                                theorem nc_locked_transform_added_mark_source_context_marks {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : CS_transforms (locked_csg_of_noncontracting g hg) s₁ s₂) {ri k : } (htgt : nc_locked_mark ri k s₂) (hsrc : nc_locked_mark ri ks₁) :
                                                ∃ (simRi : ) (grule : grule T g.nt), (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi have pattern := grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R; k < pattern.length j < k, nc_locked_mark simRi j s₁

                                                If a transform newly creates marker k, then the rule that creates it is a phase-1 marking rule and all lower markers for that same simulation occur in the source. This records the context dependency of the locked input-marking phase.

                                                theorem nc_locked_transform_added_mark_from_single_mark_source {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : CS_transforms (locked_csg_of_noncontracting g hg) s₁ s₂) {baseRi targetRi targetK : } (htgt : nc_locked_mark targetRi targetK s₂) (hsrc : nc_locked_mark targetRi targetKs₁) (hmarks : ∀ (ri k : ), nc_locked_mark ri k s₁ (ri, k) = (baseRi, 0)) :
                                                ∃ (simRi : ) (grule : grule T g.nt), (simRi, grule) (List.range g.rules.length).zip g.rules targetRi = simRi have pattern := grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R; targetK < pattern.length (targetK = 0 simRi = baseRi targetK = 1)
                                                theorem nc_locked_transform_added_base_one_mark_shape {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : CS_transforms (locked_csg_of_noncontracting g hg) s₁ s₂) {baseRi : } (htgt : nc_locked_mark baseRi 1 s₂) (hsrc : nc_locked_mark baseRi 1s₁) (_hmarks : ∀ (ri k : ), nc_locked_mark ri k s₁ (ri, k) = (baseRi, 0)) :
                                                ∃ (grule : grule T g.nt), (baseRi, grule) (List.range g.rules.length).zip g.rules have pattern := grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R; have dflt := symbol.nonterminal grule.input_N; 1 < pattern.length cr(locked_csg_of_noncontracting g hg).rules, cr.context_left = [nc_locked_mark baseRi 0] cr.input_nonterminal = nc_locked_symToNT (pattern.getD 1 dflt) cr.context_right = List.map nc_locked_liftSym (List.drop 2 pattern) cr.output_string = [nc_locked_mark baseRi 1]

                                                If a step whose source contains a single phase-0 marker creates the phase-1 marker for that same simulation, then the step is exactly the first continuation marking rule for the corresponding original production.

                                                Exact source and target shape for the first continuation marking step of a locked simulation. Once the boundary phase-1 marker is newly created, the whole step is forced to replace the second lifted input symbol by that marker, with the original surrounding context unchanged.

                                                theorem nc_locked_transform_added_mark_preserves_source_mark {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : CS_transforms (locked_csg_of_noncontracting g hg) s₁ s₂) {targetRi targetK ri k : } (htgt : nc_locked_mark targetRi targetK s₂) (hsrc : nc_locked_mark targetRi targetKs₁) (hmark : nc_locked_mark ri k s₁) :
                                                theorem nc_locked_transform_added_out_shape {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : CS_transforms (locked_csg_of_noncontracting g hg) s₁ s₂) {ri k : } {a : symbol T g.nt} (htgt : nc_locked_out ri k a s₂) (hsrc : nc_locked_out ri k as₁) :
                                                ∃ (simRi : ) (grule : grule T g.nt), (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi k < grule.output_string.length a = grule.output_string.getD k (symbol.nonterminal grule.input_N) have pattern := grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R; have dflt := symbol.nonterminal grule.input_N; (pattern.length - 1 k cr(locked_csg_of_noncontracting g hg).rules, cr.context_left = List.map (nc_locked_mark simRi) (List.range (pattern.length - 1)) cr.input_nonterminal = NC_LockedNT.mark simRi (pattern.length - 1) cr.context_right = [] cr.output_string = nc_locked_outputFrom simRi grule.output_string dflt (pattern.length - 1)) k < pattern.length - 1 cr(locked_csg_of_noncontracting g hg).rules, cr.context_left = List.map (nc_locked_mark simRi) (List.range k) cr.input_nonterminal = NC_LockedNT.mark simRi k cr.context_right = nc_locked_outputSuffix simRi grule.output_string dflt (k + 1) cr.output_string = [nc_locked_out simRi k (grule.output_string.getD k dflt)]
                                                theorem nc_locked_transform_added_out_source_mark {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : CS_transforms (locked_csg_of_noncontracting g hg) s₁ s₂) {ri k : } {a : symbol T g.nt} (htgt : nc_locked_out ri k a s₂) (hsrc : nc_locked_out ri k as₁) :
                                                ∃ (simRi : ) (grule : grule T g.nt) (markIdx : ), (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi k < grule.output_string.length a = grule.output_string.getD k (symbol.nonterminal grule.input_N) have pattern := grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R; markIdx < pattern.length (pattern.length - 1 k markIdx = pattern.length - 1 k < pattern.length - 1 markIdx = k) nc_locked_mark simRi markIdx s₁
                                                theorem nc_locked_transform_added_out_from_out_free_source {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : CS_transforms (locked_csg_of_noncontracting g hg) s₁ s₂) {ri k : } {a : symbol T g.nt} (htgt : nc_locked_out ri k a s₂) (hsrc : nc_locked_out ri k as₁) (hnoout : ∀ (ri k : ) (a : symbol T g.nt), nc_locked_out ri k as₁) :
                                                ∃ (simRi : ) (grule : grule T g.nt), (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi k < grule.output_string.length a = grule.output_string.getD k (symbol.nonterminal grule.input_N) have pattern := grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R; pattern.length - 1 k nc_locked_mark simRi (pattern.length - 1) s₁
                                                theorem nc_locked_transform_removed_mark_shape {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : CS_transforms (locked_csg_of_noncontracting g hg) s₁ s₂) {ri k : } (hsrc : nc_locked_mark ri k s₁) (htgt : nc_locked_mark ri ks₂) :
                                                ∃ (simRi : ) (grule : grule T g.nt), (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi have pattern := grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R; have dflt := symbol.nonterminal grule.input_N; (k = pattern.length - 1 cr(locked_csg_of_noncontracting g hg).rules, cr.input_nonterminal = NC_LockedNT.mark simRi (pattern.length - 1) cr.context_left = List.map (nc_locked_mark simRi) (List.range (pattern.length - 1)) cr.context_right = [] cr.output_string = nc_locked_outputFrom simRi grule.output_string dflt (pattern.length - 1)) k < pattern.length - 1 cr(locked_csg_of_noncontracting g hg).rules, cr.input_nonterminal = NC_LockedNT.mark simRi k cr.context_left = List.map (nc_locked_mark simRi) (List.range k) cr.context_right = nc_locked_outputSuffix simRi grule.output_string dflt (k + 1) cr.output_string = [nc_locked_out simRi k (grule.output_string.getD k dflt)]
                                                theorem nc_locked_transform_removed_mark_adds_out {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : CS_transforms (locked_csg_of_noncontracting g hg) s₁ s₂) {ri k : } (hsrc : nc_locked_mark ri k s₁) (htgt : nc_locked_mark ri ks₂) :
                                                ∃ (simRi : ) (grule : grule T g.nt) (j : ), (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi j < grule.output_string.length nc_locked_out simRi j (grule.output_string.getD j (symbol.nonterminal grule.input_N)) s₂
                                                theorem nc_locked_transform_removed_out_adds_liftSym {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : CS_transforms (locked_csg_of_noncontracting g hg) s₁ s₂) {ri k : } {a : symbol T g.nt} (hsrc : nc_locked_out ri k a s₁) (htgt : nc_locked_out ri k as₂) :
                                                ∃ (simRi : ) (grule : grule T g.nt), (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi k < grule.output_string.length a = grule.output_string.getD k (symbol.nonterminal grule.input_N) nc_locked_liftSym a s₂
                                                theorem nc_locked_clean_step_dirty_mark_zero_unique {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : CS_transforms (locked_csg_of_noncontracting g hg) s₁ s₂) (hclean : nc_locked_is_clean g s₁) (hdirty : ¬nc_locked_is_clean g s₂) :
                                                ∃ (simRi : ) (grule : grule T g.nt) (u : List (symbol T (NC_LockedNT g))) (v : List (symbol T (NC_LockedNT g))), (simRi, grule) (List.range g.rules.length).zip g.rules nc_locked_is_clean g u nc_locked_is_clean g v (have pattern := grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R; have dflt := symbol.nonterminal grule.input_N; s₁ = u ++ [nc_locked_liftSym (pattern.getD 0 dflt)] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v s₂ = u ++ [nc_locked_mark simRi 0] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v) (∀ (ri k : ), nc_locked_mark ri k s₂ (ri, k) = (simRi, 0)) ∀ (ri k : ) (a : symbol T g.nt), nc_locked_out ri k as₂
                                                theorem nc_locked_dirty_step_clean_cleanup_unique {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : CS_transforms (locked_csg_of_noncontracting g hg) s₁ s₂) (hdirty : ¬nc_locked_is_clean g s₁) (hclean : nc_locked_is_clean g s₂) :
                                                ∃ (simRi : ) (grule : grule T g.nt) (k : ) (u : List (symbol T (NC_LockedNT g))) (v : List (symbol T (NC_LockedNT g))), (simRi, grule) (List.range g.rules.length).zip g.rules k < grule.output_string.length nc_locked_is_clean g u nc_locked_is_clean g v (have dflt := symbol.nonterminal grule.input_N; s₁ = u ++ [nc_locked_out simRi k (grule.output_string.getD k dflt)] ++ v s₂ = u ++ [nc_locked_liftSym (grule.output_string.getD k dflt)] ++ v) (∀ (ri j : ), nc_locked_mark ri js₁) ∀ (ri j : ) (a : symbol T g.nt), nc_locked_out ri j a s₁ ri = simRi j = k a = grule.output_string.getD k (symbol.nonterminal grule.input_N)

                                                Counted locked derivations #

                                                inductive NC_locked_derives_n {T : Type} (g : grammar T) (hg : grammar_noncontracting g) :
                                                List (symbol T (NC_LockedNT g))List (symbol T (NC_LockedNT g))Prop

                                                Step-counted derivations for the locked construction. This is equivalent to CS_derives, but exposes split points needed by the dirty-phase grouping proof.

                                                Instances For
                                                  theorem nc_locked_derives_n_append {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {n : } {s₁ s₂ s₃ : List (symbol T (NC_LockedNT g))} (h : NC_locked_derives_n g hg n s₁ s₂) (hstep : CS_transforms (locked_csg_of_noncontracting g hg) s₂ s₃) :
                                                  NC_locked_derives_n g hg (n + 1) s₁ s₃
                                                  theorem nc_locked_derives_to_derives_n {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : CS_derives (locked_csg_of_noncontracting g hg) s₁ s₂) :
                                                  ∃ (n : ), NC_locked_derives_n g hg n s₁ s₂
                                                  theorem nc_locked_derives_n_removed_mark_event {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {n : } {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : NC_locked_derives_n g hg n s₁ s₂) {ri k : } (hsrc : nc_locked_mark ri k s₁) (htgt : nc_locked_mark ri ks₂) :
                                                  ∃ (m : ) (rest : ) (smid : List (symbol T (NC_LockedNT g))) (simRi : ) (grule : grule T g.nt) (j : ), n = m + rest NC_locked_derives_n g hg m s₁ smid NC_locked_derives_n g hg rest smid s₂ (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi j < grule.output_string.length nc_locked_out simRi j (grule.output_string.getD j (symbol.nonterminal grule.input_N)) smid
                                                  theorem nc_locked_derives_n_removed_mark_step_event {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {n : } {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : NC_locked_derives_n g hg n s₁ s₂) {ri k : } (hsrc : nc_locked_mark ri k s₁) (htgt : nc_locked_mark ri ks₂) :
                                                  ∃ (pre : ) (rest : ) (spre : List (symbol T (NC_LockedNT g))) (spost : List (symbol T (locked_csg_of_noncontracting g hg).nt)) (simRi : ) (grule : grule T g.nt) (j : ), n = pre + 1 + rest NC_locked_derives_n g hg pre s₁ spre CS_transforms (locked_csg_of_noncontracting g hg) spre spost NC_locked_derives_n g hg rest spost s₂ (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi j < grule.output_string.length nc_locked_mark ri k spre nc_locked_mark ri kspost nc_locked_out simRi j (grule.output_string.getD j (symbol.nonterminal grule.input_N)) spost
                                                  theorem nc_locked_derives_n_removed_out_event {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {n : } {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : NC_locked_derives_n g hg n s₁ s₂) {ri k : } {a : symbol T g.nt} (hsrc : nc_locked_out ri k a s₁) (htgt : nc_locked_out ri k as₂) :
                                                  ∃ (m : ) (rest : ) (smid : List (symbol T (NC_LockedNT g))) (simRi : ) (grule : grule T g.nt), n = m + rest NC_locked_derives_n g hg m s₁ smid NC_locked_derives_n g hg rest smid s₂ (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi k < grule.output_string.length a = grule.output_string.getD k (symbol.nonterminal grule.input_N) nc_locked_liftSym a smid
                                                  theorem nc_locked_derives_n_added_out_event {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {n : } {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : NC_locked_derives_n g hg n s₁ s₂) {ri k : } {a : symbol T g.nt} (hsrc : nc_locked_out ri k as₁) (htgt : nc_locked_out ri k a s₂) :
                                                  ∃ (m : ) (rest : ) (smid : List (symbol T (NC_LockedNT g))) (simRi : ) (grule : grule T g.nt), n = m + rest NC_locked_derives_n g hg m s₁ smid NC_locked_derives_n g hg rest smid s₂ (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi k < grule.output_string.length a = grule.output_string.getD k (symbol.nonterminal grule.input_N) nc_locked_out ri k a smid
                                                  theorem nc_locked_derives_n_added_out_step_event {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {n : } {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : NC_locked_derives_n g hg n s₁ s₂) {ri k : } {a : symbol T g.nt} (hsrc : nc_locked_out ri k as₁) (htgt : nc_locked_out ri k a s₂) :
                                                  ∃ (pre : ) (rest : ) (spre : List (symbol T (NC_LockedNT g))) (spost : List (symbol T (locked_csg_of_noncontracting g hg).nt)) (simRi : ) (grule : grule T g.nt), n = pre + 1 + rest NC_locked_derives_n g hg pre s₁ spre CS_transforms (locked_csg_of_noncontracting g hg) spre spost NC_locked_derives_n g hg rest spost s₂ (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi k < grule.output_string.length a = grule.output_string.getD k (symbol.nonterminal grule.input_N) nc_locked_out ri k aspre nc_locked_out ri k a spost
                                                  theorem nc_locked_derives_n_added_out_step_source_mark_event {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {n : } {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : NC_locked_derives_n g hg n s₁ s₂) {ri k : } {a : symbol T g.nt} (hsrc : nc_locked_out ri k as₁) (htgt : nc_locked_out ri k a s₂) :
                                                  ∃ (pre : ) (rest : ) (spre : List (symbol T (NC_LockedNT g))) (spost : List (symbol T (locked_csg_of_noncontracting g hg).nt)) (simRi : ) (grule : grule T g.nt) (markIdx : ), n = pre + 1 + rest NC_locked_derives_n g hg pre s₁ spre CS_transforms (locked_csg_of_noncontracting g hg) spre spost NC_locked_derives_n g hg rest spost s₂ (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi k < grule.output_string.length a = grule.output_string.getD k (symbol.nonterminal grule.input_N) have pattern := grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R; markIdx < pattern.length (pattern.length - 1 k markIdx = pattern.length - 1 k < pattern.length - 1 markIdx = k) nc_locked_mark simRi markIdx spre
                                                  theorem nc_locked_derives_n_to_clean_mark_event {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {n : } {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : NC_locked_derives_n g hg n s₁ s₂) (hclean₂ : nc_locked_is_clean g s₂) {ri k : } (hsrc : nc_locked_mark ri k s₁) :
                                                  ∃ (m : ) (rest : ) (smid : List (symbol T (NC_LockedNT g))) (simRi : ) (grule : grule T g.nt) (j : ), n = m + rest NC_locked_derives_n g hg m s₁ smid NC_locked_derives_n g hg rest smid s₂ (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi j < grule.output_string.length nc_locked_out simRi j (grule.output_string.getD j (symbol.nonterminal grule.input_N)) smid
                                                  theorem nc_locked_derives_n_to_clean_out_event {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {n : } {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : NC_locked_derives_n g hg n s₁ s₂) (hclean₂ : nc_locked_is_clean g s₂) {ri k : } {a : symbol T g.nt} (hsrc : nc_locked_out ri k a s₁) :
                                                  ∃ (m : ) (rest : ) (smid : List (symbol T (NC_LockedNT g))) (simRi : ) (grule : grule T g.nt), n = m + rest NC_locked_derives_n g hg m s₁ smid NC_locked_derives_n g hg rest smid s₂ (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi k < grule.output_string.length a = grule.output_string.getD k (symbol.nonterminal grule.input_N) nc_locked_liftSym a smid
                                                  inductive NC_locked_dirty_derives_n {T : Type} (g : grammar T) (hg : grammar_noncontracting g) :
                                                  List (symbol T (NC_LockedNT g))List (symbol T (NC_LockedNT g))Prop

                                                  Counted locked derivations whose every boundary state is dirty.

                                                  Instances For
                                                    theorem nc_locked_dirty_derives_n_to_derives_n {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {n : } {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : NC_locked_dirty_derives_n g hg n s₁ s₂) :
                                                    NC_locked_derives_n g hg n s₁ s₂
                                                    theorem nc_locked_dirty_derives_n_end_dirty {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {n : } {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : NC_locked_dirty_derives_n g hg n s₁ s₂) :
                                                    theorem nc_locked_dirty_return_mark_event {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {m : } {s_after s_dirty s_clean : List (symbol T (NC_LockedNT g))} (hdirty : NC_locked_dirty_derives_n g hg m s_after s_dirty) (hreturn : CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean) (hclean : nc_locked_is_clean g s_clean) {ri k : } (hmark : nc_locked_mark ri k s_after) :
                                                    ∃ (pre : ) (rest : ) (smid : List (symbol T (NC_LockedNT g))) (simRi : ) (grule : grule T g.nt) (j : ), m + 1 = pre + rest NC_locked_derives_n g hg pre s_after smid NC_locked_derives_n g hg rest smid s_clean (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi j < grule.output_string.length nc_locked_out simRi j (grule.output_string.getD j (symbol.nonterminal grule.input_N)) smid
                                                    theorem nc_locked_dirty_return_mark_step_event {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {m : } {s_after s_dirty s_clean : List (symbol T (NC_LockedNT g))} (hdirty : NC_locked_dirty_derives_n g hg m s_after s_dirty) (hreturn : CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean) (hclean : nc_locked_is_clean g s_clean) {ri k : } (hmark : nc_locked_mark ri k s_after) :
                                                    ∃ (pre : ) (rest : ) (spre : List (symbol T (NC_LockedNT g))) (spost : List (symbol T (locked_csg_of_noncontracting g hg).nt)) (simRi : ) (grule : grule T g.nt) (j : ), m + 1 = pre + 1 + rest NC_locked_derives_n g hg pre s_after spre CS_transforms (locked_csg_of_noncontracting g hg) spre spost NC_locked_derives_n g hg rest spost s_clean (simRi, grule) (List.range g.rules.length).zip g.rules ri = simRi j < grule.output_string.length nc_locked_mark ri k spre nc_locked_mark ri kspost nc_locked_out simRi j (grule.output_string.getD j (symbol.nonterminal grule.input_N)) spost
                                                    theorem nc_locked_dirty_interval_final_cleanup_added_out_event {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {m : } {s_start s_after s_dirty s_clean : List (symbol T (NC_LockedNT g))} (hstart : CS_transforms (locked_csg_of_noncontracting g hg) s_start s_after) (hclean_start : nc_locked_is_clean g s_start) (hdirty_after : ¬nc_locked_is_clean g s_after) (hmid : NC_locked_dirty_derives_n g hg m s_after s_dirty) (hdirty : ¬nc_locked_is_clean g s_dirty) (hreturn : CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean) (hclean : nc_locked_is_clean g s_clean) :
                                                    ∃ (ri : ) (r : grule T g.nt) (k : ) (u : List (symbol T (NC_LockedNT g))) (v : List (symbol T (NC_LockedNT g))) (pre : ) (rest : ) (smid : List (symbol T (NC_LockedNT g))), (ri, r) (List.range g.rules.length).zip g.rules k < r.output_string.length (have dflt := symbol.nonterminal r.input_N; s_dirty = u ++ [nc_locked_out ri k (r.output_string.getD k dflt)] ++ v s_clean = u ++ [nc_locked_liftSym (r.output_string.getD k dflt)] ++ v) m = pre + rest NC_locked_derives_n g hg pre s_after smid NC_locked_derives_n g hg rest smid s_dirty nc_locked_out ri k (r.output_string.getD k (symbol.nonterminal r.input_N)) smid

                                                    In a dirty interval that starts from a clean form, the unique output marker cleaned by the final dirty-to-clean step must have been introduced during the dirty part of the interval.

                                                    theorem nc_locked_dirty_interval_final_cleanup_added_out_step_event {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {m : } {s_start s_after s_dirty s_clean : List (symbol T (NC_LockedNT g))} (hstart : CS_transforms (locked_csg_of_noncontracting g hg) s_start s_after) (hclean_start : nc_locked_is_clean g s_start) (hdirty_after : ¬nc_locked_is_clean g s_after) (hmid : NC_locked_dirty_derives_n g hg m s_after s_dirty) (hdirty : ¬nc_locked_is_clean g s_dirty) (hreturn : CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean) (hclean : nc_locked_is_clean g s_clean) :
                                                    ∃ (ri : ) (r : grule T g.nt) (k : ) (u : List (symbol T (NC_LockedNT g))) (v : List (symbol T (NC_LockedNT g))) (pre : ) (rest : ) (spre : List (symbol T (NC_LockedNT g))) (spost : List (symbol T (locked_csg_of_noncontracting g hg).nt)), (ri, r) (List.range g.rules.length).zip g.rules k < r.output_string.length (have dflt := symbol.nonterminal r.input_N; s_dirty = u ++ [nc_locked_out ri k (r.output_string.getD k dflt)] ++ v s_clean = u ++ [nc_locked_liftSym (r.output_string.getD k dflt)] ++ v) m = pre + 1 + rest NC_locked_derives_n g hg pre s_after spre CS_transforms (locked_csg_of_noncontracting g hg) spre spost NC_locked_derives_n g hg rest spost s_dirty nc_locked_out ri k (r.output_string.getD k (symbol.nonterminal r.input_N))spre nc_locked_out ri k (r.output_string.getD k (symbol.nonterminal r.input_N)) spost

                                                    A step-split form of nc_locked_dirty_interval_final_cleanup_added_out_event: the output marker cleaned by the final return-to-clean step has a concrete introduction step inside the dirty interval.

                                                    theorem nc_locked_dirty_interval_mid_length_pos {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {m : } {s_start s_after s_dirty s_clean : List (symbol T (NC_LockedNT g))} (hstart : CS_transforms (locked_csg_of_noncontracting g hg) s_start s_after) (hclean_start : nc_locked_is_clean g s_start) (hdirty_after : ¬nc_locked_is_clean g s_after) (hmid : NC_locked_dirty_derives_n g hg m s_after s_dirty) (hdirty : ¬nc_locked_is_clean g s_dirty) (hreturn : CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean) (hclean : nc_locked_is_clean g s_clean) :
                                                    0 < m

                                                    A dirty interval cannot return to a clean form immediately after its clean-to-dirty start. The start state contains a single input marker and no output marker, while a dirty-to-clean step must clean a unique output marker.

                                                    theorem nc_locked_dirty_derives_n_step_split_of_pos {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {m : } {s₁ s₂ : List (symbol T (NC_LockedNT g))} (hpos : 0 < m) (h : NC_locked_dirty_derives_n g hg m s₁ s₂) :
                                                    ∃ (m' : ) (smid : List (symbol T (locked_csg_of_noncontracting g hg).nt)), m = m' + 1 CS_transforms (locked_csg_of_noncontracting g hg) s₁ smid ¬nc_locked_is_clean g smid NC_locked_dirty_derives_n g hg m' smid s₂
                                                    theorem nc_locked_dirty_interval_first_dirty_step {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {m : } {s_start s_after s_dirty s_clean : List (symbol T (NC_LockedNT g))} (hstart : CS_transforms (locked_csg_of_noncontracting g hg) s_start s_after) (hclean_start : nc_locked_is_clean g s_start) (hdirty_after : ¬nc_locked_is_clean g s_after) (hmid : NC_locked_dirty_derives_n g hg m s_after s_dirty) (hdirty : ¬nc_locked_is_clean g s_dirty) (hreturn : CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean) (hclean : nc_locked_is_clean g s_clean) :
                                                    ∃ (m' : ) (smid : List (symbol T (locked_csg_of_noncontracting g hg).nt)), m = m' + 1 CS_transforms (locked_csg_of_noncontracting g hg) s_after smid ¬nc_locked_is_clean g smid NC_locked_dirty_derives_n g hg m' smid s_dirty

                                                    Nondegenerate dirty intervals expose their first dirty-to-dirty step.

                                                    theorem nc_locked_dirty_interval_first_step_removed_start_mark_summary {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {m : } {s_start s_after s_dirty s_clean : List (symbol T (NC_LockedNT g))} (hstart : CS_transforms (locked_csg_of_noncontracting g hg) s_start s_after) (hclean_start : nc_locked_is_clean g s_start) (hdirty_after : ¬nc_locked_is_clean g s_after) (hmid : NC_locked_dirty_derives_n g hg m s_after s_dirty) (hdirty : ¬nc_locked_is_clean g s_dirty) (hreturn : CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean) (hclean : nc_locked_is_clean g s_clean) :
                                                    ∃ (ri : ) (r : grule T g.nt) (u : List (symbol T (NC_LockedNT g))) (v : List (symbol T (NC_LockedNT g))) (m' : ) (smid : List (symbol T (locked_csg_of_noncontracting g hg).nt)), (ri, r) (List.range g.rules.length).zip g.rules (have pattern := r.input_L ++ [symbol.nonterminal r.input_N] ++ r.input_R; have dflt := symbol.nonterminal r.input_N; s_start = u ++ [nc_locked_liftSym (pattern.getD 0 dflt)] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v s_after = u ++ [nc_locked_mark ri 0] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v) m = m' + 1 CS_transforms (locked_csg_of_noncontracting g hg) s_after smid ¬nc_locked_is_clean g smid NC_locked_dirty_derives_n g hg m' smid s_dirty (nc_locked_mark ri 0smid(r.input_L ++ [symbol.nonterminal r.input_N] ++ r.input_R).length = 1 (∀ (targetRi targetK : ), nc_locked_mark targetRi targetKsmid) j < r.output_string.length, nc_locked_out ri j (r.output_string.getD j (symbol.nonterminal r.input_N)) smid)

                                                    Packaged consumed-boundary branch for the first dirty-to-dirty step: if the marker opened by the clean-to-dirty boundary disappears, then the simulated input pattern had length one, the next state has no input markers, and the same step produced an output marker for that simulation.

                                                    theorem nc_locked_dirty_interval_first_step_removed_start_mark_endpoint {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {m : } {s_start s_after s_dirty s_clean : List (symbol T (NC_LockedNT g))} (hstart : CS_transforms (locked_csg_of_noncontracting g hg) s_start s_after) (hclean_start : nc_locked_is_clean g s_start) (hdirty_after : ¬nc_locked_is_clean g s_after) (hmid : NC_locked_dirty_derives_n g hg m s_after s_dirty) (hdirty : ¬nc_locked_is_clean g s_dirty) (hreturn : CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean) (hclean : nc_locked_is_clean g s_clean) :
                                                    ∃ (ri : ) (r : grule T g.nt) (u : List (symbol T (NC_LockedNT g))) (v : List (symbol T (NC_LockedNT g))) (m' : ) (smid : List (symbol T (locked_csg_of_noncontracting g hg).nt)), (ri, r) (List.range g.rules.length).zip g.rules (have pattern := r.input_L ++ [symbol.nonterminal r.input_N] ++ r.input_R; have dflt := symbol.nonterminal r.input_N; s_start = u ++ [nc_locked_liftSym (pattern.getD 0 dflt)] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v s_after = u ++ [nc_locked_mark ri 0] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v) m = m' + 1 CS_transforms (locked_csg_of_noncontracting g hg) s_after smid ¬nc_locked_is_clean g smid NC_locked_dirty_derives_n g hg m' smid s_dirty (nc_locked_mark ri 0smidsmid = u ++ nc_locked_outputFrom ri r.output_string (symbol.nonterminal r.input_N) 0 ++ v)

                                                    In the consumed-boundary branch, the first dirty-to-dirty step has exactly the clean macro target for the opened original rule.

                                                    theorem nc_locked_dirty_trace_first_clean_step_split {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {n : } {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : NC_locked_derives_n g hg n s₁ s₂) (hdirty₁ : ¬nc_locked_is_clean g s₁) (hclean₂ : nc_locked_is_clean g s₂) :
                                                    ∃ (m : ) (rest : ) (s_dirty : List (symbol T (NC_LockedNT g))) (s_clean : List (symbol T (locked_csg_of_noncontracting g hg).nt)), n = m + 1 + rest NC_locked_derives_n g hg m s₁ s_dirty ¬nc_locked_is_clean g s_dirty CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean nc_locked_is_clean g s_clean NC_locked_derives_n g hg rest s_clean s₂
                                                    theorem nc_locked_dirty_trace_first_clean_step_dirty_split {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {n : } {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : NC_locked_derives_n g hg n s₁ s₂) (hdirty₁ : ¬nc_locked_is_clean g s₁) (hclean₂ : nc_locked_is_clean g s₂) :
                                                    ∃ (m : ) (rest : ) (s_dirty : List (symbol T (NC_LockedNT g))) (s_clean : List (symbol T (locked_csg_of_noncontracting g hg).nt)), n = m + 1 + rest NC_locked_dirty_derives_n g hg m s₁ s_dirty CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean nc_locked_is_clean g s_clean NC_locked_derives_n g hg rest s_clean s₂

                                                    Locked clean reverse traces #

                                                    Clean macro steps in the locked construction. The sim constructor is the macro endpoint for one complete locked simulation of an original non-contracting rule under arbitrary surrounding context.

                                                    Instances For

                                                      Every locked clean macro step projects to an unrestricted derivation in the original grammar.

                                                      Step-counted traces of locked clean macro steps.

                                                      Instances For

                                                        Locked clean macro traces project to unrestricted derivations in the original grammar.

                                                        theorem nc_locked_clean_macro_derives_n_trans {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {m n : } {s₁ s₂ s₃ : List (symbol T (NC_LockedNT g))} (h₁ : NC_locked_clean_macro_derives_n g hg m s₁ s₂) (h₂ : NC_locked_clean_macro_derives_n g hg n s₂ s₃) :
                                                        NC_locked_clean_macro_derives_n g hg (m + n) s₁ s₃
                                                        inductive NC_locked_clean_derives_n {T : Type} (g : grammar T) (hg : grammar_noncontracting g) :
                                                        List (symbol T (NC_LockedNT g))List (symbol T (NC_LockedNT g))Prop

                                                        A finite locked CS derivation trace whose adjacent endpoints are all clean.

                                                        Instances For
                                                          theorem nc_locked_clean_trace_or_first_dirty_segment {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {n : } {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : NC_locked_derives_n g hg n s₁ s₂) (hclean₁ : nc_locked_is_clean g s₁) (hclean₂ : nc_locked_is_clean g s₂) :
                                                          NC_locked_clean_derives_n g hg n s₁ s₂ ∃ (pre : ) (m : ) (rest : ) (s_start : List (symbol T (NC_LockedNT g))) (s_after : List (symbol T (NC_LockedNT g))) (s_dirty : List (symbol T (NC_LockedNT g))) (s_clean : List (symbol T (NC_LockedNT g))), n = pre + 1 + m + 1 + rest NC_locked_clean_derives_n g hg pre s₁ s_start nc_locked_is_clean g s_start CS_transforms (locked_csg_of_noncontracting g hg) s_start s_after ¬nc_locked_is_clean g s_after NC_locked_derives_n g hg m s_after s_dirty ¬nc_locked_is_clean g s_dirty CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean nc_locked_is_clean g s_clean NC_locked_derives_n g hg rest s_clean s₂
                                                          theorem nc_locked_clean_trace_or_first_dirty_segment_dirty {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {n : } {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : NC_locked_derives_n g hg n s₁ s₂) (hclean₁ : nc_locked_is_clean g s₁) (hclean₂ : nc_locked_is_clean g s₂) :
                                                          NC_locked_clean_derives_n g hg n s₁ s₂ ∃ (pre : ) (m : ) (rest : ) (s_start : List (symbol T (NC_LockedNT g))) (s_after : List (symbol T (NC_LockedNT g))) (s_dirty : List (symbol T (NC_LockedNT g))) (s_clean : List (symbol T (NC_LockedNT g))), n = pre + 1 + m + 1 + rest NC_locked_clean_derives_n g hg pre s₁ s_start nc_locked_is_clean g s_start CS_transforms (locked_csg_of_noncontracting g hg) s_start s_after ¬nc_locked_is_clean g s_after NC_locked_dirty_derives_n g hg m s_after s_dirty ¬nc_locked_is_clean g s_dirty CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean nc_locked_is_clean g s_clean NC_locked_derives_n g hg rest s_clean s₂
                                                          theorem nc_locked_clean_trace_to_macro_trace {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {n : } {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : NC_locked_clean_derives_n g hg n s₁ s₂) :

                                                          Ordinary locked clean traces are a special case of locked clean macro traces.

                                                          The remaining local grouping property for the locked construction: any dirty interval bracketed by one clean-to-dirty step and one dirty-to-clean step compresses to some clean macro trace.

                                                          Equations
                                                          • One or more equations did not get rendered due to their size.
                                                          Instances For
                                                            theorem nc_locked_clean_endpoints_to_macro_trace_of_dirty_interval_macro {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {n : } {s₁ s₂ : List (symbol T (NC_LockedNT g))} (h : NC_locked_derives_n g hg n s₁ s₂) (hclean₁ : nc_locked_is_clean g s₁) (hclean₂ : nc_locked_is_clean g s₂) (hgroup : NC_locked_dirty_interval_macro_property g hg) :
                                                            ∃ (k : ), NC_locked_clean_macro_derives_n g hg k s₁ s₂

                                                            Abstract compression principle for locked traces. Once every dirty interval between clean endpoints can be replaced by a clean macro trace, every clean-to-clean locked derivation can be compressed to a clean macro trace.

                                                            Reverse language inclusion for the locked construction, assuming the local dirty-interval grouping property.

                                                            Language equality for the locked construction, reduced to the local dirty-interval grouping property.

                                                            theorem nc_locked_boundary_macro_step {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {ri : } {r : grule T g.nt} {u v s₁ s₂ : List (symbol T (NC_LockedNT g))} (hpair : (ri, r) (List.range g.rules.length).zip g.rules) (hs₁ : have pattern := r.input_L ++ [symbol.nonterminal r.input_N] ++ r.input_R; have dflt := symbol.nonterminal r.input_N; s₁ = u ++ [nc_locked_liftSym (pattern.getD 0 dflt)] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v) (hs₂ : s₂ = u ++ List.map nc_locked_liftSym r.output_string ++ v) :
                                                            theorem nc_locked_dirty_interval_consumed_boundary_macro_target {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {m : } {s_start s_after s_dirty s_clean : List (symbol T (NC_LockedNT g))} (hstart : CS_transforms (locked_csg_of_noncontracting g hg) s_start s_after) (hclean_start : nc_locked_is_clean g s_start) (hdirty_after : ¬nc_locked_is_clean g s_after) (hmid : NC_locked_dirty_derives_n g hg m s_after s_dirty) (hdirty : ¬nc_locked_is_clean g s_dirty) (hreturn : CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean) (hclean : nc_locked_is_clean g s_clean) :

                                                            The consumed-boundary first-step case has the expected macro endpoint: the dirty state produced by consuming the boundary marker is the locked output block, that block cleans to the macro target, and the original clean boundary step already determines the corresponding clean macro simulation.

                                                            theorem nc_locked_dirty_interval_consumed_boundary_macro_prefix {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {m : } {s_start s_after s_dirty s_clean : List (symbol T (NC_LockedNT g))} (hstart : CS_transforms (locked_csg_of_noncontracting g hg) s_start s_after) (hclean_start : nc_locked_is_clean g s_start) (hdirty_after : ¬nc_locked_is_clean g s_after) (hmid : NC_locked_dirty_derives_n g hg m s_after s_dirty) (hdirty : ¬nc_locked_is_clean g s_dirty) (hreturn : CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean) (hclean : nc_locked_is_clean g s_clean) :
                                                            ∃ (ri : ) (r : grule T g.nt) (u : List (symbol T (NC_LockedNT g))) (v : List (symbol T (NC_LockedNT g))) (m' : ) (smid : List (symbol T (locked_csg_of_noncontracting g hg).nt)), (ri, r) (List.range g.rules.length).zip g.rules (have pattern := r.input_L ++ [symbol.nonterminal r.input_N] ++ r.input_R; have dflt := symbol.nonterminal r.input_N; s_start = u ++ [nc_locked_liftSym (pattern.getD 0 dflt)] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v s_after = u ++ [nc_locked_mark ri 0] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v) m = m' + 1 CS_transforms (locked_csg_of_noncontracting g hg) s_after smid ¬nc_locked_is_clean g smid NC_locked_dirty_derives_n g hg m' smid s_dirty (nc_locked_mark ri 0smidhave target := u ++ List.map nc_locked_liftSym r.output_string ++ v; CS_derives (locked_csg_of_noncontracting g hg) smid target nc_locked_is_clean g target NC_locked_clean_macro_derives_n g hg 1 s_start target)

                                                            Counted clean-macro pref for the consumed-boundary branch. This is the canonical first macro segment that will later be concatenated with whatever clean behavior remains after all dirty markers have disappeared.

                                                            theorem nc_locked_dirty_interval_first_step_macro_prefix_or_mark_retained {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {m : } {s_start s_after s_dirty s_clean : List (symbol T (NC_LockedNT g))} (hstart : CS_transforms (locked_csg_of_noncontracting g hg) s_start s_after) (hclean_start : nc_locked_is_clean g s_start) (hdirty_after : ¬nc_locked_is_clean g s_after) (hmid : NC_locked_dirty_derives_n g hg m s_after s_dirty) (hdirty : ¬nc_locked_is_clean g s_dirty) (hreturn : CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean) (hclean : nc_locked_is_clean g s_clean) :
                                                            ∃ (ri : ) (r : grule T g.nt) (u : List (symbol T (NC_LockedNT g))) (v : List (symbol T (NC_LockedNT g))) (m' : ) (smid : List (symbol T (locked_csg_of_noncontracting g hg).nt)), (ri, r) (List.range g.rules.length).zip g.rules (have pattern := r.input_L ++ [symbol.nonterminal r.input_N] ++ r.input_R; have dflt := symbol.nonterminal r.input_N; s_start = u ++ [nc_locked_liftSym (pattern.getD 0 dflt)] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v s_after = u ++ [nc_locked_mark ri 0] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v) m = m' + 1 CS_transforms (locked_csg_of_noncontracting g hg) s_after smid ¬nc_locked_is_clean g smid NC_locked_dirty_derives_n g hg m' smid s_dirty (nc_locked_mark ri 0 smid have target := u ++ List.map nc_locked_liftSym r.output_string ++ v; CS_derives (locked_csg_of_noncontracting g hg) smid target nc_locked_is_clean g target NC_locked_clean_macro_derives_n g hg 1 s_start target)

                                                            First-step dichotomy for dirty intervals, in a form suitable for the final grouping induction. After the first dirty-to-dirty step, either the marker opened by the clean-to-dirty boundary is still present, or that first step has already completed the boundary simulation and yields a canonical one-step clean macro pref.

                                                            theorem nc_locked_dirty_interval_first_step_event_or_macro_prefix {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {m : } {s_start s_after s_dirty s_clean : List (symbol T (NC_LockedNT g))} (hstart : CS_transforms (locked_csg_of_noncontracting g hg) s_start s_after) (hclean_start : nc_locked_is_clean g s_start) (hdirty_after : ¬nc_locked_is_clean g s_after) (hmid : NC_locked_dirty_derives_n g hg m s_after s_dirty) (hdirty : ¬nc_locked_is_clean g s_dirty) (hreturn : CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean) (hclean : nc_locked_is_clean g s_clean) :
                                                            ∃ (ri : ) (r : grule T g.nt) (u : List (symbol T (NC_LockedNT g))) (v : List (symbol T (NC_LockedNT g))) (m' : ) (smid : List (symbol T (locked_csg_of_noncontracting g hg).nt)), (ri, r) (List.range g.rules.length).zip g.rules (have pattern := r.input_L ++ [symbol.nonterminal r.input_N] ++ r.input_R; have dflt := symbol.nonterminal r.input_N; s_start = u ++ [nc_locked_liftSym (pattern.getD 0 dflt)] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v s_after = u ++ [nc_locked_mark ri 0] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v) m = m' + 1 CS_transforms (locked_csg_of_noncontracting g hg) s_after smid ¬nc_locked_is_clean g smid NC_locked_dirty_derives_n g hg m' smid s_dirty ((nc_locked_mark ri 0 smid ∃ (pre : ) (rest : ) (sevent : List (symbol T (NC_LockedNT g))) (j : ), m' + 1 = pre + rest NC_locked_derives_n g hg pre smid sevent NC_locked_derives_n g hg rest sevent s_clean j < r.output_string.length nc_locked_out ri j (r.output_string.getD j (symbol.nonterminal r.input_N)) sevent) have target := u ++ List.map nc_locked_liftSym r.output_string ++ v; CS_derives (locked_csg_of_noncontracting g hg) smid target nc_locked_is_clean g target NC_locked_clean_macro_derives_n g hg 1 s_start target)

                                                            First-step dichotomy with the retained branch expanded to its eventual output event. If the marker opened by the clean-to-dirty boundary survives the first dirty step, then the remaining dirty interval must later emit an output marker for the same original rule before it can return to a clean form.

                                                            theorem nc_locked_dirty_interval_first_step_emit_step_or_macro_prefix {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {m : } {s_start s_after s_dirty s_clean : List (symbol T (NC_LockedNT g))} (hstart : CS_transforms (locked_csg_of_noncontracting g hg) s_start s_after) (hclean_start : nc_locked_is_clean g s_start) (hdirty_after : ¬nc_locked_is_clean g s_after) (hmid : NC_locked_dirty_derives_n g hg m s_after s_dirty) (hdirty : ¬nc_locked_is_clean g s_dirty) (hreturn : CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean) (hclean : nc_locked_is_clean g s_clean) :
                                                            ∃ (ri : ) (r : grule T g.nt) (u : List (symbol T (NC_LockedNT g))) (v : List (symbol T (NC_LockedNT g))) (m' : ) (smid : List (symbol T (locked_csg_of_noncontracting g hg).nt)), (ri, r) (List.range g.rules.length).zip g.rules (have pattern := r.input_L ++ [symbol.nonterminal r.input_N] ++ r.input_R; have dflt := symbol.nonterminal r.input_N; s_start = u ++ [nc_locked_liftSym (pattern.getD 0 dflt)] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v s_after = u ++ [nc_locked_mark ri 0] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v) m = m' + 1 CS_transforms (locked_csg_of_noncontracting g hg) s_after smid ¬nc_locked_is_clean g smid NC_locked_dirty_derives_n g hg m' smid s_dirty ((nc_locked_mark ri 0 smid ∃ (pre : ) (rest : ) (spre : List (symbol T (NC_LockedNT g))) (spost : List (symbol T (locked_csg_of_noncontracting g hg).nt)) (j : ), m' + 1 = pre + 1 + rest NC_locked_derives_n g hg pre smid spre CS_transforms (locked_csg_of_noncontracting g hg) spre spost NC_locked_derives_n g hg rest spost s_clean j < r.output_string.length nc_locked_mark ri 0 spre nc_locked_mark ri 0spost nc_locked_out ri j (r.output_string.getD j (symbol.nonterminal r.input_N)) spost) have target := u ++ List.map nc_locked_liftSym r.output_string ++ v; CS_derives (locked_csg_of_noncontracting g hg) smid target nc_locked_is_clean g target NC_locked_clean_macro_derives_n g hg 1 s_start target)

                                                            Step-split version of nc_locked_dirty_interval_first_step_event_or_macro_prefix. In the retained branch this records the exact later transform that removes the start marker and emits an output marker for the same original rule.

                                                            theorem nc_locked_removed_zero_mark_step_shape {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {ri : } {r : grule T g.nt} {s₁ s₂ : List (symbol T (NC_LockedNT g))} (hpair : (ri, r) (List.range g.rules.length).zip g.rules) (h : CS_transforms (locked_csg_of_noncontracting g hg) s₁ s₂) (hsrc : nc_locked_mark ri 0 s₁) (htgt : nc_locked_mark ri 0s₂) :
                                                            have pattern := r.input_L ++ [symbol.nonterminal r.input_N] ++ r.input_R; have dflt := symbol.nonterminal r.input_N; (pattern.length = 1 ∃ (u : List (symbol T (NC_LockedNT g))) (v : List (symbol T (NC_LockedNT g))), s₁ = u ++ [nc_locked_mark ri 0] ++ v s₂ = u ++ nc_locked_outputFrom ri r.output_string dflt 0 ++ v) 1 < pattern.length ∃ (u : List (symbol T (NC_LockedNT g))) (v : List (symbol T (NC_LockedNT g))), s₁ = u ++ [nc_locked_mark ri 0] ++ nc_locked_outputSuffix ri r.output_string dflt 1 ++ v s₂ = u ++ [nc_locked_out ri 0 (r.output_string.getD 0 dflt)] ++ nc_locked_outputSuffix ri r.output_string dflt 1 ++ v

                                                            If a step removes the phase-0 marker for a fixed original rule, then it is one of exactly two emit steps. For a unit input pattern it is the emitLast rule and exposes the whole marked output block; otherwise it is the emitRest rule at index 0 and requires the already-emitted output suffix as right context.

                                                            theorem nc_locked_dirty_interval_first_step_emit_shape_or_macro_prefix {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {m : } {s_start s_after s_dirty s_clean : List (symbol T (NC_LockedNT g))} (hstart : CS_transforms (locked_csg_of_noncontracting g hg) s_start s_after) (hclean_start : nc_locked_is_clean g s_start) (hdirty_after : ¬nc_locked_is_clean g s_after) (hmid : NC_locked_dirty_derives_n g hg m s_after s_dirty) (hdirty : ¬nc_locked_is_clean g s_dirty) (hreturn : CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean) (hclean : nc_locked_is_clean g s_clean) :
                                                            ∃ (ri : ) (r : grule T g.nt) (u : List (symbol T (NC_LockedNT g))) (v : List (symbol T (NC_LockedNT g))) (m' : ) (smid : List (symbol T (locked_csg_of_noncontracting g hg).nt)), (ri, r) (List.range g.rules.length).zip g.rules (have pattern := r.input_L ++ [symbol.nonterminal r.input_N] ++ r.input_R; have dflt := symbol.nonterminal r.input_N; s_start = u ++ [nc_locked_liftSym (pattern.getD 0 dflt)] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v s_after = u ++ [nc_locked_mark ri 0] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v) m = m' + 1 CS_transforms (locked_csg_of_noncontracting g hg) s_after smid ¬nc_locked_is_clean g smid NC_locked_dirty_derives_n g hg m' smid s_dirty ((nc_locked_mark ri 0 smid ∃ (pre : ) (rest : ) (spre : List (symbol T (NC_LockedNT g))) (spost : List (symbol T (locked_csg_of_noncontracting g hg).nt)) (j : ), m' + 1 = pre + 1 + rest NC_locked_derives_n g hg pre smid spre CS_transforms (locked_csg_of_noncontracting g hg) spre spost NC_locked_derives_n g hg rest spost s_clean j < r.output_string.length nc_locked_mark ri 0 spre nc_locked_mark ri 0spost nc_locked_out ri j (r.output_string.getD j (symbol.nonterminal r.input_N)) spost have pattern := r.input_L ++ [symbol.nonterminal r.input_N] ++ r.input_R; have dflt := symbol.nonterminal r.input_N; (pattern.length = 1 ∃ (eu : List (symbol T (NC_LockedNT g))) (ev : List (symbol T (NC_LockedNT g))), spre = eu ++ [nc_locked_mark ri 0] ++ ev spost = eu ++ nc_locked_outputFrom ri r.output_string dflt 0 ++ ev) 1 < pattern.length ∃ (eu : List (symbol T (NC_LockedNT g))) (ev : List (symbol T (NC_LockedNT g))), spre = eu ++ [nc_locked_mark ri 0] ++ nc_locked_outputSuffix ri r.output_string dflt 1 ++ ev spost = eu ++ [nc_locked_out ri 0 (r.output_string.getD 0 dflt)] ++ nc_locked_outputSuffix ri r.output_string dflt 1 ++ ev) have target := u ++ List.map nc_locked_liftSym r.output_string ++ v; CS_derives (locked_csg_of_noncontracting g hg) smid target nc_locked_is_clean g target NC_locked_clean_macro_derives_n g hg 1 s_start target)

                                                            First-step dichotomy with the retained branch expanded to the local shape of the later emit step. This is the form needed by the eventual grouping argument: the branch where the boundary marker survives the first dirty step now carries the exact source and target decomposition of the step that finally removes that marker.

                                                            theorem nc_locked_dirty_interval_first_step_emit_shape_or_macro_prefix_with_added_mark_shape {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {m : } {s_start s_after s_dirty s_clean : List (symbol T (NC_LockedNT g))} (hstart : CS_transforms (locked_csg_of_noncontracting g hg) s_start s_after) (hclean_start : nc_locked_is_clean g s_start) (hdirty_after : ¬nc_locked_is_clean g s_after) (hmid : NC_locked_dirty_derives_n g hg m s_after s_dirty) (hdirty : ¬nc_locked_is_clean g s_dirty) (hreturn : CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean) (hclean : nc_locked_is_clean g s_clean) :
                                                            ∃ (ri : ) (r : grule T g.nt) (u : List (symbol T (NC_LockedNT g))) (v : List (symbol T (NC_LockedNT g))) (m' : ) (smid : List (symbol T (locked_csg_of_noncontracting g hg).nt)), (ri, r) (List.range g.rules.length).zip g.rules (have pattern := r.input_L ++ [symbol.nonterminal r.input_N] ++ r.input_R; have dflt := symbol.nonterminal r.input_N; s_start = u ++ [nc_locked_liftSym (pattern.getD 0 dflt)] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v s_after = u ++ [nc_locked_mark ri 0] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v) m = m' + 1 CS_transforms (locked_csg_of_noncontracting g hg) s_after smid ¬nc_locked_is_clean g smid NC_locked_dirty_derives_n g hg m' smid s_dirty (∀ (targetRi targetK : ), nc_locked_mark targetRi targetK smidnc_locked_mark targetRi targetKs_after∃ (simRi : ) (grule : grule T g.nt), (simRi, grule) (List.range g.rules.length).zip g.rules targetRi = simRi have pattern := grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R; targetK < pattern.length (targetK = 0 simRi = ri targetK = 1)) ((nc_locked_mark ri 0 smid ∃ (pre : ) (rest : ) (spre : List (symbol T (NC_LockedNT g))) (spost : List (symbol T (locked_csg_of_noncontracting g hg).nt)) (j : ), m' + 1 = pre + 1 + rest NC_locked_derives_n g hg pre smid spre CS_transforms (locked_csg_of_noncontracting g hg) spre spost NC_locked_derives_n g hg rest spost s_clean j < r.output_string.length nc_locked_mark ri 0 spre nc_locked_mark ri 0spost nc_locked_out ri j (r.output_string.getD j (symbol.nonterminal r.input_N)) spost have pattern := r.input_L ++ [symbol.nonterminal r.input_N] ++ r.input_R; have dflt := symbol.nonterminal r.input_N; (pattern.length = 1 ∃ (eu : List (symbol T (NC_LockedNT g))) (ev : List (symbol T (NC_LockedNT g))), spre = eu ++ [nc_locked_mark ri 0] ++ ev spost = eu ++ nc_locked_outputFrom ri r.output_string dflt 0 ++ ev) 1 < pattern.length ∃ (eu : List (symbol T (NC_LockedNT g))) (ev : List (symbol T (NC_LockedNT g))), spre = eu ++ [nc_locked_mark ri 0] ++ nc_locked_outputSuffix ri r.output_string dflt 1 ++ ev spost = eu ++ [nc_locked_out ri 0 (r.output_string.getD 0 dflt)] ++ nc_locked_outputSuffix ri r.output_string dflt 1 ++ ev) have target := u ++ List.map nc_locked_liftSym r.output_string ++ v; CS_derives (locked_csg_of_noncontracting g hg) smid target nc_locked_is_clean g target NC_locked_clean_macro_derives_n g hg 1 s_start target)

                                                            First-step dichotomy plus the marker-introduction invariant for that same first dirty step. In the retained branch this keeps the later emit-step shape, while also recording that the first dirty step can only introduce a fresh phase-0 marker or the phase-1 marker for the boundary simulation.

                                                            theorem nc_locked_dirty_interval_first_step_base_one_mark_shape {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {m : } {s_start s_after s_dirty s_clean : List (symbol T (NC_LockedNT g))} (hstart : CS_transforms (locked_csg_of_noncontracting g hg) s_start s_after) (hclean_start : nc_locked_is_clean g s_start) (hdirty_after : ¬nc_locked_is_clean g s_after) (hmid : NC_locked_dirty_derives_n g hg m s_after s_dirty) (hdirty : ¬nc_locked_is_clean g s_dirty) (hreturn : CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean) (hclean : nc_locked_is_clean g s_clean) :
                                                            ∃ (ri : ) (r : grule T g.nt) (u : List (symbol T (NC_LockedNT g))) (v : List (symbol T (NC_LockedNT g))) (m' : ) (smid : List (symbol T (locked_csg_of_noncontracting g hg).nt)), (ri, r) (List.range g.rules.length).zip g.rules (have pattern := r.input_L ++ [symbol.nonterminal r.input_N] ++ r.input_R; have dflt := symbol.nonterminal r.input_N; s_start = u ++ [nc_locked_liftSym (pattern.getD 0 dflt)] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v s_after = u ++ [nc_locked_mark ri 0] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v) m = m' + 1 CS_transforms (locked_csg_of_noncontracting g hg) s_after smid ¬nc_locked_is_clean g smid NC_locked_dirty_derives_n g hg m' smid s_dirty (nc_locked_mark ri 1 smidhave pattern := r.input_L ++ [symbol.nonterminal r.input_N] ++ r.input_R; have dflt := symbol.nonterminal r.input_N; 1 < pattern.length cr(locked_csg_of_noncontracting g hg).rules, cr.context_left = [nc_locked_mark ri 0] cr.input_nonterminal = nc_locked_symToNT (pattern.getD 1 dflt) cr.context_right = List.map nc_locked_liftSym (List.drop 2 pattern) cr.output_string = [nc_locked_mark ri 1])

                                                            Dirty-interval first-step data specialized to the case where the step creates the boundary simulation's phase-1 marker. This identifies that branch as the first continuation marking rule of the same original production.

                                                            theorem nc_locked_dirty_interval_first_step_macro_or_base_one_or_new_zero {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {m : } {s_start s_after s_dirty s_clean : List (symbol T (NC_LockedNT g))} (hstart : CS_transforms (locked_csg_of_noncontracting g hg) s_start s_after) (hclean_start : nc_locked_is_clean g s_start) (hdirty_after : ¬nc_locked_is_clean g s_after) (hmid : NC_locked_dirty_derives_n g hg m s_after s_dirty) (hdirty : ¬nc_locked_is_clean g s_dirty) (hreturn : CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean) (hclean : nc_locked_is_clean g s_clean) :
                                                            ∃ (ri : ) (r : grule T g.nt) (u : List (symbol T (NC_LockedNT g))) (v : List (symbol T (NC_LockedNT g))) (m' : ) (smid : List (symbol T (locked_csg_of_noncontracting g hg).nt)), (ri, r) (List.range g.rules.length).zip g.rules (have pattern := r.input_L ++ [symbol.nonterminal r.input_N] ++ r.input_R; have dflt := symbol.nonterminal r.input_N; s_start = u ++ [nc_locked_liftSym (pattern.getD 0 dflt)] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v s_after = u ++ [nc_locked_mark ri 0] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v) m = m' + 1 CS_transforms (locked_csg_of_noncontracting g hg) s_after smid ¬nc_locked_is_clean g smid NC_locked_dirty_derives_n g hg m' smid s_dirty ((have target := u ++ List.map nc_locked_liftSym r.output_string ++ v; CS_derives (locked_csg_of_noncontracting g hg) smid target nc_locked_is_clean g target NC_locked_clean_macro_derives_n g hg 1 s_start target) (nc_locked_mark ri 0 smid nc_locked_mark ri 1 smid have pattern := r.input_L ++ [symbol.nonterminal r.input_N] ++ r.input_R; 1 < pattern.length smid = u ++ [nc_locked_mark ri 0] ++ [nc_locked_mark ri 1] ++ List.map nc_locked_liftSym (List.drop 2 pattern) ++ v) nc_locked_mark ri 0 smid nc_locked_mark ri 1smid ∀ (targetRi targetK : ), nc_locked_mark targetRi targetK smidnc_locked_mark targetRi targetKs_after∃ (grule : grule T g.nt), (targetRi, grule) (List.range g.rules.length).zip g.rules targetK = 0 have pattern := grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R; targetK < pattern.length)

                                                            Full first-step trichotomy for a dirty interval opened from a clean form. Either the first dirty-to-dirty step already gives the complete one-step clean macro pref, or it advances the boundary simulation from phase 0 to phase 1 with exact target shape, or it leaves the boundary phase-1 marker absent and any newly introduced marker is a nested phase-0 marker.

                                                            theorem nc_locked_dirty_interval_first_step_macro_or_base_one_or_fresh_zero {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {m : } {s_start s_after s_dirty s_clean : List (symbol T (NC_LockedNT g))} (hstart : CS_transforms (locked_csg_of_noncontracting g hg) s_start s_after) (hclean_start : nc_locked_is_clean g s_start) (hdirty_after : ¬nc_locked_is_clean g s_after) (hmid : NC_locked_dirty_derives_n g hg m s_after s_dirty) (hdirty : ¬nc_locked_is_clean g s_dirty) (hreturn : CS_transforms (locked_csg_of_noncontracting g hg) s_dirty s_clean) (hclean : nc_locked_is_clean g s_clean) :
                                                            ∃ (ri : ) (r : grule T g.nt) (u : List (symbol T (NC_LockedNT g))) (v : List (symbol T (NC_LockedNT g))) (m' : ) (smid : List (symbol T (locked_csg_of_noncontracting g hg).nt)), (ri, r) (List.range g.rules.length).zip g.rules (have pattern := r.input_L ++ [symbol.nonterminal r.input_N] ++ r.input_R; have dflt := symbol.nonterminal r.input_N; s_start = u ++ [nc_locked_liftSym (pattern.getD 0 dflt)] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v s_after = u ++ [nc_locked_mark ri 0] ++ List.map nc_locked_liftSym (List.drop 1 pattern) ++ v) m = m' + 1 CS_transforms (locked_csg_of_noncontracting g hg) s_after smid ¬nc_locked_is_clean g smid NC_locked_dirty_derives_n g hg m' smid s_dirty ((have target := u ++ List.map nc_locked_liftSym r.output_string ++ v; CS_derives (locked_csg_of_noncontracting g hg) smid target nc_locked_is_clean g target NC_locked_clean_macro_derives_n g hg 1 s_start target) (nc_locked_mark ri 0 smid nc_locked_mark ri 1 smid have pattern := r.input_L ++ [symbol.nonterminal r.input_N] ++ r.input_R; 1 < pattern.length smid = u ++ [nc_locked_mark ri 0] ++ [nc_locked_mark ri 1] ++ List.map nc_locked_liftSym (List.drop 2 pattern) ++ v) nc_locked_mark ri 0 smid nc_locked_mark ri 1smid ∀ (targetRi targetK : ), nc_locked_mark targetRi targetK smidnc_locked_mark targetRi targetKs_aftertargetK = 0 ∃ (grule : grule T g.nt), (targetRi, grule) (List.range g.rules.length).zip g.rules have pattern := grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R; 0 < pattern.length)

                                                            Retained-branch version of the first-step trichotomy with fresh markers normalized. If the boundary simulation has not advanced to phase 1, then any marker created by the first dirty step is a phase-0 marker for a genuine simulation rule whose input pattern is nonempty.

                                                            Terminal words reached by locked clean macro traces are generated by the original non-contracting grammar.

                                                            Backward direction helpers #

                                                            def nc_proj_sym {T : Type} (g : grammar T) :
                                                            symbol T (NC_NT g)symbol T g.nt

                                                            Projection from extended grammar symbols to original grammar symbols. For clean forms (no aux nonterminals), this is the natural "un-lifting" map.

                                                            Equations
                                                            Instances For
                                                              def nc_proj {T : Type} (g : grammar T) (s : List (symbol T (NC_NT g))) :
                                                              List (symbol T g.nt)

                                                              Projection on lists: apply nc_proj_sym pointwise.

                                                              Equations
                                                              Instances For
                                                                theorem nc_proj_liftSym {T : Type} (g : grammar T) (s : symbol T g.nt) :

                                                                proj ∘ liftSym = id: projecting a lifted symbol recovers the original.

                                                                def nc_is_clean {T : Type} (g : grammar T) (s : List (symbol T (NC_NT g))) :

                                                                A sentential form is "clean" if it has no auxiliary nonterminals.

                                                                Equations
                                                                Instances For
                                                                  theorem nc_is_clean_of_subset {T : Type} (g : grammar T) {s t : List (symbol T (NC_NT g))} (hclean : nc_is_clean g t) (hsub : xs, x t) :

                                                                  Cleanliness is preserved by taking a sublist in the membership sense.

                                                                  theorem nc_liftSym_clean {T : Type} (g : grammar T) (s : symbol T g.nt) :

                                                                  Lifted original symbols are clean.

                                                                  theorem nc_map_liftSym_clean {T : Type} (g : grammar T) (s : List (symbol T g.nt)) :

                                                                  Lifted original sentential forms are clean.

                                                                  theorem nc_not_clean_iff_exists_aux {T : Type} (g : grammar T) (s : List (symbol T (NC_NT g))) :
                                                                  ¬nc_is_clean g s ∃ (ri : ) (k : ), nc_aux ri k s

                                                                  Failure of cleanliness is exactly the presence of an auxiliary nonterminal.

                                                                  theorem nc_symToNT_ne_aux {T : Type} (g : grammar T) (s : symbol T g.nt) (p : × ) :

                                                                  Original symbols never lift to auxiliary nonterminals.

                                                                  Projection of the initial symbol.

                                                                  Projection of a terminal string.

                                                                  theorem CS_transform_new_symbol_mem_rule_output {T : Type} {g : CS_grammar T} {s₁ s₂ : List (symbol T g.nt)} {x : symbol T g.nt} (h : CS_transforms g s₁ s₂) (hx₂ : x s₂) (hx₁ : xs₁) :
                                                                  rg.rules, x r.output_string

                                                                  If a CS step creates a symbol that was not present before the step, that symbol must come from the selected rule's output string.

                                                                  theorem nc_clean_step_dirty_new_aux {T : Type} (g : grammar T) {s₁ s₂ : List (symbol T (NC_NT g))} (hclean : nc_is_clean g s₁) (hdirty : ¬nc_is_clean g s₂) :
                                                                  ∃ (ri : ) (k : ), nc_aux ri k s₂ nc_aux ri ks₁

                                                                  If a clean step becomes dirty, some auxiliary was newly introduced.

                                                                  theorem nc_rule_output_aux_is_phase1 {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {cr : csrule T (NC_NT g)} (hcr : cr (csg_of_noncontracting g hg).rules) {ri k : } (haux : nc_aux ri k cr.output_string) :
                                                                  ∃ (simRi : ) (grule : grule T g.nt) (phaseK : ), (simRi, grule) (List.range g.rules.length).zip g.rules phaseK < (grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R).length - 1 cr.output_string = [nc_aux simRi phaseK]

                                                                  The only rules of the non-contracting simulation whose output string contains an auxiliary nonterminal are phase-1 marking rules.

                                                                  theorem nc_rule_output_aux_phase1_rule_shape {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {cr : csrule T (NC_NT g)} (hcr : cr (csg_of_noncontracting g hg).rules) {ri k : } (haux : nc_aux ri k cr.output_string) :
                                                                  ∃ (simRi : ) (grule : grule T g.nt) (phaseK : ), (simRi, grule) (List.range g.rules.length).zip g.rules phaseK < (grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R).length - 1 cr = { context_left := List.map (nc_aux simRi) (List.range phaseK), input_nonterminal := nc_symToNT ((grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R).getD phaseK (symbol.nonterminal grule.input_N)), context_right := List.map nc_liftSym (List.drop (phaseK + 1) (grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R)), output_string := [nc_aux simRi phaseK] }

                                                                  Stronger form of nc_rule_output_aux_is_phase1: if a constructed rule outputs an auxiliary, the whole selected rule is exactly the corresponding phase-1 rule.

                                                                  theorem nc_clean_step_dirty_phase1_zero_shape {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_NT g))} (h : CS_transforms (csg_of_noncontracting g hg) s₁ s₂) (hclean : nc_is_clean g s₁) (hdirty : ¬nc_is_clean g s₂) :

                                                                  A clean-to-dirty step is specifically phase 0 of a simulated rule. Positive phase-1 steps have an auxiliary in their left context, so they cannot apply to a clean source.

                                                                  theorem nc_rule_input_aux_phase2_rest_shape {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {cr : csrule T (NC_NT g)} (hcr : cr (csg_of_noncontracting g hg).rules) {ri k : } (hinput : cr.input_nonterminal = Sum.inr (Sum.inr (ri, k))) :
                                                                  ∃ (simRi : ) (grule : grule T g.nt) (phaseK : ), (simRi, grule) (List.range g.rules.length).zip g.rules phaseK < (grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R).length - 1 cr = { context_left := List.map (nc_aux simRi) (List.range phaseK), input_nonterminal := Sum.inr (Sum.inr (simRi, phaseK)), context_right := List.map nc_liftSym (List.drop (phaseK + 1) grule.output_string), output_string := [nc_liftSym (grule.output_string.getD phaseK (symbol.nonterminal grule.input_N))] }

                                                                  If a selected constructed rule rewrites an auxiliary nonterminal, then it is one of the right-to-left phase-2 cleanup rules.

                                                                  theorem nc_dirty_step_clean_phase2_zero_shape {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_NT g))} (h : CS_transforms (csg_of_noncontracting g hg) s₁ s₂) (hdirty : ¬nc_is_clean g s₁) (hclean : nc_is_clean g s₂) :
                                                                  ∃ (simRi : ) (grule : grule T g.nt) (u : List (symbol T (NC_NT g))) (v : List (symbol T (NC_NT g))), (simRi, grule) (List.range g.rules.length).zip g.rules 0 < (grule.input_L ++ [symbol.nonterminal grule.input_N] ++ grule.input_R).length - 1 s₁ = u ++ [nc_aux simRi 0] ++ List.map nc_liftSym (List.drop 1 grule.output_string) ++ v s₂ = u ++ [nc_liftSym (grule.output_string.getD 0 (symbol.nonterminal grule.input_N))] ++ List.map nc_liftSym (List.drop 1 grule.output_string) ++ v

                                                                  A dirty-to-clean step must be the final phase-2 cleanup rule at phase 0. Positive phase-2 cleanup rules preserve earlier auxiliaries in their left context, so their target cannot be clean.

                                                                  theorem nc_clean_step_grammar_derives {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_NT g))} (h : CS_transforms (csg_of_noncontracting g hg) s₁ s₂) (h₁ : nc_is_clean g s₁) (h₂ : nc_is_clean g s₂) :
                                                                  grammar_derives g (nc_proj g s₁) (nc_proj g s₂)
                                                                  inductive CS_derives_n {T : Type} (g : CS_grammar T) :
                                                                  List (symbol T g.nt)List (symbol T g.nt)Prop

                                                                  Inductive step-count version of CS_derives.

                                                                  Instances For

                                                                    Clean reverse traces #

                                                                    The final reverse direction has two conceptual parts:

                                                                    1. clean-to-clean steps project to derivations in the original grammar;
                                                                    2. dirty auxiliary phases can be grouped into clean-to-clean macro steps.

                                                                    The first part is captured below. The remaining work is the phase-grouping argument for derivations that temporarily contain nc_aux symbols.

                                                                    inductive NC_clean_macro_step {T : Type} (g : grammar T) (hg : grammar_noncontracting g) :
                                                                    List (symbol T (NC_NT g))List (symbol T (NC_NT g))Prop

                                                                    Clean macro steps in the constructed grammar. The second constructor is the intended endpoint of dirty-phase grouping: one complete auxiliary simulation of an original non-contracting rule, under arbitrary surrounding context.

                                                                    Instances For
                                                                      theorem nc_clean_macro_step_grammar_derives {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {s₁ s₂ : List (symbol T (NC_NT g))} (h : NC_clean_macro_step g hg s₁ s₂) :
                                                                      grammar_derives g (nc_proj g s₁) (nc_proj g s₂)

                                                                      Every clean macro step projects to an unrestricted derivation in the original grammar.

                                                                      inductive NC_clean_macro_derives_n {T : Type} (g : grammar T) (hg : grammar_noncontracting g) :
                                                                      List (symbol T (NC_NT g))List (symbol T (NC_NT g))Prop

                                                                      Step-counted traces of clean macro steps.

                                                                      Instances For
                                                                        theorem nc_clean_macro_trace_grammar_derives {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {n : } {s₁ s₂ : List (symbol T (NC_NT g))} (h : NC_clean_macro_derives_n g hg n s₁ s₂) :
                                                                        grammar_derives g (nc_proj g s₁) (nc_proj g s₂)

                                                                        Clean macro traces project to unrestricted derivations in the original grammar.

                                                                        inductive NC_clean_derives_n {T : Type} (g : grammar T) (hg : grammar_noncontracting g) :
                                                                        List (symbol T (NC_NT g))List (symbol T (NC_NT g))Prop

                                                                        A finite CS derivation trace all of whose adjacent endpoints are clean.

                                                                        Instances For
                                                                          theorem nc_clean_trace_grammar_derives {T : Type} (g : grammar T) (hg : grammar_noncontracting g) {n : } {s₁ s₂ : List (symbol T (NC_NT g))} (h : NC_clean_derives_n g hg n s₁ s₂) :
                                                                          grammar_derives g (nc_proj g s₁) (nc_proj g s₂)

                                                                          Clean CS traces project to unrestricted derivations in the original grammar.