我正在构建一个定语从句语法来解析 20,000 段半自然文本。随着我的谓词数据库大小的增长(现在达到 1,200 条规则),解析字符串可能需要相当长的时间 — 特别是对于 DCG 目前无法解释的字符串,因为我尚未编码语法。对于包含 30 个单词的字符串,当前最坏的情况是 3 分钟。我正在尝试弄清楚如何优化它,或者我是否应该开始研究云计算。
我正在使用 SWI-Prolog,它提供了一个“配置文件”目标,它提供了一些统计数据。我惊讶地发现数据库中最简单的规则占用了大部分执行时间。我的语料库包含代表数字的字符串,我想将它们捕获到scalar/3
谓词。这些占用了总执行时间的 50-60%。
一开始,我的电脑里有 70 行scalars.pl
,代表我的语料库中数字的数字和自然语言表示。就像这样:
scalar(scalar(3)) --> ["three"].
scalar(scalar(3)) --> ["3"].
scalar(scalar(4)) --> ["four"].
scalar(scalar(4)) --> ["4"].
...等等。
认为文件的长度是问题所在,我添加了一条新规则,该规则将自动解析任何数字表示形式:
scalar(scalar(X)) --> [Y], { atom_number(Y, X) }.
多亏了这一点,我的规则从 70 条减少到了 31 条,并提供了一些帮助——但这并不是一个巨大的节省。还有什么可以做的吗?我的感觉可能不是,因为还有什么比列表中的单个原子更简单的呢?
这些标量在整个语法的很多地方都会被调用,我认为这是问题的根源。尽管它们是简单的规则,但它们无处不在,而且不可避免。高度通用的语法不适用于我的应用程序,如果我最终得到 3,000 条或更多规则,我也不会感到惊讶。
我从来没有建造过这么大的 DCG,所以我不确定在性能方面我能期望多少。很高兴接受有关此问题的任何建议:是否有其他方式来编码这些规则?我是否应该接受某些解析将花费很长时间,并弄清楚如何并行运行解析?
先感谢您!
编辑:我被要求提供一个可重现的示例,但要做到这一点,我必须将 SO 链接到整个项目,因为这是一个规模问题。为了完整起见,这是我正在做的事情的玩具版本。想象一下,有大量文件描述了数百个名词、数百个动词和数百个句法结构。
sent(sent(VP, NP)) --> vp(VP), np(NP).
vp(vp(V)) --> v(V).
np(np(Qty, Noun)) --> qty(Qty), n(Noun).
scalar(scalar(3)) --> ["three"].
scalar(scalar(X)) --> [Y], { atom_number(Y, X) }.
qty(qty(Scalar)) --> scalar(Scalar).
v(v(eat)) --> ["eat"].
n(n(pie)) --> ["pie"].