我从 Ivan Bratko 的书:“人工智能编程”中采用了这个实现 BFS 访问算法的程序。
它的逻辑对我来说很清楚(我已经注释了代码行的含义)但不起作用。
我的代码是:
s(a, b).
s(b, c).
s(c, d).
s(a, d).
% GOAL: il raggiungimento del nodo d:
goal(d).
/* solve(Start, Solution): Solution is a path (in reverse order) from Start to a goal it is TRUE
if it is TRUE breadthfirst(Paths, Solution) (it is TRUE if some path from a candidate set of paths Paths
can be extended to a goal nod. Solution is such an extended path
*/
solve(Start, Solution) :- breadthfirst([[Start]], Solution).
/* breadthfirst([Path1, Path2, ...], Solution) it is TRUE if:
Solution is an extension to a goal of one of the paths in the Paths list of candidates paths
SET CANDIDATES PATH RAPPRESENTATIONS: The set will be represented as a list of paths, and each path will
be a list of nodes in the inverse order; that is, the head will be the most recently generated node, and
the last element of the list will be the start node of the search
*/
/* BASE CASE: If the HEAD of the FIRST PATH (in Paths list) is a GOAL then this path is a Solution of the problem
*/
breadthfirst([[Node|Path]|_], [Node|Path]) :- goal(Node).
/* GENERAL CASE: Otherwise (if the head of the first path is not a goal node) remove the first path from the
candidates set and generate the set of all possible one-step extensions of this paths, add this set of
extension at the end of the candidate set, and execute breath-first search on this updated set
*/
breadthfirst([Path|Paths], Solution) :-
/* Remove the first path from the Paths list and extends it (generate the set of
all possible one-step extensions of this paths that is NewPaths list */
extend(Path, NewPaths),
/* Paths1 = [Paths|NewPaths] */
conc(Paths, NewPaths, Paths1),
/* Execute BFS on Paths1 */
breadthfirst(Paths1, Solution).
/* extended/2 predicate take a Path that is a list of node and generate the set of all possible one-step
extensions of this paths
*/
extend([Node|Path], NewPaths) :- bagof([NewNode, Node|Path],
(s(Node, NewNode), not member(NewNode,[Node|Path]) ),
NewPaths),
!.
extend(Path, []). % bagof failed: Node has no successor
conc([],L,L).
conc([X|L1],L2,[X|L3]) :- conc(L1,L2,L3).
问题是,当我尝试执行查询时,它总是以 FALSE 响应我(如果存在从起始节点 X 到另一个注释 Y 的路径)
例如(跟踪情况)我有:
[trace] ?- solve(a,Solution).
Call: (6) solve(a, _G367) ? creep
Call: (7) breadthfirst([[a]], _G367) ? creep
Call: (8) goal(a) ? creep
Fail: (8) goal(a) ? creep
Redo: (7) breadthfirst([[a]], _G367) ? creep
Call: (8) extend([a], _G443) ? creep
Exit: (8) extend([a], []) ? creep
Call: (8) conc([], [], _G444) ? creep
Exit: (8) conc([], [], []) ? creep
Call: (8) breadthfirst([], _G367) ? creep
Fail: (8) breadthfirst([], _G367) ? creep
Fail: (7) breadthfirst([[a]], _G367) ? creep
Fail: (6) solve(a, _G367) ? creep
false.
如您所见,当它尝试扩展不是目标节点的当前节点(在本例中为 a)时,似乎会出现问题。扩展一个节点意味着从Paths列表(候选路径列表)的头部删除第一条路径,并且由于该路径中的元素,创建一个名为NewPath的新列表,其中包含这些节点的所有一步邻居节点。
然后,使用conc/2谓词构建一个新的Paths1候选路径列表,将NewPaths列表放在Paths列表的末尾(没有头部的候选路径的旧列表)
然后在这个新列表上执行广度优先(Paths1)
当它尝试扩展当前节点时似乎会出现问题,因为似乎extends/2谓词不能很好地工作(实际上 NewPath apper void):
extend([Node|Path], NewPaths) :- bagof([NewNode, Node|Path],
(s(Node, NewNode), not member(NewNode,[Node|Path]) ),
NewPaths),
!.
有关更多信息,我在查阅我的程序时收到以下错误消息:
[debug] ?- consult(bfs).
ERROR: /home/andrea/Documenti/prolog/lezione10/bfs.pl:47:62: Syntax error: Operator expected
Warning: /home/andrea/Documenti/prolog/lezione10/bfs.pl:51:
Singleton variables: [Path]
% bfs compiled 0.00 sec, 160 bytes
true.
为什么?你有什么想法来解决这个问题吗?