Prolog循环控件无法按预期工作

时间:2016-04-02 13:48:50

标签: prolog

我有以下prolog代码。链接谓词是指包含各种链接的另一个文件,例如:

link(b,brown,j)

我正在使用成员谓词来尝试控制此路由程序中的循环。我的想法是,如果我之前到过某个位置,程序将不会尝试沿着这条路走下去。

但是,当我尝试跟踪程序以查看它出错的位置时,当它检查位置是否是位置列表中的成员时,第一个位置已经在列表中,因此程序总是尝试另一个在那之后的路线,它不应该。任何人都知道如何解决这个问题?

member(X,[X|_]).
member(X,[_|Xs]):- member(X,Xs).

route(X,X,[X],_).
route(X,Z,[X|Path],Positions):- 
    link(X,Colour,Y),
    \+member([Y,Colour],Positions),             
    route(Y,Z,Path,[[Y,Colour]|Positions]),
    !.

1 个答案:

答案 0 :(得分:3)

首先是一些小的评论:你根本不需要这样做。如果您确实希望将谓词限制为一个答案,请使用once/1在顶部进行操作。这不仅在概念上更清洁,而且效率更高。

你遇到的另一个问题与Prolog的不安全否定有关。如果你不小心像往常一样交出一个过于笼统的目标,否则总是会失败。换句话说:Prolog中的否定就是破裂。有两种方法:要么为这种情况产生错误,要么只使用更好的定义,如non_member/2

让我们看看non_member/2到底会发生什么:

link(b,brown,j).

route(X,X,[X],_).
route(X,Z,[X|Path],Positions):-
    link(X,Colour,Y),
    % \+member([Y,Colour],Positions),
    non_member([Y,Colour],Positions),
    route(Y,Z,Path,[[Y,Colour]|Positions]).

non_member(E, Es) :-
   maplist(dif(E), Es).

| ?- route(X,Y,Path,Rs).
     Y = X, Path = [X]
;    X = b, Y = j, Path = "bj", Rs = []
;    X = b, Y = j, Path = "bj", Rs = [_A],
     dif([j,brown],_A)
;    X = b, Y = j, Path = "bj", Rs = [_A,_B],
     dif([j,brown],_A),
     dif([j,brown],_B)
;    X = b, Y = j, Path = "bj", Rs = [_A,_B,_C],
     dif([j,brown],_A),
     dif([j,brown],_B),
     dif([j,brown],_C)
;    X = b, Y = j, Path = "bj", Rs = [_A,_B,_C,_D],
     dif([j,brown],_A),
     dif([j,brown],_B),
     dif([j,brown],_C),
     dif([j,brown],_D)
;    X = b, Y = j, Path = "bj", Rs = [_A,_B,_C,_D,_E],
     dif([j,brown],_A),
     dif([j,brown],_B),
     dif([j,brown],_C),
     dif([j,brown],_D),
     dif([j,brown],_E)
; ...

因此,所有答案都描述相同的Path = "bj"[b,j]的简称)。但现在最后一个参数是一个元素列表,它们必须与[j,brown]不同。所以最好的是:

route(X, Y, Path) :-
   route(X, Y, Path, []).

以下是重用path/4的替代定义。我不太确定这些颜色是什么意思。尽管如此:

clink(X-_, Y-Color) :-
   link(X, Color, Y).

route(X, Y, Path) :-
   path(clink, Path, X-none, Y-_).

甚至更短时间使用library(lambda)

route(X, Y, Path) :-
   path(\ (Xl,_)^(Yl^C)^clink(Xl,C,Yl), Path, X-none, Y-_).