我是 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] 删除。
我来说两句