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

发布于 2024-08-20 14:13:03 字数 994 浏览 4 评论 0原文

我正在编写一个谓词来查找 A* 迭代的所有可能的后继状态,并将它们放入类似 [(cost, state), ...] 的列表中,目前处于此状态:

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).

Add 添加一些内容到在列表末尾, 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 成为的列表所以它看起来像是在做我想做的事,只是不是……在我想做的地方。

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

I'm writing a predicate to find all possible successor states for an iteration of A* and put them in a list like [(cost, state), ...] , which stands at this at the moment:

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).

Add adds something to the end of a list, memb gets the (index)th element of a list. I know they work, and when I look at L2 in the bottom predicate I get something like this

?- 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] ;
...

Which is very frustrating because the [(1500, 3), (3670, 4)] list is what I want X to be after I call it so it looks to be doing what I want just not... where I want.

Please, how can I fix this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

愁杀 2024-08-27 14:13:03

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

It's been awhile since I programmed in Prolog, but I think you need to separate the list that you are building up from the list that you return (i.e., add another parameter). Your rule for [X|[]] should bind the output variable and not recurse.

残花月 2024-08-27 14:13:03

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

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

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

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

 addSuccessors_acc(L,L,_,_).

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

Think about how L actually gets it's initial value. Well the thing is it doesn't. What you're trying to do is build up a list from scratch, so you need to start with an empty list, not an unbound variable. One way to solve this is to write a wrapper predicate which allows your current predicate to act as an accumulator predicate.

This might look something like this, where addSuccessors_acc will contain the clauses that you have already defined.

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

The idea is that the second argument to the addSuccessors_acc predicate acts as your accumulator, which is the list that is being built up with each recursive call. Then in the base case of the accumulator predicate you just need to unify the accumulator variable with the first argument, to pass along the final list. eg:

 addSuccessors_acc(L,L,_,_).

Also, as ergosys points out, your third clause can actually be the base case. Since you are dealing with the last element in the list there is no need to recurse - all that is doing is delaying the base case one extra call onwards.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文