这个Prolog规则为何不会陷入无限循环?

时间:2018-12-08 01:00:51

标签: prolog

我有以下事实和规则:

one(s).
one(t).
two(X,Y) :- one(X), one(Y), three(X), \+three(Y), \+two(Y,X).
three(s).

对于查询two(Y,X).,我得到以下结果:

?- two(Y,X).
Y = s,
X = t ;
false.

我不明白为什么结果是Y=sX=t。为什么Prolog不会无限次进入\+two(Y,X)? Prolog是否记得已经处理过哪些谓词?

2 个答案:

答案 0 :(得分:1)

之所以成功,是因为Prolog使用求反作为有限失败

如果我们评估Prolog谓词,则会看到:

[trace]  ?- two(X, Y).
   Call: (8) two(_660, _662) ? creep
   Call: (9) one(_660) ? creep
   Exit: (9) one(s) ? creep
   Call: (9) one(_662) ? creep
   Exit: (9) one(s) ? creep
   Call: (9) three(s) ? creep
   Exit: (9) three(s) ? creep
   Call: (9) three(s) ? creep
   Exit: (9) three(s) ? creep
   Redo: (9) one(_662) ? creep
   Exit: (9) one(t) ? creep
   Call: (9) three(s) ? creep
   Exit: (9) three(s) ? creep
   Call: (9) three(t) ? creep
   Fail: (9) three(t) ? creep
   Redo: (8) two(s, t) ? creep
   Call: (9) two(t, s) ? creep
   Call: (10) one(t) ? creep
   Exit: (10) one(t) ? creep
   Call: (10) one(s) ? creep
   Exit: (10) one(s) ? creep
   Call: (10) three(t) ? creep
   Fail: (10) three(t) ? creep
   Fail: (9) two(t, s) ? creep
   Redo: (8) two(s, t) ? creep
   Exit: (8) two(s, t) ? creep
X = s,
Y = t .

因此在失败的第一个“路径”中,XY都设置为s

two(X,Y) :-
    one(X),     %% X = s
    one(Y),     %% Y = s
    three(X),   %% X = s
    \+three(Y), %% Y = s, fail
    \+two(Y,X).

但是随后我们回溯了one(Y)调用,并获得:

two(X,Y) :-
    one(X),     %% X = s
    one(Y),     %% Y = t
    three(X),   %% X = s
    \+three(Y), %% Y = t
    \+two(Y,X)  %% call two(t, s).

现在\+ p(X, Y)被认为是true,因为p(X, Y)无法满足,并且陷入了无限循环。因此,我们将其称为two(t, s),但由于以下原因而失败了:

two(t,s) :-
    one(t),     %% succeeds
    one(s),     %% succeeds
    three(t),   %% fails
    \+three(s), %% 
    \+two(s,t)  %% 

因此three(t)失败,并且由于这里没有回溯机会,因此two(t, s)结束了。因此,这意味着two(t, s)具有有限的故障,因此\+ two(t, s)成功,因此two(X, Y)成功并且X = s, Y = t

答案 1 :(得分:1)

您定义了以下谓词:

one(s).
one(t).
two(X,Y) :- one(X), one(Y), three(X), \+three(Y), \+two(Y,X).
three(s).

谓词two(X,Y)等同于

two(X,Y) :- (X=s ; X=t), (Y=s ; Y=t), (X=s), \+(Y=s), \+two(Y,X).
=
two(X,Y) :- (X=s, (Y=s ; Y=t), X=s ; X=t, (Y=s ; Y=t), X=s), \+(Y=s), \+two(Y,X).
=
two(X,Y) :- (X=s, (Y=s ; Y=t), s=s ; X=t, (Y=s ; Y=t), t=s), \+(Y=s), \+two(Y,X).
=
two(X,Y) :- (X=s, (Y=s ; Y=t) ; false), \+(Y=s), \+two(Y,X).
=
two(X,Y) :- ((X=s, Y=s ; false), \+(Y=s) ; (X=s, Y=t ; false), \+(Y=s)), \+two(Y,X).
=
two(X,Y) :- ((X=s, Y=s ; false), \+(s=s) ; (X=s, Y=t ; false), \+(t=s)), \+two(Y,X).
=
two(X,Y) :- (X=s, Y=t ; false), true, \+two(Y,X).
=
two(X,Y) :- (X=s, Y=t, \+two(Y,X) ; false).
=
two(s,t) :- (true, \+two(t,s) ; false).
=
two(s,t) :- (true ; false).

这就是你所得到的。