在询问here关于何时在Prolog中使用新变量调用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).
,但情况似乎并非如此。
我的知识库如下:
?-location(X,kitchen),edible(X).
我的查询是
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.
带有以下描述:
Redo
为什么在Redo: (9) edible(apple)
的第一个解决方案之后没有额外的Redo
(在继续下一个edible
之前会失败),因为还有另一个在函数Redo
的代码中,这意味着创建了一个选择点?我找到了相同查询的注释跟踪here。我会从中发布一个简短的片段,因为它有额外的{{1}},我觉得这里缺少:
有人能指出我在这种情况下的预期正确方向吗?
感谢。
答案 0 :(得分:4)
它与Indexing有关。
来自SWI-Prolog术语表
索引是一种用于快速选择a的候选子句的技术 针对特定目标的谓词。在大多数Prolog系统中,索引是 完成(仅)头部的第一个参数。如果这个论点是 用functor实例化为atom,integer,float或复合项, 散列用于快速选择第一个参数的所有子句 可以与目标的第一个参数统一起来。 SWI-Prolog支持 即时和多参数索引。见2.18节。
这是概念和实施不同的情况之一。
想想这样,如果你要为Prolog编写逻辑引擎,然后用户希望它更快地工作,你会添加使其更快的增强功能,但这样做,它的工作方式不会是与概念模型相同。
既然引擎有增强功能,你应该有一个开关,在调试时关闭这些增强功能,以便你看到真正发生的事情。
从Prolog Programming in Depth开始
Michael A. Covington
唐纳德努特
Andr'e Vellino
秒。 4.14。索引pg。 111
当Prolog系统执行查询时,它不必在整个知识库中搜索匹配的子句。所有Prolog使用INDEXING(散列函数或查找表)直接转到右谓词。例如,对于FAMILY.PL,对mother / 2的查询不会搜索父/ 2的子句。
大多数现代Prolog使用索引来进一步发展。它们不仅对谓词和arity进行索引,还对第一个参数的主要函子进行索引。例如,如果您有知识库
a(b).
a(c).
d(e).
d(f).
然后查询'? - d(f)。'不仅不会搜索/ 1的子句,它也不会查看d(e)。它直接转到d(f),这是唯一一个谓词,arity和第一个参数匹配查询的子句。
对于那些有限的增强功能的初学者,是否有某种“香草”或“标准”Prolog环境,以便更清楚地了解所有小细节如何工作和互动?
来自:A Couple of Meta-interpreters in Prolog
与其自身实现语言类似或相同的语言的解释器称为元解释器(MI)。
了解Prolog MI是了解Prolog如何工作以及了解非常有用的MI的一种很好的方法,例如:
Use of Prolog for developing a new programming language
另一种了解统一如何工作的方法是使用统一算法和另一种语言实现的回溯,然后使用它来增强您想要查看的代码输出信息。在OCaml中有一个miniProlog,但我并不怀疑很多人都知道OCaml。
许多关于人工智能的更广泛的书籍实现了它。
Perter Norvig(Lisp)"Paradigms of Artificial Intelligence Programming"
George F Luger的"Artificial Intelligence Structures and Strategies for Complex Problem Solving"(伪代码)
Prolog实施可以在GitHub找到。 smallProlog非常简单,用C语言完成。
对于统一理论,有
中的经典"Handbook of automated reasoning"第8章
Franz Baader和Wayne Snyder的答案 1 :(得分:4)
您可以使用Byrd的盒子模型可视化重做 模拟谓词调用P有4个端口:
+-------+
--- call -->| |--- exit -->
| P |
<-- fail ---| |<-- redo ---
+-------+
通常,当每个出口都没有切口时,会有重做。并为每一个人 除了在SWI-Prolog(以及其他一些Prolog系统?)之外的某个时间,最终会有一次失败:
确定性成功通常是最后一个条款的结果 在索引花束中,可以在非调试顶级中看到 分号提示被压制。另见:
Making "deterministic success" of Prolog goals explicit
在Jekejeke Prolog中,这种“优化”尚未实施 用于调试器。它也有确定性的成功,但不是时候了 调试器打开,这就是为什么有两个不同的痕迹:
SWI-Prolog Trace:
Welcome to SWI-Prolog (threaded, 64 bits, version 7.5.8)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
?- location(X,kitchen),edible(X).
Call: (9) location(_3980, kitchen) ? creep
Exit: (9) location(apple, kitchen) ? creep
Call: (9) edible(apple) ? creep
Exit: (9) edible(apple) ? creep
X = apple
Redo: (9) location(_3980, kitchen) ? creep
Exit: (9) location(broccoli, kitchen) ? creep
Call: (9) edible(broccoli) ? creep
Fail: (9) edible(broccoli) ? creep
Redo: (9) location(_3980, kitchen) ? creep
Exit: (9) location(crackers, kitchen) ? creep
Call: (9) edible(crackers) ? creep
Exit: (9) edible(crackers) ? creep
X = crackers.
Jekejeke Prolog Trace:
Jekejeke Prolog 2, Development Environment 1.2.2
(c) 1985-2017, XLOG Technologies GmbH, Switzerland
?- location(X,kitchen),edible(X).
0 Call location(X, kitchen) ?
0 Exit location(apple, kitchen) ?
0 Call edible(apple) ?
0 Exit edible(apple) ?
X = apple ;
0 Redo edible(apple) ?
0 Fail edible(apple) ?
0 Redo location(apple, kitchen) ?
0 Exit location(broccoli, kitchen) ?
0 Call edible(broccoli) ?
0 Fail edible(broccoli) ?
0 Redo location(broccoli, kitchen) ?
0 Exit location(crackers, kitchen) ?
0 Call edible(crackers) ?
0 Exit edible(crackers) ?
X = crackers ;
0 Redo edible(crackers) ?
0 Fail edible(crackers) ?
0 Redo location(crackers, kitchen) ?
0 Fail location(X, kitchen) ?
No