prolog - Prolog 中的回溯
问题描述
我对 Prolog 很陌生,并且对回溯有疑问
我得到了事实
p(X, Y):- q(X, Y).
p(X, Y):- r(X, Y).
q(X, Y):- s(X), t(Y).
r(X, Y):- u(X, Y).
我得到了数据库
s(f(a)).
t(g(b)).
u(a, g(b)).
和目标
?- p(a, g(Y)).
我知道这个查询有一个解决方案
Y = b
但是,我不确定 Prolog 回溯了多少次。我相信答案是 3 次,因为 Prolog 从上到下工作并检查每个事实,以确保不能将以前的事实组合起来用于解决目标。任何帮助,将不胜感激。
最后一个 Q,具有嵌套事实的事实,IE
s(f(a))
其中 f 未定义,我可以假设这在语法上等于 s(a) 吗?
解决方案
但是,我不确定 Prolog 回溯了多少次。
不是一个很好的问题。从哪里回溯到哪里?
考虑 Prolog 构建一个搜索树(或“证明树”),这样:
- 为每个谓词调用创建一个 OR 节点,其中子节点是谓词的可能子句之一。
- 为每个子句创建一个 AND 节点,其中子节点是该子句所需的谓词调用之一。
如果证明具有以下形式,则可以找到有效证明:
- 从根“目标”递归下树:
- 每个 AND 节点的所有子节点都标记为“已证明”/“真”
- 每个 OR 节点都有一个标记为“已验证”/“真实”的子节点
- 叶节点是公理,定义为“证明”/“真实”:它们是事实。
当 Prolog 发现证明停止的情况时,就会发生“回溯”:
- OR 节点的所有子节点都不能被证明。然后“回溯”到树的一层,可能到 AND 节点(将发生更多回溯)。
- AND 节点的其中一个子节点无法被证明。然后“回溯”到无法证明的孩子的前一个兄弟姐妹,要求“重做”。如果没有先前的兄弟,则回溯到树的一层,可能到一个 OR 节点(它必须尝试它的另一个子节点)。
Prolog 程序作为搜索树执行的一个补充视图是“Byrd Box 模型”。如果收集了一些笔记。它们并不完美,但它们在这里:关于“Byrd Box 模型”。看一看。
无论如何,回到那个程序。
通过调试器运行它是有益的,但作为替代解决方案,我们可以添加一些打印语句:
p(X, Y) :-
format("p(~q,~q) clause #1\n",[X,Y]),
q(X, Y),
format("In p/2, success with q(~q,~q)\n",[X,Y]).
p(X, Y) :-
format("p(~q,~q) clause #2\n",[X,Y]),
r(X, Y),
format("In p/2, success with r(~q,~q)\n",[X,Y]).
q(X, Y) :-
format("q(~q,~q)\n",[X,Y]),
s(X),
format("In q/2, success with s(~q)\n",[X]),
t(Y),
format("In q/2, success with t(~q)\n",[Y]).
r(X, Y) :-
format("r(~q,~q)\n",[X,Y]),
u(X, Y),
format("In r/2, success with r(~q,~q)\n",[X,Y]).
s(f(a)) :- format("Fact s(f(a))\n").
t(g(b)) :- format("Fact t(g(b))\n").
u(a, g(b)) :- format("Fact u(a,g(b))\n").
运行它会带来:
?- p(a,g(Y)).
p(a,g(_1054)) clause #1
q(a,g(_1054))
p(a,g(_1054)) clause #2
r(a,g(_1054))
Fact u(a,g(b))
In r/2, success with r(a,g(b))
In p/2, success with r(a,g(b))
Y = b.
我们可以推导出搜索:
- 从 p/2 开始
- 转至q/2
- 这里我们失败了,没有 s(X),所以我们回溯到 p/2 并尝试另一个子句(OR 节点的下一个子节点)
- 再次在 p/2
- 转到 r/2
- 我们正在触及树的底部:事实!
- 剩下的就是执行执行打印输出的 AND 节点的子节点。
不知道这样是否能让事情更清楚?
最后一个 Q,具有嵌套事实的事实,IE
s(f(a))
其中 f 未定义,我可以假设这在语法上等于 s(a) 吗?
绝对不。s(f(a))
是一种句法结构。其中没有任何内容需要“定义”,也没有任何内容将被评估。它不同于s(a)
另一种句法结构。这可以在 Prolog 顶层看到:
?- s(f(a)) == s(a).
false.
推荐阅读
- python - 将 MDF 文件中的通道组合到嵌套结构中
- html - 您好我正在尝试使用 SVG 制作带有文本的加载屏幕。但是每次文本没有到达我想要的位置时,它就会出现在网站徽标的后面
- shapefile - 无法在 R 中加载 shapefile
- c++ - 简单的 C++ 计算器总是输出 16
- google-sheets - 是否可以在不冻结的情况下在 Google 表格中创建可滚动表格?
- ios - 使用 AVPlayer 分散视频注意力
- c# - 将 C# 片段转换为 Dart 以获得二维数组
- oracle - Oracle REST POST 请求返回 sys_refcursor 的问题
- python - 来自文件的 Python 模式匹配
- javascript-objects - 如何使用javascript操作数组内的对象?