BFS访问Prolog,为什么这个程序不起作用?

时间:2013-05-13 16:19:32

标签: prolog

我已经从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)时,似乎会出现问题。扩展节点意味着从路径列表的头部(候选路径列表)中删除第一条路径,并且由于此路径中的元素,创建一个名为NewPath的新列表,其中包含这些节点的所有一步邻居节点。

然后,使用 conc / 2 谓词,它会在路径列表的末尾构建一个新的 Paths1 候选路径列表(没有头部的候选路径的旧列表) NewPaths 列表

然后在这个新列表上执行breadthfirst( 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.

为什么呢?你有什么想法来解决这个问题吗?

1 个答案:

答案 0 :(得分:4)

第47行

not member(NewNode,[Node|Path]) 

语法无效。它必须是

\+ member(NewNode,[Node|Path])

not( member(NewNode,[Node|Path]) )