如何在PROLOG中编写以下规则:如果P则不是Q
我知道您可以轻松编写如果P然后Q 谓词如q(X) :- p(X)
,但是如何否定q/1
谓词?我不想用non_q/1
等其他语义定义新的谓词。
答案 0 :(得分:13)
条款“如果P则不是Q”在逻辑上等同于否定条款“不是P或不是Q”。因此它是Horn clause没有正文字,并且作为SLD定理证明和Horn子句的对应的应用,可以在Prolog编程中表示为目标子句或“查询”:
?- P, Q.
让我们在一分钟内回到这个想法。
但是目标条款可能不是你想到的那种表现形式。构成Prolog“知识库”的事实和规则是明确的条款,即Horn条款,每个条款都有一个正面的文字。 “如果P不是Q”没有正面文字,那么在这个意义上它就不能表示(作为一个明确的条款)。
上面显示的目标条款“询问”是否可以证明P和Q. Prolog提供了“否定为失败”的概念,因此“询问”“不是P或不是Q”的更自然的方式是:
?- not((P,Q)).
如果P或Q失败,我们就会获得成功,如果两者都失败,我们就会失败。
但是,如果您的目的是断言知识库中的否定,Prolog自然不支持这一点。根据您的应用程序,可能有一种合理的方法来解决Prolog语法并完成所需的操作(总是有一种不合理的方法来执行它,正如您所暗示的那样,使用 non_q 谓词)
答案 1 :(得分:6)
你听说过Prolog的剪辑吗?
无论如何,我对Prolog标准知之甚少,但在SWI-Prolog中,符号\+
意味着否定。我知道它不需要在每个Prolog的翻译中工作。
你可以用Prolog的剪辑来做出谓词否定。谓词的定义如下:
not(Goal) :- call(Goal),!,fail.
not(Goal).
这意味着无法证明目标,而不是目标是错误的。 也许这个Prolog & Cut链接很有用。
答案 2 :(得分:2)
“......如果P不是Q”可以通过->
if-then控制流谓词(例如GNU)表示,以及\+
否定(或“不可证明”)运算符(例如GNU),如下所示:
(P -> \+ Q),
请注意,\+
通常会实现所谓的negation-as-failure;即,如果\+ Q
不能,则子目标/表达式Q
将成功。请注意,Q
下\+
的评估不会影响执行时表达式Q
中存在的任何变量的绑定。
例如,考虑:
foo(a).
bar(b).
鉴于以下事实,以下内容:
foo(a) -> \+ bar(a). % succeeds, as bar(a) is not provable.
foo(a) -> \+ bar(b). % fails, as bar(b) is provable.
foo(a) -> \+ bar(X). % fails, as bar(X) is provable; note that X remains unbound.
foo(X) -> \+ bar(X). % succeeds, as bar(X) where X unified to 'a' isn't provable.
正如您所描述的那样,实现类似于\+ q(X) :- p(X)
的内容(就“规则”而言)并不简单,但潜在的黑客攻击是:
q(X) :- p(X), !, fail.
此定义仅反映q(X)
对于X
p(X)
失败的意图,q(X)
如果在之前其他任何句子{em>>成功{1}},但可能不太理想。
答案 3 :(得分:0)
您可以使用最小逻辑来定义负头。在最小的逻辑 ~A可以被视为A - > FF。因此以下
P -> ~Q
可以视为:
P -> (Q -> ff).
现在,如果我们采用以下身份(A - >(B - > C))=(A& B - > C),我们 看到以上内容相当于:
P & Q -> ff.
现在有一个问题,我们如何才能提出否定查询?有一个 利用与否定不同的最小逻辑的方法 失败。这个想法是对表单的查询:
G |- A -> B
通过暂时将A添加到prolog程序G来回答,然后 试图解决B,即执行以下操作:
G, A |- B
现在让我们转到Prolog表示法,我们将显示p和p - > 〜流量 通过执行(最小逻辑)Prolog程序来暗示~q。该 prolog程序是:
p.
ff :- p, q.
查询是:
?- q -: ff.
我们首先需要定义新的连接词( - :)/ 2。快速解决方案 如下:
(A -: B) :- (assert(A); retract(A), fail), B, (retract(A); assert(A), fail).
在这里,您可以看到SWI Prolog中这种最小逻辑否定的实现:
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 5.10.4)
Copyright (c) 1990-2011 University of Amsterdam, VU Amsterdam
1 ?- [user].
:- op(1200,xfy,-:).
|: (A -: B) :- (assertz(A); retract(A), fail), B, (retract(A); assertz(A), fail).
|: p.
|: ff :- p, q.
|:
% user://1 compiled 0.02 sec, 1,832 bytes
true.
2 ?- q -: ff.
true .
最好的问候
参考: 统一证明作为逻辑程序设计的基础(1989) 作者:Dale Miller,Gopalan Nadathur,Frank Pfenning,Andre Scedrov