DCG用于惯用语短语偏好

Tra*_*ers 5 prolog dcg iso-prolog

我有一个手动制作的DCG规则来选择单个单词的惯用语.DCG规则如下:

seq(cons(X,Y), I, O) :- noun(X, I, H), seq(Y, H, O), \+ noun(_, I, O).
seq(X) --> noun(X).
Run Code Online (Sandbox Code Playgroud)

第一个子句是手动制作的,因为它(:-)/2是用来代替的(-->)/2.我可以用一些使用标准DCG的子句替换这个手工制作的子句吗?

最好的祝福

PS:这是一些测试数据:

noun(n1) --> ['trojan'].
noun(n2) --> ['horse'].
noun(n3) --> ['trojan', 'horse'].
noun(n4) --> ['war'].
Run Code Online (Sandbox Code Playgroud)

以下是一些测试用例,重要的测试用例是第一个测试用例,因为它只提供n3而不是cons(n1,n2).第一个测试用例的行为是特别需要的:

?- phrase(seq(X),['trojan','horse']).
X = n3 ;
No
?- phrase(seq(X),['war','horse']).
X = cons(n4,n2) ;
No
?- phrase(seq(X),['trojan','war']).
X = cons(n1,n4) ;
No
Run Code Online (Sandbox Code Playgroud)

fal*_*lse 6

(为了避免与其他非终端碰撞我改名您seq//1nounseq//1)

我可以用一些使用标准DCG的子句替换这个手工制作的子句吗?

不,因为它不坚定而且是STO(详情如下).

意图

但是,让我从你的计划的意图开始.你说你想要选择单个单词的惯用语.你的程序真的这样做吗?或者,换句话说,你的定义真的很独特吗?我现在可以构建一个反例,但让Prolog做出这样的想法:

nouns --> [] | noun(_), nouns.

?- length(Ph, N), phrase(nouns,Ph),
   dif(X,Y), phrase(nounseq(X),Ph), phrase(nounseq(Y),Ph).
Ph = [trojan, horse, trojan],
N = 3,
X = cons(n1, cons(n2, n1)),
Y = cons(n3, n1) ;
... ;
Ph = [trojan, horse, war],
N = 3,
X = cons(n3, n4),
Y = cons(n1, cons(n2, n4)) ...

所以你的定义含糊不清.你真正想要的(可能)是某种重写系统.但这些很少以确定的方式定义.什么,如果两个单词重叠像额外的noun(n5) --> [horse, war].等.


一致性

免责声明:目前,DCG文件仍在开发中 - 非常欢迎评论!你找到这个地方的所有材料.严格地说,目前在DCG没有一致性概念.

坚定性

符合要求的定义必须保持的一个中心属性是坚定性的属性.因此,在查看您的定义之前,我将比较两个目标phrase/3(在默认模式下运行SWI).

?- Ph = [], phrase(nounseq(cons(n4,n4)),Ph0,Ph).
Ph = [],
Ph0 = [war, war] ;
false.

?- phrase(nounseq(cons(n4,n4)),Ph0,Ph), Ph = [].
false.

?- phrase(nounseq(cons(n4,n4)),Ph0,Ph).
false.

最后移动目标Ph = [],删除唯一的解决方案.因此,您的定义并不坚定.这是由于你的处理方式(\+)/1:变量O不得出现在(\+)/1.但另一方面,如果它不发生在(\+)/1你内部,你只能检查句子的开头.而不是整个句子.

以发生检查财产为准

但情况更糟:

?- set_prolog_flag(occurs_check,error).
true.

?- phrase(nounseq(cons(n4,n4)),Ph0,Ph).
ERROR: noun/3: Cannot unify _G968 with [war|_G968]: would create an infinite tree

因此,您的程序依赖于STO-unifications(主题发生 - 检查统一),其结果明确未定义

ISO/IEC 13211-1子条款7.3.3以发生检查(STO)为准,不受发生检查(NSTO)

这是因为您打算定义两个非终端的交集.请考虑以下方式来表达它:

:- op(  950,  xfx, //\\).  % ASCII approximation for ? - 2229;INTERSECTION

(NT1 //\\ NT2) -->
     call(Xs0^Xs^(phrase(NT1,Xs0,Xs),phrase(NT2,Xs0,Xs))).

%以下是预定义的library(lambda):

^(V0, Goal, V0, V) :-
      call(Goal,V).

^(V, Goal, V) :-
     call(Goal).

已经有了这个定义,我们可以进入STO情境:

?- phrase(([a]//\\[a,b]), Ph0,Ph).
ERROR: =/2: Cannot unify _G3449 with [b|_G3449]: would create an infinite tree

事实上,当使用理性树时,我们得到:

?- set_prolog_flag(occurs_check,false).
true.

?- phrase(([a]//\\[a,b]), Ph0,Ph).
Ph0 = [a|_S1], % where
    _S1 = [b|_S1],
Ph = [b|_S1].

所以有一个无限的列表,对于自然语言句子来说肯定没什么意义(除了资源和能力无限的人......).