匹配“连接器”并创建结构?

问题描述

我正在尝试匹配然后转换为结构:

text1,connector,text2 ==> connector(text1,text2)

以下有效,但似乎太笨拙且不习惯:

p([]) --> [].
p([H|T]) --> [H],p(T).
conn(C) :- member(C,[on,in]).
req(C) --> p(X),[Fun],p(Y),{ C =.. [Fun,X,Y],conn(Fun) }.

什么是更好的方法


有一些问题,所以这里是大局......经过一些探索后,这里就是它的位置..

我想解析简体英语,这样它就可以生成事实、规则、动作、问题搜索等......这些将用于像 env 这样的聊天中,即 Q/A、req/reply、train-learn ...循环

这不太适合语言解析(np,vp,noun,..),但最好先解析语言模板,如编程语言..

模板如:ifthen、repeat、while、in、in、on、part-of、isa等。

...(后来我想如果我需要的话用python-spacy预解析POS信息/解决POS问题/,因为prolog没有NN标记。有python-prolog桥接和python也有更好的 CLI 库)

解决方法

您将程序简化为最小示例是件好事,不幸的是它变得太小了。根据您的其他问题,我将从您的代码的以下版本开始:

noun(box) --> [box].
noun(table) --> [table].

conn(C) :- member(C,[on,in]).

req(C) --> noun(X),[Fun],noun(Y),{ C =.. [Fun,X,Y],conn(Fun) }.

以下工作:

?- phrase(req(Req),[box,on,table]).
Req = on(box,table) ;
false.

但最一般的查询不起作用:

?- phrase(req(Req),Phrase).
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR:   [12] _4008=..[_4014,box|...]

这很不幸,因为最通用的查询非常方便:它为您提供了一些“免费测试”,让您无需考虑测试用例即可运行代码。此处错误的原因是我们试图将 =../2 与可变函数符号一起应用。

我会更像这样写这个语法:

noun(box) --> [box].
noun(table) --> [table].

connector(X,Y,on(X,Y)) -->
    [on].
connector(X,in(X,Y)) -->
    [in].

req(C) -->
    noun(X),connector(X,C),noun(Y).

这有点明确,但它允许我们使用最一般的查询进行测试(详尽无遗,因为没有递归!):

?- phrase(req(Req),Phrase).
Req = on(box,box),Phrase = [box,box] ;
Req = on(box,table),table] ;
Req = in(box,in,box] ;
Req = in(box,table] ;
Req = on(table,Phrase = [table,box] ;
Req = on(table,table] ;
Req = in(table,box] ;
Req = in(table,table].

具体测试也有效(希望这并不奇怪):

?- phrase(req(Req),table) ;
false.

connector 规则构建术语允许它们为特定连接器做额外的工作。例如,我们可能希望将“inside”视为“in”的同义词:

connector(X,Y)) -->
    [in] | [inside].

?- phrase(req(Req),box]).
Req = in(box,box) ;
false.

?- phrase(req(Req),inside,box) ;
false.

或者我们可能希望将“X 下的Y”视为“Y 上的X”的同义词:

connector(X,on(Y,X)) -->
    [under].

?- phrase(req(Req),[table,under,box]).
Req = on(box,table) ;
false.
,

你的问题缺乏上下文,所以我不能说你的任务是否真的需要 DCG。以防万一,请记住 req//1 将组合得很糟糕,因为 p//1 将匹配任何内容,并且只有在回溯时才会识别连接器。

如果连接器在一个短语中只出现一次,也许这会更易读:

req(L,Y)) :- append(X,[in|Y],L).
req(L,[on|Y],L).

编辑

并且很容易概括,就像您已经做过的那样:

req(L,C) :- append(X,[F|Y],L),conn(F),C=..[F,Y].