2

所以

?- canCall(mary, Person).

工作和终止和

?- canFind(mary, Person).

也可以工作并终止。但不知何故

?- canCall(mary, Person), canFind(mary, Person). 

不终止。可能的原因是什么?

4

2 回答 2

6

(您的实际意思是:查询单独终止,但有时它们的连接不会终止)

您在这里发现了 Prolog 终止属性的一个非常基本的方面。让我们用下面的纯1程序来看看:

canFind(mary, john).

canCall(mary, bob).
canCall(A, B) :-
   canCall(B, A).

?- canCall(mary, Person).
   Person = bob
;  ... 

?- canFind(mary, Person).
   Person = john.

一切看起来都很好!让我们签入此代码,以便每个人都可以使用它。现在你倒霉的同事尝试:

?- canCall(mary, Person), canFind(mary, Person).
* LOOPS *

哦不,这个循环!也许我只需要重新排列目标:

?- canFind(mary, Person), canCall(mary, Person).
* LOOPS *

再次!

当然,你也很难过。毕竟,您认真地测试了这段代码。它终止了。还是做到了?

终止的两个概念

这是 Prolog 中最令人困惑的事情之一:我们在这里(至少)有两个不同的查询终止概念。您测试的那个(有时)称为存在终止。但是,我宁愿建议将其称为简单地找到答案。正如你所经历的那样,它非常脆弱。

如果一个查询不仅找到了答案,而且找到了所有答案并完成了查询,那么这称为通用终止或简单终止。如果 Prolog 程序员说查询终止,他们的意思是它普遍终止。

那么我们如何观察普遍终止呢?只需询问所有答案。在 GNU-Prolog 中,您键入a. 在其他系统中,您将不得不锤击SPACE;Return直到完成,否则您疲劳的眼睛或腕管会阻止它。

?- canCall(mary, Person).
   Person = bob
;  Person = bob
;  Person = bob
;  Person = bob
;  Person = bob
;  ...

所以在这里我们看到有无限多的答案(实际上,我们有限的存在必须证明这一点,但暂时相信我)。

没有更便宜的方法来观察这一点吗?没有所有这些答案文字的墙壁?您可以通过添加一个永远不会成立的条件来“关闭”答案,false.

所以改为问:

?- canCall(mary, Person), false

这种查询的结果是什么?永远不可能true。它只能是false, 如果它终止。因此,对于这个查询,我们只测试程序的终止属性

现在,两个(普遍)终止查询的结合将始终终止。所以这种终止方式更加健壮。

通用端接还有许多很酷的特性。例如,您可以随意交换子句的顺序(即事实和规则):无论它们的顺序如何,所有程序都共享完全相同的终止属性。

另一个是您可以在的帮助下轻松找到程序中未终止的来源。从这个开始阅读。

在面向命令的编程语言中,这个概念并不容易出现。但是,对于迭代器,您有非常相似的概念:如果迭代器产生第一个项目,则对应于存在终止;如果产生了有限多个项目,也就是说,如果在有限多个之后next完成,则对应于通用终止。有点儿。


1 实际上,在不纯程序中,您有各种荒谬的行为。所以考虑它们是没有意义的。

于 2016-04-05T10:20:39.253 回答
0

我想,当您单独运行时,Person会统一为两个不同的值。检查这个。

于 2016-04-05T08:09:31.117 回答