Prolog间接关系

时间:2017-10-23 17:54:51

标签: prolog

我刚刚开始学习Prolog并遇到有线问题:

假设我让人们排成两行:

left(a,b).
left(c,i).
left(i,j).
right(k,j).

代表这些行:

line1:a,b  line2: c,i,j,k.

我想要的是看看这些人是否在同一条线上。我写的是遵循规则:

nextto(X,Y):- left(X,Y);left(Y,X);right(X,Y);right(Y,X).
sameline(X,Y):- nextto(X,Y).
sameline(X,Y):- nextto(X,Z),sameline(Z,Y).

我将“left/right”转换为“nextto”之间的关系。 当两个人实际上在相同的行中时,代码工作正常。但如果我尝试:

?- sameline(a,c)

“a”和“c”不在同一行。程序进入无限循环,直到用完本地堆栈。我假设它一直试图在“X”和“Y”之间找到变量“Z”,如果没有找到,程序将只创建另一个“Z”以继续搜索。我已经看到了使用递归调用的典型祖先示例:

ancestor(X,Y) :- parent(X,Y).
ancestor(X,Y) :- parent(X,Z),ancestor(Z,Y). 

这是有道理的。但是我的代码与祖先的例子有何不同?显然nextto(a,j)将返回false,但为什么循环不会停止?

这是我学习Prolog的第二天,因此高级使用Prolog可能无济于事。(。

感谢。

1 个答案:

答案 0 :(得分:2)

如果你跟踪:

?- sameline(a,c).

由于以下原因,您会看到它属于周期a <-> b

nextto(X,Y):- left(X,Y);left(Y,X);right(X,Y);right(Y,X).

在上面的规则中,您允许next(a,b)next(b,a)成功,但只需要一个成功就可以不进入周期:

在跟踪中,您可以看到:

Redo: (8) sameline(a, c) ? creep    %OK trying to succeed sameline(a,c)
   Call: (9) nextto(a, _884) ? creep

以上继续:

Call: (10) left(a, _884) ? creep
   Exit: (10) left(a, b) ? creep     %Only b succeeds left(a,_)
   Exit: (9) nextto(a, b) ? creep
   Call: (9) sameline(b, c) ? creep  %OK trying to succeed recursively 

相同线(B,C)。

但这最终要求:

Redo: (9) sameline(b, c) ? creep
   Call: (10) nextto(b, _884) ? creep
   Call: (11) left(b, _884) ? creep
   Fail: (11) left(b, _884) ? creep
   Redo: (10) nextto(b, _884) ? creep
   Call: (11) left(_882, b) ? creep
   Exit: (11) left(a, b) ? creep
   Exit: (10) nextto(b, a) ? creep
   Call: (10) sameline(a, c) ? creep   % Same thing we began due to cycle

如果我理解你正在尝试做什么,为了解决这个问题,你应该定义:

nextto(X,Y):- left(X,Y);right(Y,X).
sameline(X,Y):- nextto(X,Y).
sameline(X,Y):- nextto(X,Z),sameline(Z,Y).

nextto/2的这个定义强制遵循一条路径而不是循环。

示例:

?- sameline(c,X).
X = i ;
X = j ;
X = k ;
false.

?- sameline(c,i).
true ;
false.

?- sameline(a,c).
false.

修改

如果你想nextto / 2来处理周期,解决它的一种方法就是保留你所访问的内容列表:

sameline(X,Y):- sameline(X,Y,[X]).

nextto(X,Y):- left(X,Y);left(Y,X);right(X,Y);right(Y,X).
sameline(X,Y,_):- nextto(X,Y).
sameline(X,Y,L):- nextto(X,Z),\+member(Z,L),sameline(Z,Y,[Z|L]).