我正在尝试用Prolog实现一个块世界程序。块世界是人工智能中一个著名的难题,本身相当简单。以下是我目前的代码:
% Define the blocks in your worldblocks([a, b, c, d, e, f]).% A block X is a member of the list of blocksblock(X) :- blocks(BLOCKS), % Extract the list BLOCKS member(X, BLOCKS).% Given predicatesmove(X, Y, Z, S1, S2):- member([clear, X], S1), member([on, X, Y], S1), block(Y), member([clear, Z], S1), notequal(X, Z), substitute([on, X, Y], [on, X, Z], S1, INT), substitute([clear, Z], [clear, Y], INT, S2).notequal(X, X):-!, fail.notequal(_, _).substitute(X, Y, [X|T], [Y|T]).substitute(X, Y, [H|T], [H|T1]):- substitute(X, Y, T, T1).% Additional predicates to be implemented% (i) move from a block onto the tablemove_onto_table(X, Y, S1, S2):- member([clear, X], S1), member([on, X, Y], S1), substitute([on, X, Y], [on, X, 'table'], S1, INT), substitute([clear, Y], [clear, X], INT, S2).% (ii) move from the table onto a blockmove_onto_block(X, Y, S1, S2):- member([clear, X], S1), member([on, X, 'table'], S1), substitute([on, X, 'table'], [on, X, Y], S1, INT), substitute([clear, X], [clear, Y], INT, S2).% Define start and goal statesstart([[on, d, 'table'], [on, c, d], [on, a, c], [on, b, 'table'], [clear, a], [clear, b]]).goal([[on, d, 'table'], [on, c, 'table'], [on, a, b], [on, b, 'table'], [clear, a], [clear, c], [clear, d]]).% Define notYetVisitednotYetVisited(State, PathSoFar):- permutation(State, PermuteState), \+ member(PermuteState, PathSoFar).% Define path and connect predicatespath(S1, S2):- move(X, Y, Z, S1, S2).path(S1, S2):- move_onto_table(X, Y, S1, S2).path(S1, S2):- move_onto_block(X, Y, S1, S2).connect(S1, S2) :- path(S1, S2).connect(S1, S2) :- path(S2, S1).% Define DFS predicate with added debugging statements and iterative deepeningdfs(X, [X], _):- goal(X), write('Goal reached: '), write(X), nl.% else expand X by Y and find path from Ydfs(X, [X|Ypath], VISITED):- connect(X, Y), notYetVisited(Y, VISITED), write('Current state: '), write(X), nl, write('Moving to: '), write(Y), nl, dfs(Y, Ypath, [Y|VISITED]).
我使用的查询是这样的:start(Start), dfs(Start, Path, []).
现在,输出的结果只是一个循环。尽管我实现了对重复状态的检查,但dfs似乎只是在两个相同的状态之间来回振荡,如下所示:
Current state: [[on, d, table], [on, c, d], [on, a, c], [on, b, table], [clear, a], [clear, b]]Moving to: [[on, d, table], [on, c, d], [on, a, b], [on, b, table], [clear, a], [clear, c]]Current state: [[on, d, table], [on, c, d], [on, a, b], [on, b, table], [clear, a], [clear, c]]Moving to: [[on, d, table], [on, c, d], [on, a, c], [on, b, table], [clear, a], [clear, b]]Current state: [[on, d, table], [on, c, d], [on, a, c], [on, b, table], [clear, a], [clear, b]]Moving to: [[on, d, table], [on, c, d], [on, a, b], [on, b, table], [clear, a], [clear, c]]Current state: [[on, d, table], [on, c, d], [on, a, b], [on, b, table], [clear, a], [clear, c]]Moving to: [[on, d, table], [on, c, d], [on, a, c], [on, b, table], [clear, a], [clear, b]]Current state: [[on, d, table], [on, c, d], [on, a, c], [on, b, table], [clear, a], [clear, b]]Moving to: [[on, d, table], [on, c, d], [on, a, b], [on, b, table], [clear, a], [clear, c]]Current state: [[on, d, table], [on, c, d], [on, a, b], [on, b, table], [clear, a], [clear, c]]Moving to: [[on, d, table], [on, c, d], [on, a, c], [on, b, table], [clear, a], [clear, b]]
我尝试了多种解决方案。显然,期望的是它能够通过所需的多个状态到达目标状态(该目标状态在脚本中是硬编码的)。以下是我迄今为止所做的尝试:
- 改变notYetVisited的工作方式,尝试使用简单的等式而不是使用排列。然而,这导致堆栈限制被超出。
- 在各个点添加调试语句。这些语句已包含在提供的代码中。
- 对dfs过程使用DFID(深度优先迭代加深)方法。然而,这同样几乎立即超出了堆栈限制。
- 更改dfs以在回溯时更新状态。
- 更改移动过程(move_onto_table和move_onto_block),以确保满足’clear’条件。
回答: