为什么这个Prolog谓词不统一?

时间:2010-02-01 19:57:37

标签: recursion prolog unification

我正在编写一个谓词来查找A *迭代的所有可能的后继状态,并将它们放在像[(成本,状态),...]这样的列表中,这就是现在的立场:

addSuccessors(L, [], _).
addSuccessors(L, [X|T], OrigList) :- memb(OrigList, Index, X),
                                     add((X, Index), L, List2),
                                     addSuccessors(List2, T, OrigList).
addSuccessors(L, [X|[]], OrigList) :- memb(OrigList, Index, X),
                                     add((X, Index), L, L2),
                                     addSuccessors(L2, [], OrigList).

添加添加到列表末尾的内容,memb获取列表的(索引)元素。我知道它们有效,当我在底部谓词中查看L2时,我会得到类似这样的内容

?- addSuccessors(X, [1500, 3670], [0, 0, 0, 1500, 3670]).
X = [] ;
[ (1500, 3), (3670, 4)]
X = [] ;
X = [_G1175] ;
[_G1175, (1500, 3), (3670, 4)]
X = [_G1175] ;
X = [_G1175, _G1181] ;
[_G1175, _G1181, (1500, 3), (3670, 4)]
X = [_G1175, _G1181] ;
...

这是非常令人沮丧的,因为[(1500,3),(3670,4)]列表是我想要X之后我称之为它所以它看起来正在做我想要的事情......我在哪里想。

请问,我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

自从我在Prolog中编程以来已经有一段时间了,但我认为您需要将您正在构建的列表与您返回的列表分开(即添加另一个参数)。 [X | []]的规则应该绑定输出变量而不是递归。

答案 1 :(得分:1)

想想L实际上是如何得到它的初始值的。嗯,事情是它没有。你要做的是从头开始构建一个列表,所以你需要从一个空列表开始,而不是一个未绑定的变量。解决此问题的一种方法是编写一个包装器谓词,它允许您的当前谓词充当累加器谓词。

这可能看起来像这样,其中addSuccessors_acc将包含您已定义的子句。

addSuccessors(L, X, Y) :-
    addSuccessors_acc(L,[],X,Y).

这个想法是addSuccessors_acc谓词的第二个参数充当你的累加器,它是每个递归调用构建的列表。然后在累加器谓词的基本情况下,您只需要将累加器变量与第一个参数统一,以传递最终列表。例如:

 addSuccessors_acc(L,L,_,_).

另外,正如ergosys指出的那样,你的第三个条款实际上可能是基本情况。由于您正在处理列表中的最后一个元素,因此无需递归 - 所有这一切都是将基本情况延迟一次额外的调用。