我正在研究Ivan Bratko的书:“人工智能编程”,对于一个普遍的exame并使用SWI Prolog,我对本书中关于断言和收回谓词。
它只是呈现以下代码,将某些事实声明为动态:
:-dynamic fast(ann).
:-dynamic slow(tom).
:-dynamic slow(pat).
然后在Prolog shell中使用断言规则在数据库中定义新规则:
[debug] 59 ?- assert((faster(X,Y) :- fast(X), slow(Y))).
true.
好的,所以新规则似乎已添加到我的数据库中。
现在我尝试执行此查询并失败:
[debug] 64 ?- faster(X,Y).
false.
在书上说输出应该是这个:
A = ann
B = tom
这听起来很好而且理性,因为我已经查阅了之前的程序,其中说明了哪些是快速的,哪些是慢的,后来我添加了更快的规则断言...
为什么不工作?也许它取决于Prolog实现(SWI-Prolog)?
答案 0 :(得分:4)
Prolog中的dynamic
指令在编译的程序中很有用(通常在要编译的源文件中使用)。如果您使用assert
或等效机制在交互式shell中创建事实(或规则),那么SWI-Prolog将已假设这些谓词是动态的。
然而,dynamic
指令在您希望在为该谓词定义任何事实之前通过规则中的子句引用谓词的情况下是有益的。也就是说,假设我们首先这样做:
?- assert((faster(X,Y) :- fast(X), slow(Y))).
true.
然后尝试查询:
?- faster(X,Y).
您可能希望这只是失败,因为fast/1
或slow/1
尚未存在任何事实。但实际上SWI-Prolog将(按设计)抛出错误异常:
ERROR: faster/2: Undefined procedure: fast/1
为了防止这种情况,我们应该在用户输入模式中添加动态指令:
?- [user].
|: :-dynamic fast/1, slow/1.
|: (type Ctrl-z to exit user entry mode)
% user://1 compiled 0.00 sec, 1 clauses
现在我们将获得预期的失败行为(假设先前声明的规则):
?- faster(X,Y).
false.
您可以使用相同的模式来创建事实:
?- [user].
|: fast(ann).
|: slow(tom).
|: slow(pat).
|: (type Ctrl-z to exit user entry mode)
% user://2 compiled 0.00 sec, 4 clauses
true.
现在faster
查询以两种不同的方式成功:
?- faster(X,Y).
X = ann,
Y = tom ;
X = ann,
Y = pat.