如何为这个“移动块”Prolog练习实现一个求解谓词?

时间:2013-05-09 17:19:31

标签: prolog

我正在学习Prolog使用Ivan Bratko的书:人工智能编程,我发现实施最后一部分练习有些困难

该练习是一个程序,它使用图形来决定如何移动块并按顺序排列它们。

这是与程序必须执行的操作相关的图像:

enter image description here

正如你在上一张图片中看到的那样,可以使用以下许多可接受的移动来移动块A,B,C:

  • 只有位于堆栈顶部的块才能移动

  • 一个区块可以在地面上移动(在空白堆栈上)

  • 可以在另一个块上移动一个块(在另一个堆栈的顶部) 包含其他一些块)

因此,这些可接受的移动会在图形中生成一个状态与另一个状态之间可能转换的图形,如下所示:

enter image description here

所以,正如您可以在上一个图表中看到的那样,我可以使用3个子列表的列表来表达情况。

每个子列表都会显示一个堆栈,我可以根据之前的约束放置块

因此,例如,上一个图的中心节点的情况可以表示为:

[[A], [B], [C]]

因为每个堆栈都包含一个块。

左上角的节点表示的情况,我在其他块C,A,B下面堆叠一个可以表示为:

[[C,A,B], [], []]

好的,所以我的程序如下:

del(X, [X|Tail], Tail).

del(X, [Y|Tail], [Y|Tail1]) :- del(X, Tail, Tail1).

/* s(CurrentState, SuccessorState): Predicate that calculate a legal move from
                                    the CurrentState to the SuccessorState:
*/
s(Stacks, [Stack1, [Top1|Stack2] | OtherStacks]) :- 
                                     del( [Top1|Stack1], Stacks, Stacks1),
                                     del( Stack2, Stacks1, OtherStacks).

goal(Situation) :- member([a,b,c], Situation).

在最后的日子里,我对它进行了深入的研究,并了解它是如何运作的。

s / 3 谓词基本上是我的后继函数s(CurrentState, SuccessorState) ,用于计算从CurrentState到{{1}的合法移动}。

这个谓词效果很好,实际上如果我启动以下查询:

SuccessorState

我获得 [[b,c],[a],[]] 是状态的[strong>后继状态 [[a,b, c],[],[]] ,这很好,因为我已经从第一个堆栈顶部的[debug] ?- s([[a,b,c],[],[]],R). R = [[b, c], [a], []] 块移动到第二个堆栈的顶部(这是无效的),这是完全合法的举动。

好的,继续我有 a 谓词说明当我到达最终状态时(计算必须停止时):

goal/1

它表示情况(特定的堆栈列表配置)是一个目标情况,如果在相关的堆栈列表中有一个堆栈是[a,b,c]列表。

所以以下情况是目标情况:

goal(Situation) :- member([a,b,c], Situation).

好了,现在我的问题是以下问题:我必须像这样实现 [[a,b,c],[],[]] [[], [a,b,c],[]] [[],[], [a,b,c]] 谓词:

solve/2

从传递的情况开始(在这种情况下是堆栈的列表,其中第一个堆栈中的所有块都在地面上solve([[c,a,b],[],[]], Situation) c在中间,b在顶部)并达到目标状态。

我不知道我到底要做什么以及如何解决(不幸的是我没有老师)

我试图激发自己看这个使用类似编程技术的8版本问题的版本(其中我有一个目标是满足和解决谓词):

a

1 个答案:

答案 0 :(得分:2)

空间搜索图中会有循环,然后您可以切换到某种形式的绑定搜索。我越容易知道它的有限深度搜索:

?- length(Situation,_), solve([[c,a,b],[],[]], Situation).
Situation = [[[c, a, b], [], []], [[a, b], [c], []], [[b], [a], [c]], [[], [b, c], [a]], [[], [a, b|...], []]] .

length / 2枚举增长长度的未绑定列表。所以我们得到了一个结果。

请注意,如果没有从初始状态到目标/ 1的解决方案,这仍将循环。 如果这很糟糕,我认为solve / 2将需要一个服务求解2/2谓词,它将获得路径,以便在非确定性s / 2调用之后启用通常的\+ memberchk(NewState, Visited)。那么它将是(未经测试的)

solve(N, SearchPath) :- solve2([N], SearchPath).

solve2([N|Visited], [N|Visited]) :- goal(N).
solve2([N|Visited], Path) :-
   s(N,N1),
   \+ memberchk(N1, Visited),
   solve2([N1,N|Visited], Path).