Prolog 表示否定谓词的序言
如何在PROLOG中编写以下规则:如果是p,那么不是QProlog 表示否定谓词的序言,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.
我知道你可以很容易地写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自然不会支持这一点。”。除非,如果您在程序中声明某事:-失败。
。这提供了一种否定术语的方法(比如这里的atomsomething
),事实上,这是一种非常自然(我认为并非不合理)的方法,可以在序言中明确否定术语。@sharky:我同意q:-失败。
是表示q
否定的自然方法。但它本身并不是在Prolog中“断言”q的错误的有效方法。首先,如果这是abo的唯一规则