Prolog 表示否定谓词的序言

Prolog 表示否定谓词的序言,prolog,negation,Prolog,Negation,如何在PROLOG中编写以下规则:如果是p,那么不是Q 我知道你可以很容易地写if p then Q谓词,比如Q(X):-p(X),但是你怎么能否定Q/1谓词呢?我不想用其他语义定义新的谓词,比如non_q/1你听说过Prolog中的cut吗 无论如何,我对Prolog标准不太了解,但在SWI Prolog中,\+符号表示否定。我知道它不必在每个Prolog的解释器中都工作 可以使用Prolog的cut进行谓词否定。谓词的定义如下: not(Goal) :- call(Goal),!,fail.

如何在PROLOG中编写以下规则:如果是p,那么不是Q


我知道你可以很容易地写if p then Q谓词,比如
Q(X):-p(X)
,但是你怎么能否定
Q/1
谓词呢?我不想用其他语义定义新的谓词,比如
non_q/1

你听说过Prolog中的cut吗

无论如何,我对Prolog标准不太了解,但在SWI Prolog中,
\+
符号表示否定。我知道它不必在每个Prolog的解释器中都工作

可以使用Prolog的cut进行谓词否定。谓词的定义如下:

not(Goal) :- call(Goal),!,fail.
not(Goal). 
这意味着目标无法被证明,而不是目标是错误的。 也许这个链接会有用。

从句“如果p那么不是Q”在逻辑上等同于否定从句“不是p或者不是Q”。因此,它是一个没有正文本的函数,作为SLD定理证明和Horn子句对应关系的应用,可以在Prolog编程中表示为目标子句或“查询”:

让我们马上回到这个想法上来

但目标条款可能不是你心目中的那种表述。构成序言“知识库”的事实和规则是明确的从句,即每个从句只有一个肯定的文字。“If P then not Q”没有正文本,因此在这个意义上它不能被表示(作为一个定句)

上面显示的目标子句“询问”p和Q是否都可以被证明。Prolog提供了“否定即失败”的概念,因此“询问”是否“P或Q”成立的更自然的方式是:

?- not((P,Q)).
如果p或Q失败,我们就会成功,如果两者都成功,我们就会失败

然而,如果您的目的是在知识库中断言否定,Prolog自然不支持这一点。根据您的应用程序,可能有一种合理的方法来绕过Prolog语法并完成所需的工作(总是有一种不合理的方法来完成,正如您在非q谓词中所暗示的那样)。

可以通过
->
if-then控制流谓词来表示“…if-then-not q”(例如,),与
\+
否定(或“不可证明”)运算符(例如)一起,如下所示:

(P -> \+ Q),
(A -: B) :- (assert(A); retract(A), fail), B, (retract(A); assert(A), fail).
注意,通常,
\+
将实现所谓的;i、 例如,如果
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)
q(X)
的任何其他子句之前断言
p(X)
成功时,所有
X
都会失败的意图,但可能并不理想。

您可以使用最小逻辑来定义负磁头。用最小逻辑 ~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->~q 通过执行(最小逻辑)Prolog程序暗示~q。这个 序言程序是:

p.
ff :- p, q.
查询是:

?- q -: ff.
我们首先需要定义新的连接词(-:)/2。快速解决方案 详情如下:

(P -> \+ Q),
(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所著

我认为实施方式取决于您使用它的方式。你想干什么?毕竟,Prolog是一类逻辑的子集(纯Prolog中的Horn子句)。这否定了p,但问题是关于否定q。嘿@jan burse,我在回答中描述了如何否定
p
?我看不出来<代码>q(X):-p(X)!,失败。否定
q(X)
对于所有
X
p(X)
有效的,被解释为:给定
p
q
是不可证明的。是的,再想想,你是对的。p不是否定的,它是被迫失败的。如果有第二条q(X),那么它将被否定。有趣的解决方案,应该确实有效。超级酷。但我还是有一种奇怪的感觉。在某些情况下,~q和q都是不可导的,你如何表示呢。您需要一个附加子句q(X):-throw(undefined)或q(X):-loop_无限期。这可以解决查询中包含“if P then not q”的问题,但不能解决程序中包含的问题。谢谢您的回答。它帮助我更好地理解了Prolog的构建方式。您提到“但是,如果您的目的是在知识库中断言否定,Prolog自然不会支持这一点。”。除非,如果您在程序中声明
某事:-失败。
。这提供了一种否定术语的方法(比如这里的atom
something
),事实上,这是一种非常自然(我认为并非不合理)的方法,可以在序言中明确否定术语。@sharky:我同意
q:-失败。
是表示
q
否定的自然方法。但它本身并不是在Prolog中“断言”q的错误的有效方法。首先,如果这是abo的唯一规则