在Prolog中使用广度优先搜索方案的一般想法是什么?
不选择无限分支?
在Prolog中使用广度优先搜索的一般方法是否存在?我已经在Google上搜索了一些资料,但对于新手来说并没有找到太多有用信息。
在Prolog中使用广度优先搜索方案的一般想法是什么?
不选择无限分支?
在Prolog中使用广度优先搜索的一般方法是否存在?我已经在Google上搜索了一些资料,但对于新手来说并没有找到太多有用信息。
我听说过“议程搜索”。在遍历数据、关系、规则等树状结构时,您需要维护一个“议程”(即列表),以确定下一步要做什么。当您进入一个节点时,将其子节点放入议程中,并继续处理议程的第一个元素,然后将其弹出。这样,如果您将新项放在议程末尾,可以实现广度优先搜索;如果将它们放在议程前面,则可以实现深度优先搜索。
使用Prolog很容易实现它。
编辑:在这里我可能会给出一个实现提示。这是议程搜索算法的基本实现。
agenda_search([N|T],Mode):-
doWithNode(N), % do whatever you do the searching for
getNodeChildren(N,C),
(Mode=bf -> % bf or df (depth-first)
append(T,C,A);
append(C,T,A)),
agenda_search(A,Mode).
doWithNode
,表示您要对每个节点执行的操作(例如,将节点数据与搜索术语进行比较,序列化节点内容等)。而 getNodeChildren
会将给定节点的子项列表绑定到 C
上(即,此谓词实际上知道树结构及如何查找子节点)。当然, doWithNode
谓词可能需要其他参数来完成其工作,这些参数也会显示在 agenda_search
的参数列表中。agenda_search([RootNode], bf) % for breadth-first search
并且
agenda_search([RootNode], df) % for depth-first search
我还在这个网页上找到了一些关于议程搜索的解释。议程搜索的好处是你可以很容易地在df和bf两种变体之间切换并尝试不同的结果。算法在内存方面表现良好,因为议程(即仍需探索的节点)每次只捕捉树中的一小部分节点(即所谓的边缘节点)。
bfs(Res) :- start(Start), empty_queue(EQ), queue_append(EQ,[e(Start,[])],Q1), bfs1(Q1,Res).
bfs1(Queue,Res) :- queue_cons(e(Next,Path),NQ,Queue), bfs2(Next,Path,NQ,Res).
bfs2(H,Path,_NQ,Res) :- goal(H), reverse([H|Path],Res). bfs2(H,Path,NQ,Res) :- findall(e(Succ,[H|Path]), (s(H,Succ),\+ member(Succ,Path)),AllSuccs), queue_append(NQ,AllSuccs,NewQueue), bfs1(NewQueue,Res).
(您还可以尝试用更好的数据结构替换/补充路径组件;例如,AVL树。) 一个要解决的示例问题是:
start(env(0,0)). s(env(X,Y),env(X1,Y)) :- X1 is X+1. s(env(X,Y),env(X,Y1)) :- Y1 is Y+1. goal(env(3,3)).
您还可以通过使用启发式函数计算优先级来替换队列。然后,您将得到A*搜索(它可以模拟深度优先、广度优先、最佳优先等)。 Bratko的书(人工智能逻辑编程)应该是阅读这些材料的好来源。