【问题标题】:Why does Prolog crash in this simple example?为什么 Prolog 在这个简单的例子中会崩溃?
【发布时间】:2012-04-28 03:06:10
【问题描述】:
likes(tom,jerry).
likes(mary,john).
likes(mary,mary).
likes(tom,mouse).
likes(jerry,jerry).
likes(jerry,cheese).
likes(mary,fruit).
likes(john,book).
likes(mary,book).
likes(tom,john).

likes(john,X):-likes(X,john), X\=john.

您好,上面是一个非常简单的 prolog 文件,其中包含一些事实和一条规则:John 喜欢任何喜欢他的人。 但是在加载此文件并询问 Prolog 以下查询后:

likes(john,X).

程序崩溃。原因是 prolog 以某种方式卡在 likes(john,john),即使规则声明 X\=john

有什么建议吗?

【问题讨论】:

  • 出于好奇,如果 X\=john 出现在点赞之前会怎样?
  • 很奇怪,如果你把它放在身体前面,Prolog 会返回:X = book ; false. 我不知道为什么它会在book 之后停止。

标签: prolog prolog-dif failure-slice


【解决方案1】:

具有讽刺意味的是,鉴于我们所在的网站,您会遇到堆栈溢出。

它这样做是因为 prolog 使用的执行顺序,它将在您的规则中的 likes(X,john) 处进入无限递归,它再次激活 规则 - 这不是事实 - 永远不会到达X\=john 位。

解决此问题的一种方法是将规则命名为与事实不同,如下所示:

kindoflikes(tom,jerry).
kindoflikes(mary,john).
kindoflikes(mary,mary).
kindoflikes(tom,mouse).
kindoflikes(jerry,jerry).
kindoflikes(jerry,cheese).
kindoflikes(mary,fruit).
kindoflikes(john,book).
kindoflikes(mary,book).
kindoflikes(tom,john).

likes(Y,X):- kindoflikes(X,Y), X\=Y.
likex(Y,X):- kindoflikes(Y,X), X\=Y.

注意两个规则定义中 kindoflikes 中 X 和 Y 的颠倒。 所以你得到:

?- likes(john,X).
X = mary ;
X = tom ;
X = book.

但你并不局限于寻找约翰喜欢的东西,你可以这样做:

?- likes(jerry,X).
X = tom ;
X = cheese.

【讨论】:

  • @GregHNZ:Prolog 在事实之前不执行规则
【解决方案2】:

您的第一个问题是程序崩溃的原因。我不确定您使用的是哪种 Prolog 系统,但许多系统会产生一个干净的“资源错误”,可以在 Prolog 中进行处理。

您的实际问题是您的程序不会因查询likes(john, X) 而终止。它会为您提供预期的答案,然后才会循环。

?- 喜欢(约翰,X)。 X = 书; X = 玛丽; X = 汤姆; 错误:超出本地堆栈

您很幸运能够如此迅速地发现该问题。想像更多的答案,你有耐心看完所有答案就不是那么明显了。但有一条捷径。改为询问:

?- 喜欢(约翰,X),

这个false 的目标永远不会是真的。所以它很容易阻止任何答案。充其量,以false 结尾的查询会终止。目前情况并非如此。考虑以下(查看其他答案以获取更多详细信息)时,最能看出这种不终止的原因:

?- 喜欢(约翰,X),likes(tom,jerry) :- false喜欢(玛丽,约翰):- 喜欢(玛丽,玛丽):- likes(tom,mouse) :- falselikes(jerry,jerry) :- falselikes(jerry,cheese) :- falselikes(mary,fruit) :- falselikes(john,book) :- falselikes(mary,book) :- falselikes(tom,john) :- false。 喜欢(约翰,X):- 喜欢(X,约翰),X\=约翰

因此,正是程序的这一小部分导致了堆栈溢出。为了解决这个问题,我们必须在那个微小的部分做一些事情。这是一个:添加一个目标dif(X, john),这样规则现在变为:

喜欢(约翰,X):- 差异(X,约翰), 喜欢(X,约翰)。

dif/2 可用于许多 Prolog 系统,例如:SICStus、SWI、YAP、B、IF。

【讨论】:

    猜你喜欢
    • 2015-03-08
    • 1970-01-01
    • 1970-01-01
    • 2012-11-29
    • 1970-01-01
    • 2017-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多