import nltk
from nltk.parse.generate import generate,demo_grammar
from nltk import CFG
grammar = CFG.fromstring("""
ROOT -> S
S -> NP VP
NP -> NP PP
NP -> DT NN
DT -> 'The'
NN -> 'work'
PP -> IN NP
IN -> 'of'
NP -> DT NN
DT -> 'the'
NN -> 'painter'
VP -> VBZ ADJP
VBZ -> 'is'
ADJP -> JJ
JJ -> 'good'
""")
print(grammar)
for sentence in generate(grammar, n=100):
print(' '.join(sentence))
给出错误
RuntimeError: maximum recursion depth exceeded while calling a Python object
尝试改变functools.py中的隐蔽功能,仍然是同样的问题。
答案 0 :(得分:3)
函数generate
,作为其文档字符串状态,"生成来自CFG的所有句子的迭代器。"显然,它是通过按照语法中列出的顺序选择替代扩展来实现的。因此,第一次看到NP
,它会使用规则NP -> NP PP
对其进行扩展。它现在有另一个NP
来扩展,它也会以相同的规则扩展......等等无限期,或者更确切地说,直到超出python的限制。
要解决您提供的语法问题,只需重新排序前两个NP
规则,以便递归规则不是第一个遇到的规则:
grammar = CFG.fromstring("""
ROOT -> S
S -> NP VP
NP -> DT NN
NP -> NP PP
DT -> 'The'
...
""")
这样做,发生器会产生大量完整的句子供你检查。请注意,更正的语法仍然是递归的,因此是无限的;如果生成足够多的句子,最终会达到相同的递归深度限制。
答案 1 :(得分:-1)
我试图对NP NN DT等的重复出现进行编号。由于唯一识别(我推测),似乎解决了这个问题。令我感到奇怪的是它应该在第一时间就是这样,即抛出的树木生产应该序列化词性。
import nltk
from nltk.parse.generate import generate,demo_grammar
from nltk import CFG
grammar = CFG.fromstring("""
ROOT -> S
S -> NP VP
NP -> NP1 PP
NP1 -> DT1 NN1
DT1 -> 'The'
NN1 -> 'work'
PP -> IN NP2
IN -> 'of'
NP2 -> DT2 NN2
DT2 -> 'the'
NN2 -> 'painter'
VP -> VBZ ADJP
VBZ -> 'is'
ADJP -> JJ
JJ -> 'good'
""")
print(grammar)
for sentence in generate(grammar, n=100):
print(' '.join(sentence))