Prolog 中的选择点和重做

mil*_*anv 6 prolog choice-point

此处询问有关何时Redo在 Prolog 中使用新变量调用a或何时尝试使用相同变量的问题后,我想我想通了。然而,在下面的一段代码中,我认为Redo要调用一个额外的代码,但事实并非如此。

我的知识库如下:

location(desk,office).
location(apple,kitchen).
location(flashlight,desk).
location('washing machine',cellar).
location(nani,'washing machine').
location(broccoli,kitchen).
location(crackers,kitchen).
location(computer,office).

edible(apple).
edible(crackers).
Run Code Online (Sandbox Code Playgroud)

我的查询是

?-location(X,kitchen),edible(X).
Run Code Online (Sandbox Code Playgroud)

具有以下跟踪:

   Call: (9) location(_5612, kitchen) ? creep
   Exit: (9) location(apple, kitchen) ? creep
   Call: (9) edible(apple) ? creep
   Exit: (9) edible(apple) ? creep
X = apple ;
   Redo: (9) location(_5612, kitchen) ? creep       <====
   Exit: (9) location(broccoli, kitchen) ? creep
   Call: (9) edible(broccoli) ? creep
   Fail: (9) edible(broccoli) ? creep
   Redo: (9) location(_5612, kitchen) ? creep
   Exit: (9) location(crackers, kitchen) ? creep
   Call: (9) edible(crackers) ? creep
   Exit: (9) edible(crackers) ? creep
X = crackers.
Run Code Online (Sandbox Code Playgroud)

为什么Redo在第一个解决方案之后没有额外的Redo: (9) edible(apple)(然后会失败,然后再继续下一个Redo),因为在带有 functor 的代码中还有另一个事实edible,这意味着有一个选择点创建?我在这里找到了相同查询的带注释痕迹。我将发布一个简短的片段,因为它有Redo我觉得这里缺少的额外内容:

网页截图

有人能指出我在这种情况下会发生什么的正确方向吗?

谢谢。

Guy*_*der 5

它与索引有关。

\n

摘自 SWI-Prolog 术语表

\n
\n

索引是一种用于快速选择特定目标谓词候选子句的技术。在大多数 Prolog 系统中,索引(仅)在头部的第一个参数上完成。如果将此参数实例化为原子、整数、浮点或带有函子的复合项,则使用散列来快速选择第一个参数可能与目标的第一个参数一致的所有子句。SWI-Prolog 支持\n即时索引和多参数索引。参见第 2.18 节。

\n
\n

这是概念和实现存在分歧的情况之一。

\n

可以这样想,如果您要为 Prolog 编写逻辑引擎,然后用户希望它运行得更快,您将添加增强功能以​​使其更快,但这样做时,它的工作方式将与概念模型。

\n

现在引擎有了增强功能,您确实应该有一个开关,可以在调试时关闭这些增强功能,以便您看到真正发生的情况。

\n

摘自Michael A. Covington的《Prolog 深度编程》 \nDonald Nute


\nAndr\xc2\xb4e Vellino

\n

秒。4.14。索引页。111

\n
\n

当 Prolog 系统执行查询时,它不必在整个知识库中搜索匹配的子句。所有 Prolog 都使用 INDEXING(散列函数或查找表)直接转到正确的谓词。例如,对于 FAMILY.PL,对 mother/2 的查询不会在子句中搜索father/2。

\n

大多数现代 Prolog 使用索引来实现更进一步的功能。它们不仅对谓词和元数进行索引,而且对 \xef\xac\x81rst 参数的主函子进行索引。例如,如果您有知识库

\n
\n
a(b).  \na(c).  \n\nd(e).\nd(f).  \n
Run Code Online (Sandbox Code Playgroud)\n
\n

那么查询 \xe2\x80\x98?- d(f).\xe2\x80\x99 不仅不会\xe2\x80\x99t 搜索子句中的 a/1,它也不会\xe2\x80\x99t 查看d(e)。它直接进入 d(f),这是唯一一个其谓词、元数和 \xef\xac\x81rst 参数与查询中的参数匹配的子句。

\n
\n

评论里有问题

\n
\n

是否有某种针对初学者的“普通”或“标准”Prolog 环境,其中这些增强功能受到限制,以便更清楚地了解所有小细节如何工作和交互?

\n
\n

元解释器

\n

来自:Prolog 中的几个元解释器

\n
\n

与其自己的实现语言相似或相同的语言的解释器称为元解释器\xc2\xa0(MI)。

\n
\n

了解 Prolog MI 是了解 Prolog 工作原理以及了解非常有用的 MI 的绝佳方式,例如

\n

使用 Prolog 开发新的编程语言

\n

用另一种语言实现

\n

了解统一如何工作的另一种方法是使用统一算法和以另一种语言实现的回溯,然后使用它来增强代码输出您想要查看的信息。有一个迷你Prolog,但我不怀疑很多人都知道 OCaml。

\n

许多有关人工智能的更广泛的书籍都实现了它。

\n

《人工智能编程范式》作者:Perter Norvig (Lisp)

\n

“解决复杂问题的人工智能结构和策略”作者:George F Luger(伪代码)

\n

Prolog 实现可以在GitHub上找到。小Prolog非常基础,用 C 语言完成。

\n

对于统一理论,有经典

\n

《自动推理手册》第8章

\n

统一论弗朗茨·巴德尔和韦恩·斯奈德的

\n

推导树

\n

请参阅:Prolog 推导树、选择和统一

\n