我是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中时,我遇到一个问题就是它是免费的,它显示我应该是真的假。在所有其他选择中它显示为真,我认为盒子永远不会自由。
答案 0 :(得分:1)
你采取了错误的陈述。使用事实可以很好地表示一个不可变的世界,但是一旦你开始搜索,你想要代表一个可变的世界状态,这在逻辑变量中是最好的。这样你就可以利用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
的一个文件中