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)
(为了避免与其他非终端碰撞我改名您seq//1来nounseq//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].
所以有一个无限的列表,对于自然语言句子来说肯定没什么意义(除了资源和能力无限的人......).