Prolog中的广度优先

Prolog中的广度优先,prolog,breadth-first-search,logic-programming,Prolog,Breadth First Search,Logic Programming,在Prolog中,使用宽度优先于默认深度优先搜索方案的总体思路是什么 不拿无限的树枝 在Prolog中是否有使用广度优先的通用方法?我一直在谷歌上搜索,没有找到太多对新手有用的信息。广度优先的优势是你可以找到所有的解决方案。有了深度优先,你会被困在无限的树枝上 缺点是广度优先使用大量内存,因此通常不用于执行 如果您想使用它,您需要使用某种队列显式地实现它 编辑:如果您想在不占用大量内存的情况下获得广度优先搜索的优势,可以使用迭代深化。这是具有深度范围的深度优先搜索,可以依次增加深度范围。这会导致

在Prolog中,使用宽度优先于默认深度优先搜索方案的总体思路是什么

不拿无限的树枝


在Prolog中是否有使用广度优先的通用方法?我一直在谷歌上搜索,没有找到太多对新手有用的信息。

广度优先的优势是你可以找到所有的解决方案。有了深度优先,你会被困在无限的树枝上

缺点是广度优先使用大量内存,因此通常不用于执行

如果您想使用它,您需要使用某种队列显式地实现它


编辑:如果您想在不占用大量内存的情况下获得广度优先搜索的优势,可以使用迭代深化。这是具有深度范围的深度优先搜索,可以依次增加深度范围。这会导致一些重复计算,但如果您的搜索空间没有长的线性延伸而没有分支,那么这个重复就很小了。

我知道有一个东西叫做“议程搜索”。在遍历(数据、关系、规则等)树的过程中,您维护一个“议程”(列表),其中列出了下一步要做的事情。当您进入一个节点时,您将其子节点放在议程上,然后继续执行您弹出的议程的第一个元素。这样,如果你把新的项目放在议事日程的末尾,你就会得到广度优先。如果你把它们放在议事日程的前面,你就会得到深度优先

用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
,这些谓词表示要对每个节点执行的操作(例如,将节点数据与搜索词进行比较、序列化节点内容、asf)。和
getNodeChildren
,将给定节点的子节点列表绑定到
C
(即,该谓词实际上知道树结构以及如何查找子节点)。当然,
doWithNode
谓词可能需要额外的参数来完成其工作,这也会显示在
agenda\u search
的参数列表中

您可以这样调用它:

agenda_search([RootNode], bf)   % for breadth-first search


我还找到了一些关于议程搜索的解释。议程搜索的好处在于,您可以轻松地在df和bf这两个变量之间切换,并处理结果。该算法在内存方面表现良好,因为议程(仍需探索的节点)在任何时候都只能捕获树中的一小部分节点(或多或少)(所谓的边缘)。

用于议程搜索的代码应该可以正常工作。 为了效率,您可能希望考虑使用另一个数据结构;实际上,在广度优先模式下,整个节点列表(T)将由append(T,C,A)遍历。 例如,您可以使用来自SICStus的库(队列)模块。 广度优先搜索将如下所示(由谓词start/1、后续谓词s/2和目标谓词goal/1设置参数)。注意,我还添加了循环检查

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). bfs(Res):-启动(start),空队列(EQ), 队列附加(EQ[e(Start,[])],Q1), bfs1(Q1,Res)。 bfs1(队列,Res):-队列图标(e(下一个,路径),NQ,队列), bfs2(下一个,路径,NQ,Res)。 bfs2(H,路径,Res):-goal(H),reverse([H | Path],Res)。 bfs2(H、路径、NQ、Res):- findall(e(成功,[H|路径]), (s(H,Succ),\+成员(Succ,Path)),所有Succ), 队列附加(NQ、AllSuccs、NewQueue), bfs1(新队列,Res)。 (您还可以尝试用更好的数据结构(例如AVL树)替换/补充Path组件。) 要解决的一个示例问题是:

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)). 开始(环境(0,0))。 s(env(X,Y),env(X1,Y)):-X1是X+1。 s(env(X,Y),env(X,Y1)):-Y1是Y+1。 目标(env(3,3))。 您还可以将队列替换为优先级队列,并使用启发式函数计算优先级。然后得到一个*搜索(可以模拟深度优先、广度优先、最佳优先……)。 布拉特科的书(人工智能的逻辑编程)应该是阅读这些材料的好来源

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)).