Emptiness of context-free grammars
The procedure
DefinitionAcceptable symbols#✓fully proved
Given a list \(G\) of natural numbers and a symbol \(s\) of an encoded grammar over an alphabet \(T\), which is either a nonterminal \(i \in \mathbb{N}\) or a terminal in \(T\), \(s\) is acceptable when it is a terminal or a nonterminal that occurs in \(G\). The test returns a Boolean.
DefinitionAcceptable productions#✓fully proved
Given a list \(G\) of nonterminals (natural numbers), the test accepts an encoded production \((A, \rho)\) when every symbol of \(\rho\) is acceptable: a terminal always is, and a nonterminal is when it belongs to \(G\). So the production is accepted exactly when every nonterminal occurring in \(\rho\) belongs to \(G\).
def ruleOk (G : List ℕ) (e : ℕ × List (ℕ ⊕ T)) : Bool :=
e.2.foldr (fun s b => symOk G s && b) true
def symOk (G : List ℕ) (s : ℕ ⊕ T) : Bool :=
Sum.elim (memB G) (fun _ => true) s
CSLibExt/Computability/Decidability/ContextFree.lean:81
Uses 1 · Used by 7
DefinitionOne round of the generating-nonterminal computation#✓fully proved
Let a list of productions be given, each a pair of a nonterminal \(A \in \mathbb{N}\) and a right-hand side made of nonterminals and terminals, together with a list \(G\) of nonterminals. One round returns, in order, the left-hand sides of those productions in whose right-hand side every nonterminal belongs to \(G\).
def genStep (rules : List (ℕ × List (ℕ ⊕ T))) (G : List ℕ) : List ℕ :=
rules.filterMap fun e => cond (ruleOk G e) (some e.1) none
def ruleOk (G : List ℕ) (e : ℕ × List (ℕ ⊕ T)) : Bool :=
e.2.foldr (fun s b => symOk G s && b) true
CSLibExt/Computability/Decidability/ContextFree.lean:85
Uses 1 · Used by 7
DefinitionGenerating nonterminals#✓fully proved
For an encoded grammar \(g\), start from the empty list of nonterminals and, in each round, replace the current list \(G\) by the list of left-hand sides of those productions of \(g\) whose right-hand sides contain no nonterminal outside \(G\). The generating nonterminals of \(g\) are the list obtained after as many rounds as \(g\) has productions.
Every nonterminal in this list derives a terminal word, and the start nonterminal is in it whenever the grammar generates some word.
def generating (g : EncodedCFG T) : List ℕ :=
(genStep g.rules)^[g.rules.length] []
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
def genStep (rules : List (ℕ × List (ℕ ⊕ T))) (G : List ℕ) : List ℕ :=
rules.filterMap fun e => cond (ruleOk G e) (some e.1) none
CSLibExt/Computability/Decidability/ContextFree.lean:109
Uses 2 · Used by 9
DefinitionThe emptiness test for context-free grammars#✓fully proved
For an encoded grammar \(g\), the test returns true exactly when the start nonterminal of \(g\) is not among the generating nonterminals of \(g\).
def isEmptyB (g : EncodedCFG T) : Bool :=
!memB g.generating g.start
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
Uses 3 · Used by 4
Stabilization
TheoremThe generating nonterminals are closed under one more round#✓fully proved
For an encoded grammar \(g\), one more round of the generating-nonterminal computation, applied to the productions of \(g\) and the generating nonterminals of \(g\), yields only generating nonterminals of \(g\): every left-hand side of a production of \(g\) whose right-hand side has all its nonterminals among the generating nonterminals of \(g\) is itself a generating nonterminal of \(g\).
theorem genStep_generating_subset (g : EncodedCFG T) :
genStep g.rules g.generating ⊆ g.generating
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
def genStep (rules : List (ℕ × List (ℕ ⊕ T))) (G : List ℕ) : List ℕ :=
rules.filterMap fun e => cond (ruleOk G e) (some e.1) none
CSLibExt/Computability/Decidability/ContextFree.lean:109
Correctness
TheoremSentential forms of productive nonterminals derive terminal words#✓fully proved
In a context-free grammar \(G\), if every nonterminal occurring in a sentential form \(u\) derives some terminal word, then \(u\) derives some terminal word.
theorem exists_derives_of_forall {G : ContextFreeGrammar T} :
∀ u : List (Symbol T G.NT),
(∀ A, Symbol.nonterminal A ∈ u → ∃ w : List T, G.Derives [.nonterminal A] (w.map .terminal))
→ ∃ w : List T, G.Derives u (w.map .terminal)
Uses 1 · Used by 1
TheoremSoundness of the productive-nonterminal iteration#✓fully proved
Let \(g\) be an encoded context-free grammar. A round sends a list \(H\) of nonterminals to the left-hand sides of those productions of \(g\) in whose right-hand side every nonterminal belongs to \(H\). For every \(k \ge 0\), every nonterminal obtained after \(k\) rounds starting from the empty list derives some terminal word in the context-free grammar that \(g\) denotes.
theorem exists_derives_of_mem_iterate (g : EncodedCFG T) :
∀ (k : ℕ) {j : ℕ}, j ∈ (genStep g.rules)^[k] [] →
∃ w : List T, g.toCFG.Derives [.nonterminal j] (w.map .terminal)
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
def genStep (rules : List (ℕ × List (ℕ ⊕ T))) (G : List ℕ) : List ℕ :=
rules.filterMap fun e => cond (ruleOk G e) (some e.1) none
CSLibExt/Computability/Decidability/ContextFree.lean:109
Uses 9 · Used by 2
TheoremA sentential form containing an empty nonterminal denotes the empty language#✓fully proved
Let \(T\) be an alphabet and \(N\) a set of nonterminals, and let \(V\) assign a language over \(T\) to each nonterminal. A sentential form \(X_1 \cdots X_m\) over \(T\) and \(N\) denotes under \(V\) the concatenation \(L_1 \cdots L_m\), where \(L_t = V(X_t)\) if \(X_t\) is a nonterminal and \(L_t = \{X_t\}\) if \(X_t\) is a terminal; the empty form denotes \(\{\varepsilon\}\). Let \(A \in N\) with \(V(A) = \emptyset\). Then every sentential form over \(T\) and \(N\) in which \(A\) occurs denotes the empty language under \(V\).
theorem evalForm_eq_zero_of_mem {N : Type*} {V : N → Language T} {A : N} (hA : V A = 0) :
∀ {u : List (Symbol T N)}, Symbol.nonterminal A ∈ u → evalForm V u = 0
def evalForm (V : N → Language T) : List (Symbol T N) → Language T
| [] => 1
| s :: u => evalSymbol V s * evalForm V u
CSLibExt/Computability/Languages/ContextFree/Basic.lean:68
Uses 2 · Used by 1
TheoremCompleteness of the generating-nonterminal computation#✓fully proved
If an encoded grammar \(g\) generates some word \(w\), then the start nonterminal of \(g\) is among the generating nonterminals of \(g\) computed by the emptiness procedure.
theorem start_mem_generating_of_mem_language {g : EncodedCFG T} {w : List T}
(hw : w ∈ g.language) : g.start ∈ g.generating
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
Uses 15 · Used by 2
TheoremCorrectness of the emptiness test#✓fully proved
For every encoded context-free grammar \(g\), the emptiness test returns true on \(g\) if and only if the language of \(g\) is empty.
theorem isEmptyB_iff (g : EncodedCFG T) : g.isEmptyB = true ↔ g.language = 0
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
Uses 8 · Used by 2
Emptiness is computable
TheoremEmptiness of context-free grammars is computable#✓fully proved
Let \(T\) be an alphabet with decidable equality and a primitive recursive encoding into the natural numbers. The predicate on encoded context-free grammars \(g\) over \(T\) that holds exactly when the language of \(g\) is empty is a computable predicate.
theorem computablePred_language_eq_zero :
ComputablePred fun g : EncodedCFG T => g.language = 0
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
Uses 9 · Used by 1
TheoremEmptiness of context-free grammars is decidable#✓fully proved
For every alphabet \(T\) with decidable equality and a primitive recursive encoding, the property of an encoded context-free grammar \(g\) over \(T\) that the language of \(g\) is empty is decidable by a multi-stack machine. This is Sipser, Theorem 4.8: the problem \(E_{\mathrm{CFG}}\) is decidable.
theorem tm2Decidable_language_eq_zero :
Cslib.Decidability.TM2Decidable fun g : EncodedCFG T => g.language = 0
def TM2Decidable (p : α → Prop) : Prop :=
∃ f : ℕ → ℕ, Nonempty (TM2Computable encodeNat encodeNat f) ∧ ∀ a, f (encode a) = 1 ↔ p a
CSLibExt/Computability/Decidability/Basic.lean:60
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
Factors
DefinitionFactor of a word#✓fully proved
For a word \(w = w_0 w_1 \cdots w_{n-1}\) and natural numbers \(i\) and \(j\), the factor of \(w\) from position \(i\) to position \(j\) is obtained by dropping the first \(i\) letters of \(w\) and keeping at most the first \(j - i\) letters of the rest, where \(j - i\) is \(0\) when \(j \le i\). For \(i \le j \le n\) it is \(w_i w_{i+1} \cdots w_{j-1}\).
Used by 4
TheoremSplitting a factor#✓fully proved
Let \(w\) be a word and \(i \le j \le |w|\), and write \(w[i, j)\) for the factor of \(w\) from position \(i\) to position \(j\). If \(w[i, j) = uv\), then \(i + |u| \le j\), \(w[i, i + |u|) = u\) and \(w[i + |u|, j) = v\).
theorem factor_eq_append {w u v : List T} {i j : ℕ} (hij : i ≤ j) (hj : j ≤ w.length)
(h : factor w i j = u ++ v) :
i + u.length ≤ j ∧ factor w i (i + u.length) = u ∧ factor w (i + u.length) j = v
def factor (w : List T) (i j : ℕ) : List T :=
(w.drop i).take (j - i)
CSLibExt/Computability/Decidability/ContextFree.lean:319
Uses 1 · Used by 1
Matching right-hand sides
DefinitionFitting a symbol at a position#✓fully proved
Write \(\langle s, t \rangle\) for the pairing bijection \(\mathbb{N} \times \mathbb{N} \to \mathbb{N}\) given by \(\langle s, t \rangle = t^2 + s\) if \(s < t\) and \(\langle s, t \rangle = s^2 + s + t\) otherwise. Given a word \(w\), a list \(R\) of items, a list \(S\) of positions and an encoded symbol \(X\), the test at a position \(i\) succeeds when either \(X\) is a terminal \(a\), \(i + 1 \in S\) and the letter of \(w\) at position \(i\) (counting from \(0\)) is \(a\); or \(X\) is a nonterminal \(B\) and some \(k \in S\) has \(\langle B, \langle i, k \rangle \rangle \in R\).
In use, \(S\) holds the positions where the rest of the right-hand side can start.
def symFits (w : List T) (R : List ℕ) (S : List ℕ) (X : ℕ ⊕ T) (i : ℕ) : Bool :=
match X with
| .inr a => memB S (i + 1) && decide (w[i]? = some a)
| .inl B => S.any fun k => memB R (Nat.pair B (Nat.pair i k))
def memB (G : List ℕ) (j : ℕ) : Bool :=
G.foldr (fun a b => decide (a = j) || b) false
CSLibExt/Computability/Decidability/PrimrecList.lean:40
Uses 1 · Used by 7
DefinitionStart positions of a right-hand side#✓fully proved
Write \(\langle s, t \rangle\) for the pairing bijection \(\mathbb{N} \times \mathbb{N} \to \mathbb{N}\) given by \(\langle s, t \rangle = t^2 + s\) if \(s < t\) and \(\langle s, t \rangle = s^2 + s + t\) otherwise. Given a word \(w\), a list \(R\) of items (natural numbers), a position \(j\) and an encoded right-hand side \(X_1 \cdots X_m\), a position \(i\) is a start when there are positions \(i = p_0, p_1, \ldots, p_m = j\) with \(p_0, \ldots, p_{m-1} \le |w|\) such that for each \(l = 1, \ldots, m\): if \(X_l\) is a terminal \(a\), then \(p_l = p_{l-1} + 1\) and the letter of \(w\) at position \(p_{l-1}\) (counting from \(0\)) is \(a\); if \(X_l\) is a nonterminal \(B\), then \(R\) contains the code \(\langle B, \langle p_{l-1}, p_l \rangle \rangle\). The starts are computed from the right, one symbol at a time, by the symbol-fitting test; for the empty right-hand side the only start is \(j\).
def starts (w : List T) (R : List ℕ) (j : ℕ) (rhs : List (ℕ ⊕ T)) : List ℕ :=
rhs.foldr (fun X S => (List.range (w.length + 1)).filter (symFits w R S X)) [j]
def symFits (w : List T) (R : List ℕ) (S : List ℕ) (X : ℕ ⊕ T) (i : ℕ) : Bool :=
match X with
| .inr a => memB S (i + 1) && decide (w[i]? = some a)
| .inl B => S.any fun k => memB R (Nat.pair B (Nat.pair i k))
CSLibExt/Computability/Decidability/ContextFree.lean:375
Uses 1 · Used by 7
DefinitionOne round of the membership procedure#✓fully proved
Write \(\langle s, t \rangle\) for the pairing bijection \(\mathbb{N} \times \mathbb{N} \to \mathbb{N}\) given by \(\langle s, t \rangle = t^2 + s\) if \(s < t\) and \(\langle s, t \rangle = s^2 + s + t\) otherwise. Given an encoded grammar \(g\), a word \(w\) and a list \(R\) of items found so far, the round lists, for every production \(A \to \rho\) of \(g\), every position \(j \le |w|\) and every start \(i\) of \(\rho\) for the factor of \(w\) ending at \(j\) given \(R\), the code \(\langle A, \langle i, j \rangle \rangle\) of the item \((A, i, j)\).
def memStep (g : EncodedCFG T) (w : List T) (R : List ℕ) : List ℕ :=
g.rules.flatMap fun e => (List.range (w.length + 1)).flatMap fun j =>
(starts w R j e.2).map fun i => Nat.pair e.1 (Nat.pair i j)
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
def starts (w : List T) (R : List ℕ) (j : ℕ) (rhs : List (ℕ ⊕ T)) : List ℕ :=
rhs.foldr (fun X S => (List.range (w.length + 1)).filter (symFits w R S X)) [j]
CSLibExt/Computability/Decidability/ContextFree.lean:382
Uses 2 · Used by 7
DefinitionCandidate items for membership#✓fully proved
For an encoded grammar \(g\) and a word \(w\), the candidate items are the triples \((A, i, j)\), encoded as natural numbers by pairing, where \(A\) is the left-hand side of a production of \(g\) and \(i, j \le |w|\); each triple is listed once for every production whose left-hand side is \(A\).
def items (g : EncodedCFG T) (w : List T) : List ℕ :=
(g.rules.map Prod.fst).flatMap fun A => (List.range (w.length + 1)).flatMap fun j =>
(List.range (w.length + 1)).map fun i => Nat.pair A (Nat.pair i j)
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
Uses 1 · Used by 7
DefinitionItems found by the membership procedure#✓fully proved
Let \(g\) be an encoded context-free grammar and \(w = w_0 \cdots w_{n-1}\) a word. An item is a triple \((A, i, j)\) of natural numbers, coded as a natural number by nested pairing. A round sends a list \(R\) of items to the items \((A, i, j)\) such that \(A \to X_1 \cdots X_m\) is a production of \(g\), \(j \le n\), and there are positions \(i = k_0, k_1, \ldots, k_m = j\), each at most \(n\), such that for every \(t\) with \(1 \le t \le m\), either \(X_t\) is the terminal \(w_{k_{t-1}}\) and \(k_t = k_{t-1} + 1\), or \(X_t\) is a nonterminal \(B\) with \((B, k_{t-1}, k_t)\) in \(R\). The items found are the result of applying the round \(M\) times to the empty list, where \(M\) is \((n + 1)^2\) times the length of the list of productions of \(g\).
def found (g : EncodedCFG T) (w : List T) : List ℕ :=
(memStep g w)^[(items g w).length] []
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
def memStep (g : EncodedCFG T) (w : List T) (R : List ℕ) : List ℕ :=
g.rules.flatMap fun e => (List.range (w.length + 1)).flatMap fun j =>
(starts w R j e.2).map fun i => Nat.pair e.1 (Nat.pair i j)
CSLibExt/Computability/Decidability/ContextFree.lean:387
def items (g : EncodedCFG T) (w : List T) : List ℕ :=
(g.rules.map Prod.fst).flatMap fun A => (List.range (w.length + 1)).flatMap fun j =>
(List.range (w.length + 1)).map fun i => Nat.pair A (Nat.pair i j)
CSLibExt/Computability/Decidability/ContextFree.lean:392
Uses 3 · Used by 7
DefinitionThe membership test for context-free grammars#✓fully proved
For an encoded grammar \(g\) with start nonterminal \(S\) and a word \(w\), the test returns true exactly when the item \((S, 0, |w|)\) is among the items found for \(g\) and \(w\).
def memLanguageB (g : EncodedCFG T) (w : List T) : Bool :=
memB (found g w) (Nat.pair g.start (Nat.pair 0 w.length))
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
def memB (G : List ℕ) (j : ℕ) : Bool :=
G.foldr (fun a b => decide (a = j) || b) false
CSLibExt/Computability/Decidability/PrimrecList.lean:40
def found (g : EncodedCFG T) (w : List T) : List ℕ :=
(memStep g w)^[(items g w).length] []
CSLibExt/Computability/Decidability/ContextFree.lean:397
Uses 3 · Used by 10
Soundness
DefinitionSound items#✓fully proved
Write \(\langle s, t \rangle\) for the pairing bijection \(\mathbb{N} \times \mathbb{N} \to \mathbb{N}\) given by \(\langle s, t \rangle = t^2 + s\) if \(s < t\) and \(\langle s, t \rangle = s^2 + s + t\) otherwise. Given an encoded grammar \(g\) and a word \(w\), a natural number \(x\) is a sound item when \(x = \langle A, \langle i, j \rangle \rangle\) for some \(A\), \(i\), \(j\) with \(i \le j \le |w|\) such that the nonterminal \(A\) yields, in the decoded grammar of \(g\), the factor of \(w\) from position \(i\) to position \(j\).
def SoundItem (g : EncodedCFG T) (w : List T) (x : ℕ) : Prop :=
∃ A i j, x = Nat.pair A (Nat.pair i j) ∧ i ≤ j ∧ j ≤ w.length ∧
Yields g.toCFG [.nonterminal A] (factor w i j)
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
inductive Yields (g : ContextFreeGrammar T) : List (Symbol T g.NT) → List T → Prop
| nil : Yields g [] []
| terminal (a : T) {u : List (Symbol T g.NT)} {w : List T} (h : Yields g u w) :
Yields g (Symbol.terminal a :: u) (a :: w)
| nonterminal {r : ContextFreeRule T g.NT} (hr : r ∈ g.rules)
{u : List (Symbol T g.NT)} {w₁ w₂ : List T}
(hout : Yields g r.output w₁) (hrest : Yields g u w₂) :
Yields g (Symbol.nonterminal r.input :: u) (w₁ ++ w₂)
CSLibExt/Computability/Languages/ContextFree/Yields.lean:48
def factor (w : List T) (i j : ℕ) : List T :=
(w.drop i).take (j - i)
CSLibExt/Computability/Decidability/ContextFree.lean:319
Uses 4 · Used by 1
Completeness
TheoremCompleteness of the start positions#✓fully proved
Let \(g\) be an encoded context-free grammar over an alphabet \(T\) with decidable equality, let \(w\) be a word over \(T\), and let \(\rho\) be an encoded right-hand side whose decoding yields a word \(u\) in the grammar that \(g\) denotes. If \(i \le j \le |w|\) and \(u\) is the factor of \(w\) from position \(i\) to position \(j\), then \(i\) is a start position of \(\rho\) at \(j\) for the word \(w\) and the list of items found by the membership procedure on \(g\) and \(w\).
theorem mem_starts_of_yields {g : EncodedCFG T} {w : List T} {β : List (Symbol T g.toCFG.NT)}
{u : List T} (h : Yields g.toCFG β u) :
∀ (rhs : List (ℕ ⊕ T)) (i j : ℕ), β = rhs.map decodeSymbol → u = factor w i j → i ≤ j →
j ≤ w.length → i ∈ starts w (found g w) j rhs
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
inductive Yields (g : ContextFreeGrammar T) : List (Symbol T g.NT) → List T → Prop
| nil : Yields g [] []
| terminal (a : T) {u : List (Symbol T g.NT)} {w : List T} (h : Yields g u w) :
Yields g (Symbol.terminal a :: u) (a :: w)
| nonterminal {r : ContextFreeRule T g.NT} (hr : r ∈ g.rules)
{u : List (Symbol T g.NT)} {w₁ w₂ : List T}
(hout : Yields g r.output w₁) (hrest : Yields g u w₂) :
Yields g (Symbol.nonterminal r.input :: u) (w₁ ++ w₂)
CSLibExt/Computability/Languages/ContextFree/Yields.lean:48
def decodeSymbol : ℕ ⊕ T → Symbol T ℕ
| .inl i => .nonterminal i
| .inr a => .terminal a
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:83
def factor (w : List T) (i j : ℕ) : List T :=
(w.drop i).take (j - i)
CSLibExt/Computability/Decidability/ContextFree.lean:319
def starts (w : List T) (R : List ℕ) (j : ℕ) (rhs : List (ℕ ⊕ T)) : List ℕ :=
rhs.foldr (fun X S => (List.range (w.length + 1)).filter (symFits w R S X)) [j]
CSLibExt/Computability/Decidability/ContextFree.lean:382
def found (g : EncodedCFG T) (w : List T) : List ℕ :=
(memStep g w)^[(items g w).length] []
CSLibExt/Computability/Decidability/ContextFree.lean:397
Uses 14 · Used by 1
TheoremCorrectness of the membership test#✓fully proved
For every encoded context-free grammar \(g\) and every word \(w\), the membership test returns true on \(g\) and \(w\) if and only if \(w\) belongs to the language of \(g\).
theorem memLanguageB_iff {g : EncodedCFG T} {w : List T} :
memLanguageB g w = true ↔ w ∈ g.language
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
def memLanguageB (g : EncodedCFG T) (w : List T) : Bool :=
memB (found g w) (Nat.pair g.start (Nat.pair 0 w.length))
CSLibExt/Computability/Decidability/ContextFree.lean:401
Uses 19 · Used by 5
TheoremMembership for context-free grammars is decidable#✓fully proved
For every alphabet \(T\) with decidable equality and a primitive recursive encoding, the property of a pair \((g, w)\), where \(g\) is an encoded context-free grammar over \(T\) and \(w\) is a word over \(T\), that \(w\) is in the language of \(g\) is decidable by a multi-stack machine. This is Sipser, Theorem 4.7: the problem \(A_{\mathrm{CFG}}\) is decidable.
theorem tm2Decidable_mem_language :
Cslib.Decidability.TM2Decidable fun p : EncodedCFG T × List T => p.2 ∈ p.1.language
def TM2Decidable (p : α → Prop) : Prop :=
∃ f : ℕ → ℕ, Nonempty (TM2Computable encodeNat encodeNat f) ∧ ∀ a, f (encode a) = 1 ↔ p a
CSLibExt/Computability/Decidability/Basic.lean:60
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
Uses 14 · Used by 5
Infiniteness
DefinitionRight-hand side length bound#✓fully proved
For an encoded grammar \(g\), the length bound is the maximum of \(2\) and the lengths of the right-hand sides of the productions of \(g\).
def lenBound (g : EncodedCFG T) : ℕ :=
g.rules.foldr (fun e m => max e.2.length m) 2
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
Uses 1 · Used by 3
DefinitionPumping bound of an encoded grammar#✓fully proved
For an encoded grammar \(g\), let \(L\) be the length bound of \(g\), the larger of \(2\) and the largest length of a right-hand side of a production of \(g\), and let \(K\) be the number of distinct left-hand sides of the productions of \(g\). The pumping bound of \(g\) is \(L^{K+1}\).
With this bound, Ogden's lemma with every letter marked gives the pumping lemma for the decoded grammar.
def pumpBound (g : EncodedCFG T) : ℕ :=
g.lenBound ^ ((dedupB (g.rules.map Prod.fst)).length + 1)
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
def dedupB (l : List ℕ) : List ℕ :=
l.foldr (fun x acc => cond (memB acc x) acc (x :: acc)) []
CSLibExt/Computability/Decidability/PrimrecList.lean:51
Uses 3 · Used by 6
DefinitionThe words of a given length over a list of letters#✓fully proved
For a list \(A\) of letters and a natural number \(n\), the list obtained from the list whose only entry is the empty word by \(n\) rounds, each of which replaces every word \(w\), in order, by the words \(a w\) for the letters \(a\) of \(A\), in order. Its entries are exactly the words of length \(n\) all of whose letters occur in \(A\).
DefinitionThe terminals of an encoded grammar#✓fully proved
For an encoded context-free grammar \(g\) over an alphabet \(T\) with decidable equality, the list of the terminals that occur in the right-hand sides of the productions of \(g\), each listed once.
Listing each terminal once keeps the enumeration of the words over these terminals free of repetitions.
def terminals (g : EncodedCFG T) : List T :=
(g.rules.flatMap fun e => e.2.filterMap Sum.getRight?).foldr
(fun a acc => cond (acc.any fun b => decide (b = a)) acc (a :: acc)) []
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
Uses 1 · Used by 4
DefinitionThe infiniteness test#✓fully proved
Let \(g\) be an encoded grammar and \(N\) its pumping bound. The test returns true exactly when some word \(w\) whose letters all occur as terminals in the productions of \(g\), with \(N \le |w| < 2N\), is accepted by the membership test for \(g\).
def infiniteB (g : EncodedCFG T) : Bool :=
(List.range g.pumpBound).any fun i =>
(wordsOver g.terminals (g.pumpBound + i)).any g.memLanguageB
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
def wordsOver (A : List T) (n : ℕ) : List (List T) :=
(fun W => W.flatMap fun w => A.map fun a => a :: w)^[n] [[]]
CSLibExt/Computability/Decidability/ContextFree.lean:727
TheoremLetters of generated words occur in the productions#✓fully proved
If a word \(w\) is generated by an encoded grammar \(g\), then every letter of \(w\) is among the terminals of \(g\), that is, it occurs in the right-hand side of some production of \(g\).
theorem mem_terminals_of_mem_language {g : EncodedCFG T} {w : List T} (hw : w ∈ g.language)
{a : T} (ha : a ∈ w) : a ∈ g.terminals
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
Uses 8 · Used by 1
TheoremPumping lemma for encoded grammars#✓fully proved
Let \(g\) be an encoded grammar with pumping bound \(N\). Every word \(w\) generated by \(g\) with \(|w| \ge N\) can be written as \(w = uvxyz\) with \(vy\) nonempty and \(|vxy| \le N\), such that \(u v^i x y^i z\) is generated by \(g\) for every natural number \(i\), including \(i = 0\).
theorem pumping_pumpBound (g : EncodedCFG T) :
∀ w ∈ g.language, g.pumpBound ≤ w.length → ∃ u v x y z : List T,
w = u ++ v ++ x ++ y ++ z ∧ v ++ y ≠ [] ∧ (v ++ x ++ y).length ≤ g.pumpBound ∧
∀ i : ℕ, u ++ (List.replicate i v).flatten ++ x ++ (List.replicate i y).flatten ++ z ∈
g.language
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
Uses 10 · Used by 2
TheoremLong words make a context-free language infinite#✓fully proved
If the language of an encoded grammar \(g\) contains a word whose length is at least the pumping bound of \(g\), then the language of \(g\) is infinite.
theorem infinite_of_mem_of_le {g : EncodedCFG T} {w : List T} (hw : w ∈ g.language)
(hlen : g.pumpBound ≤ w.length) : g.language.Infinite
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
Uses 4 · Used by 1
TheoremContext-free pumping down below twice the pumping bound#✓fully proved
Let \(g\) be an encoded context-free grammar, let \(L\) be the largest of \(2\) and the lengths of the right-hand sides of the productions of \(g\), let \(K\) be the number of distinct left-hand sides of these productions, and let \(N = L^{K+1}\) be the pumping bound of \(g\). For every word \(w\) in the language of \(g\) with \(|w| \ge N\), there is a word \(v\) in the language of \(g\) with \(N \le |v| < 2N\).
theorem exists_mem_le_lt {g : EncodedCFG T} :
∀ (n : ℕ) (w : List T), w.length = n → w ∈ g.language → g.pumpBound ≤ w.length →
∃ v ∈ g.language, g.pumpBound ≤ v.length ∧ v.length < 2 * g.pumpBound
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
Uses 4 · Used by 1
TheoremCorrectness of the infiniteness test#✓fully proved
For every encoded context-free grammar \(g\), the infiniteness test returns true on \(g\) if and only if the language of \(g\) is infinite.
theorem infiniteB_iff {g : EncodedCFG T} : g.infiniteB = true ↔ g.language.Infinite
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
Uses 11 · Used by 1
TheoremInfiniteness of context-free languages is decidable#✓fully proved
For every alphabet \(T\) with decidable equality and a primitive recursive encoding, the property of an encoded context-free grammar \(g\) over \(T\) that the language of \(g\) is infinite is decidable by a multi-stack machine. This is the problem \(\mathrm{INFINITE}_{\mathrm{CFG}}\).
theorem tm2Decidable_language_infinite :
Cslib.Decidability.TM2Decidable fun g : EncodedCFG T => g.language.Infinite
def TM2Decidable (p : α → Prop) : Prop :=
∃ f : ℕ → ℕ, Nonempty (TM2Computable encodeNat encodeNat f) ∧ ∀ a, f (encode a) = 1 ↔ p a
CSLibExt/Computability/Decidability/Basic.lean:60
structure EncodedCFG (T : Type*) where
/-- The start nonterminal. -/
start : ℕ
/-- The productions. -/
rules : List (ℕ × List (ℕ ⊕ T))
CSLibExt/Computability/Languages/ContextFree/Encoded.lean:74
Uses 20
Loading dependency explorer…
The dependency explorer needs JavaScript and its graph data.