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.
您好,上面是一个很简单的序言文件,用事实和只有一个规则:约翰喜欢任何人谁喜欢他。 但加载该文件后问序言以下查询:
likes(john,X).
程序崩溃。 究其原因,不知何故序言卡在likes(john,john)
尽管规则规定, X\=john
。
有什么建议?
讽刺的是,由于我们是在,你得到一个堆栈溢出的网站。
它确实是因为执行的是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.
注意X和Y的两个规则定义的kindoflikes逆转。 所以,你得到:
?- likes(john,X).
X = mary ;
X = tom ;
X = book.
但是你没有锁定在寻找约翰喜欢什么,你可以这样做:
?- likes(jerry,X).
X = tom ;
X = cheese.
你的第一个问题是,为什么你的程序崩溃。 我不知道你使用的是什么样的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
末终止。 目前,这是情况并非如此。 这样做的原因未结束考虑以下时看得最清楚故障片 (查找更多详情其他答案):
?- 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。