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
。
有什么建议吗?
答案 0 :(得分:3)
具有讽刺意味的是,鉴于我们所处的网站,您将获得堆栈溢出。
这样做是因为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.
答案 1 :(得分:2)
您的第一个问题是您的程序崩溃的原因。我不确定你使用的是什么样的Prolog系统,但是很多系统都会产生一个干净的“资源错误”,可以在Prolog中处理。
您的实际问题是您的程序不会终止查询likes(john, X)
。它为您提供了预期的答案,然后才循环。
?- likes(john,X). X = book ; X = mary ; X = tom ; ERROR: Out of local stack
你很幸运,你如此迅速地发现了这个问题。想象一下更多的答案,你有耐心去解决所有问题并不是那么明显。但是有一条捷径。请改为:
?- likes(john, X), false.
此false
目标永远不会成立。所以它很容易阻止任何答案。充其量,最后一个false
的查询会终止。目前情况并非如此。考虑以下failure-slice(查看其他答案以获取更多详细信息)时,最好看到这种不终止的原因:
?- likes(john,X), false.likes(tom,jerry) :- false.likes(mary,john) :- false.likes(mary,mary) :- false.likes(tom,mouse) :- false.likes(jerry,jerry) :- false.likes(jerry,cheese) :- false.likes(mary,fruit) :- false.likes(john,book) :- false.likes(mary,book) :- false.likes(tom,john) :- false. likes(john,X) :- likes(X,john), false,X\=john.
因此,程序的这个微小部分负责堆栈溢出。要解决这个问题,我们必须在那个小小的部分做某些事情。这是一个:添加目标dif(X, john)
,使规则现在为:
likes(john,X) :- dif(X, john), likes(X,john).
dif/2
可用于许多Prolog系统,例如:SICStus,SWI,YAP,B,IF。