如何让盒子免费,在桌子上有盒子的情况下,SWI-Prolog?

凯特

我是 prolog 的初学者,我正在尝试使用如图https://i.stack.imgur.com/BechG.png所示的框来解决问题我的代码是:

box(a).
box(b).
box(c).
table(t).
on(a,t).
on(b,t).
on(c,a).
free(b).
free(c).

move(X,Z),free(Y):-
   free(X),
   free(Z),
   on(X,Y).

move(X,t):-
   free(X),
   not(on(X,t)).

move(X,Y):-
   free(X),
   free(Y).

一次只能移动一个盒子,这意味着我不能同时从桌子上抓取两个盒子。当我把这个命令放在move(c,t),move(b,c),move(a,b).SWI-Prolog 中时,我遇到了一个问题,当它被释放时,它会向我显示它应该是真的地方是假的。在所有其他选择中,它显示为真,我认为盒子 a 永远不会免费。

扬·维勒梅克

你采取了错误的表示。使用事实可以很好地表示一个不可变的世界,但是一旦您开始搜索,您就想表示世界的可变状态,这最好在逻辑变量中实现。这样你就可以利用 Prolog 的非确定性和回溯来找到让你从开始状态到最终状态的一系列移动。因此,让我们也代表数据库中的最终状态,然后使用规则来获取变量中的开始和最终状态。我们对状态的表示是一系列(三个)on(X,Y)项。

final(a,b).
final(b,c).
final(c,t).

start(State) :-
    findall(on(X,Y), on(X,Y), State).
final(State) :-
    findall(on(X,Y), final(X,Y), FinalState),
    same_state(State, FinalState).

same_state(State1, State2) :-
    sort(State1, State),
    sort(State2, State).

现在我们必须根据状态来定义自由。这很简单:顶部和桌子都是免费的:

free(X, State) :-
    box(X),
    \+ member(on(_,X), State).
free(t, _).

现在我们可以将移动定义为on(X,Y)从初始状态中删除一个并添加一个新的:

move(State0, move(X,New), [on(X,New)|Rest]) :-
    select(on(X,_), State0, Rest),
    free(X, State0),
    free(New, State0),
    X \== New.

接下来,我们必须进行多次移动。我们必须小心不要进入我们以前见过的状态:

moves(State, [], _Visited, State).
moves(State0, [Move|T], Visited, State) :-
    move(State0, Move, State1),
    \+ ( member(V, Visited),
         same_state(State1, V)
       ),
    moves(State1, T, [State1|Visited], State).

现在我们差不多完成了:

solve(Moves) :-
    start(State),
    moves(State, Moves, [State], Final),
    final(Final).

有很多需要优化。我会把它留给你。最后两个谓词确实显示了搜索的整体方法:从头开始,移动,避免回到旧状态并测试您是否找到了目标状态。全部内容都显示在https://swish.swi-prolog.org/p/BenchG.pl 的一个文件中

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章