Prolog无限循环

时间:2013-01-27 13:38:27

标签: prolog swi-prolog failure-slice b-prolog xsb

这是一个应该找出谁与约翰兼容的程序。 我是Prolog的新手。为了让Prolog知道,例如。 met(X,Y)= met(Y,X) 已编写了大量代码。 现在当我开始查询

?- compatible(john, X)

它进入无限循环......

源代码:

compatible(X,Y) :- reading(X), reading(Y).
compatible(X,Y) :- football(X), football(Y).
compatible(X,Y) :- friends(X,Y).
compatible(X,Y) :- mutual(X,Y).
friends(X,Y) :- havemet(X,Y), compatible(X,Y).
havemet(X,Y) :- met(X,Y).
havemet(X,Y) :- met(Y,X).
mutual(X,Y) :- friends(X,Temp), friends(Y,Temp).
mutual(X,Y) :- friends(Temp,X), friends(Y,Temp).
mutual(X,Y) :- friends(X,Temp), friends(Temp,Y).
mutual(X,Y) :- friends(Temp,X), friends(Temp,Y).

football(john).
football(james).
friends(john, carl).
friends(carl, john).
reading(carl).
reading(fred).
reading(emily).
met(carl, emily).
met(fred, james).
met(fred, emily).

我一直在研究这么多,但我仍然不明白是什么问题以及如何解决这个问题。我很乐意帮助我。

3 个答案:

答案 0 :(得分:2)

我对你的无限循环并不感到惊讶。 compatible取决于friendsfriends取决于compatible。你确定这是你想要的吗?

请注意,如果您真的希望您的规则是递归的,那么您需要一个停止条件。但我不明白为什么你需要递归来解决像亲和力匹配这样的简单问题。

答案 1 :(得分:2)

那你的程序有什么问题?这是一种本地化问题的方法。通过插入目标 false ,我们获得了failure slice。这是一个与原始程序共享许多属性的片段。特别是:如果失败切片循环,原始程序也循环。因此,failure-slice向我们展示了必须被修改以克服原始问题的程序的一部分。对于您的查询,我得到以下仍未终止的片段:

?- compatible(john, X), false.

compatible(X,Y) :- false, reading(X), reading(Y).
compatible(X,Y) :- false, football(X), football(Y).
compatible(X,Y) :- false, friends(X,Y).
compatible(X,Y) :- mutual(X,Y), false.

friends(X,Y) :- havemet(X,Y), compatible(X,Y).
friends(john, carl) :- false.
friends(carl, john).

havemet(X,Y) :- false, met(X,Y).
havemet(X,Y) :- met(Y,X).

mutual(X,Y) :- false, friends(X,Temp), friends(Y,Temp).
mutual(X,Y) :- friends(Temp,X), friends(Y,Temp), false.
mutual(X,Y) :- friends(X,Temp), false, friends(Temp,Y).
mutual(X,Y) :- false, friends(Temp,X), friends(Temp,Y).

met(carl, emily).
met(fred, james) :- false.
met(fred, emily) :- false.

但是,compatible/2的任何查询都不应该终止?对于最常见的查询,可以进一步减少故障切片:

?- compatible(X, Y), false.

compatible(X,Y) :- false, reading(X), reading(Y).
compatible(X,Y) :- false, football(X), football(Y).
compatible(X,Y) :- false, friends(X,Y).
compatible(X,Y) :- mutual(X,Y), false.

friends(X,Y) :- havemet(X,Y), compatible(X,Y).
friends(john, carl) :- false.
friends(carl, john) :- false.

havemet(X,Y) :- false, met(X,Y).
havemet(X,Y) :- met(Y,X).

mutual(X,Y) :- false, friends(X,Temp), friends(Y,Temp).
mutual(X,Y) :- false, friends(Temp,X), friends(Y,Temp).
mutual(X,Y) :- friends(X,Temp), false, friends(Temp,Y).
mutual(X,Y) :- false, friends(Temp,X), friends(Temp,Y).

met(carl, emily).
met(fred, james) :- false.
met(fred, emily) :- false.

在这里剩下的部分你必须以某种方式解决问题。未终止可能还有其他原因。但无论如何,你 来解决这个问题。

如果这还不够好,您可以在程序中添加目标V = const。但我认为这应该足够......

答案 2 :(得分:1)

您使用的Prolog系统是什么?您是否需要使用特定系统?

您的程序不会在标准Prolog中终止,但会在Prolog中提供表格支持,例如XSB-Prolog http://xsb.sourceforge.net/或B-Prolog http://www.probp.com/ - 只需添加{{1作为你程序的第一行。

:- auto_table.