使用逻辑编程滑动瓷砖拼图,使用不同的拼贴尺寸

时间:2017-10-01 04:59:51

标签: prolog xsb

所以我试图解决这个布斯安排问题given here。它基本上是一个滑动瓷砖拼图,其中一个(展位)瓷砖必须到达目标点,最后所有其他(展位)瓷砖应该在其原始位置。每个图块/展位都有一个尺寸,以下是输入事实和关系描述:

  • 形式室(W,H)的一个事实,它指定宽度W和
    房间的高度H(3≤W,H≤20)。
  • 一个事实的摊位(B),其中 指定展位数量(1≤B≤20)。
  • 包含的关系 形状尺寸(B,W,H)的事实,其指定宽度W. 展位B的高度H.
  • 由形式的事实组成的关系
    位置(B,W,H),指定B展位的初始位置(W,H)。

  • 一个事实目标(B,W,H),指定了目的地(W,H) 目标摊位B.

  • 另一个事实视界(H)给出了上限 要执行的移动次数。

该程序应该从文件中读取输入事实,但我只是想尝试解决,所以我现在只复制粘贴一个可能的输入,并且我已经写了一些基本条款:

room(3, 3).
booths(3).
dimension(1, 2, 1).
dimension(2, 2, 1).
dimension(3, 1, 1).
position(1, 0, 1).
position(2, 1, 2).
position(3, 0, 0).
target(3, 0, 2).
horizon(10).

xlim(X) :- room(X,_).
ylim(X) :- room(_,X).

sum(X,Y,Z) :- Z is X+Y .

do(position(B,X,Y),movedown,position(B,X,Z)) :- Y > 0 , sum(Y,-1,Z) .
do(position(B,X,Y),moveup,position(B,X,Z)) :- ylim(L), Y < L , sum(Y,1,Z) .
do(position(B,X,Y),moveleft,position(B,Z,Y)) :- X > 0 , sum(X,-1,Z) .
do(position(B,X,Y),moveright,position(B,Z,Y)) :- xlim(L), X < L, sum(X,1,Z) .

noverlap(B1,B2) :- 
    position(B1,X1,Y1), 
    position(B2,X2,Y2), 
    ends(Xe1,Ye1,B1), 
    ends(Xe2,Ye2,B2), 
    ( Xe1 < X2 ; 
      Xe2 < X1 ; 
      Ye1 < Y2 ; 
      Ye2 < Y1 ).

ends(Xe,Ye,B) :- 
    dimension(B,W,H), 
    position(B,X,Y), 
    Xe is X+W-1, 
    Ye is Y+H-1.

between(X,Y,Z) :- 
    X > Y , 
    X < Z .

validMove(M,B) :- do(position(B,X,Y),M,position(B,Xn,Yn)) .

我是Prolog的新手而且我被困在如何离开这里,我有no_overlap规则,所以我可以测试一个移动是否有效,但我不确定如何使用当前的条款。我目前的移动条款do / 3可能需要一些修改。任何指针?。

1 个答案:

答案 0 :(得分:7)

你需要用谜题的状态关系来表达任务。您当前的条款确定单个移动的有效性,也可以生成可能的移动。

然而,这还不够:您需要表达的不仅仅是单个移动及其对单个磁贴的影响。您需要以某种方式对整个谜题的状态进行编码,并编码单个移动如何改变整个任务的状态。

首先,我建议您考虑一下这样的关系:

world0_move_world(W0, M, W) :- ...

并表达给定“世界”W0,可能的移动M结果世界W之间的关系。这种关系应该如此通用,以便在回溯时生成M中可能的每次移动W0。理想情况下,如果W0是一个自由变量,它甚至可以工作,为此您可能会发现有用:约束允许您以更一般的方式表达算术关系比你现在使用的那样。

一旦你有了这样的关系,整个任务就是找到一个序列 Ms移动,这样任何初始世界W0都是转换为所需的状态W

假设您已将world0_move_world/3实施为构建基块,您可以轻松将其移至列表移动,如下所示(使用):

moves(W0) --> { desired_world(W0) }.
moves(W0) --> [M], { world0_move_world(W0, M, W) }, moves(W).

然后,您可以使用迭代深化来查找解决难题的最短动作序列:

?- length(Ms, _), initial_world(W0), phrase(moves(W0), Ms).