如何实现这个“移动块”序言锻炼解决谓语?(How to implement a solve pred

2019-09-02 10:29发布

我使用的伊万·布拉科书序言研究:人工智能编程,我发现了一些困难,实现一个运动提出的最后一部分

这次演习是使用图形来决定如何移动块,对他们的顺序安排节目。

这是关系到程序必须做的图像:

正如可以在先前IMMAGE见块A,B,C可以使用许多可容许移动被移动:

  • 块可以仅当它是在该堆的顶部上移动

  • 块可以在地面上被移动(上空隙栈)

  • 块可以在另一个块被移动(在另一个堆叠的包含一些其它块顶部)

因此,这些移动受理诱导一个状态,图中的另一种状态,像这样的东西之间的可能的转换的图表:

所以,你可以在本身前面的图,我可以用rappresent 3子列表列表的情况。

每个子列表rappresent堆在那里我可以根据先前的限制把块

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

[[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)计算从一个合法的移动CurrentStateSuccessorState

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

[debug]  ?- s([[a,b,c],[],[]],R).
R = [[b, c], [a], []] 

我获得[[B,C],[A],[]是用于将状态的后续状态 [[A,B,C],[],[]],这是好事,因为我已移动a块从所述第二堆栈的顶部的第一堆栈的顶部(这是无效),这是一个完全合法的举动。

好了,去上我的goal/1谓词说,当我已经达到了一个最终状态(当计算必须停止):

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

它说的情况(具体的堆栈列表配置)是一个目标的情况,如果在相关堆栈列出有一个堆栈是[A,B,C]名单。

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

[[a,b,c],[],[]]
[[], [a,b,c],[]]
[[],[], [a,b,c]]

好了,现在我的问题是下面的一个:我要实现的solve/2谓词是这样的:

solve([[c,a,b],[],[]], Situation)

从一个传递情况开始(在这种情况下,具有在第一堆栈中的所有块与堆叠的名单c在地面上, b在中间, a在顶部)和到达目标的情况。

我不知道到底是什么我必须做的,我怎么也得解决这个问题(可惜我没有老师)

我试图激发自己看着这个版本的八皇后问题,即使用了类似的编程技术(其中我有一个目标,以满足和解决谓语):

s(Queens, [Queen|Queens]) :- member(Queen, [1,2,3,4,5,6,7,8]),
                             noattack(Queen, Queens, 1).

goal([_,_,_,_,_,_,_,_]).

noattack(_,[],_) :- !.
noattack(Y,[Y1|Ylist],Xdist) :-   Y =\= Y1,
                                  Y1-Y =\= Xdist,
                                  Y-Y1 =\= Xdist,
                                  Dist1 is Xdist + 1,
                                  noattack(Y,Ylist,Dist1).

solve(N,[N]) :- goal(N).      % sample call: solve([], X).

solve(N, [N|Sol1]) :- s(N,N1),
                      solve(N1,Sol1).

Answer 1:

将有在空间搜索图的循环,那么你可以切换到某种形式的约束搜索。 越容易我知道这是有界深度搜索:

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

长度/ 2列举生长长度的未结合的列表。 因此,我们得到一个结果。

需要注意的是这个,如果有从初始状态到目标/ 1无解仍将循环。 如果这是不好的,我认为解决/ 2将需要一个服务solve2 / 2谓词,将获取路径,使平时\+ memberchk(NewState, Visited)的不确定性S / 2调用之后。 那么这将是(未经测试)

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


文章来源: How to implement a solve predicate for this “moving blocks” Prolog exercise?
标签: prolog