不清楚这个 Prolog 深度优先搜索 (DFS) 方法代码是如何工作的

问题描述

今天老师在序言上给了我们这个代码

dfs_paths(tree(X,void,void),[X]) :- !.
dfs_paths(tree(X,L,_R),[X|Xs])   :- dfs_paths(L,Xs).
dfs_paths(tree(X,_L,R),[X|Xs])   :- dfs_paths(R,Xs).
    
tree(A) :-
   A = tree(i,tree(A,tree(la,tree(sa,void)
       ),tree(b,tree(lb,tree(sb,void)
    )).

他告诉我们代码是在 prolog 上工作 DFS 方法的一种方式,但我们没有收到有关代码如何在每一行上工作的更多信息。

我是使用 prolog 的新手,我正在尝试理解这段代码

谢谢各位!

更新:这是树

Binary tree

解决方法

显然,我们希望通过回溯获得从树根到其叶子之一的所有路径。

首先,必须更正树的声明:

树是一个按如下方式构建/编写的术语(注意,每个文本元素都是小写,否则我们将写下变量而不是常量):

tree(i,tree(a,tree(la,void,void),tree(sa,void)),tree(b,tree(lb,tree(sb,void))).

我们可以简单地通过声明一个事实来存储这棵树作为参数

tree_storage(
   tree(i,void)))
).

现在是“访问代码”

dfs_paths(+Tree,?Path)

通过由 Path 给出的树构建(或验证)路径 Tree

如果第一个参数看起来像一个叶节点(即使用带有 3 个参数的函子 tree 和参数位置 2 和 3 上的常量 void 构建,路径就是节点:

dfs_paths(tree(X,[X]).

根本不需要cut (!)。

否则,如果树的左分支不是void,则可以通过沿着左分支向下递归生成路径,并在前面加上根树节点的名称,即{ {1}}。我们不在乎在这里访问正确的分支。为了让编译器不抱怨,正确分支的占位符在前面写了一个 X

_

否则,如果树的右分支不是dfs_paths(tree(X,L,_R),[X|Xs]) :- dif(L,dfs_paths(L,Xs). ,则提供了通过沿着右分支向下递归生成路径的可能性,并在前面加上根树节点的名称,即{ {1}}。我们不在乎访问这里的左分支。为了让编译器不报错,左分支的占位符在前面写了一个 void

X

将这些放在一起并添加一个 _ 语句来打印正在发生的事情,我们看到 Prolog 通过将三个规则应用于“树”项来尝试所有可能性:

dfs_paths(tree(X,_L,R),[X|Xs]) :- dif(R,dfs_paths(R,Xs).

现在运行:

format/2