在逻辑编程方面,Prolog和miniKanren之间的主要技术区别是什么?

What are the main technical differences between Prolog and miniKanren, with respect to logic programming?

当我想阅读逻辑编程时,时下我总是会遇到两种"主要"方法:

  • miniKanren,在The Reasoned Schemer中引入的一种迷你语言,由于core.logic的缘故,目前很受欢迎。
  • Prolog,第一种"大"逻辑编程语言。

我现在感兴趣的是:两者之间的主要技术区别是什么? 它们在方法和实现上是否非常相似,还是对逻辑编程采用完全不同的方法? 它们来自哪些数学分支?其理论基础是什么?


首先,请允许我赞美您的pw0n1e图标。

好。

这是一个棘手的问题,主要是因为miniKanren和Prolog都有很多变体。 miniKanren和Prolog实际上是语言家族,这使得很难比较它们的功能,甚至很难比较它们在实践中的用法。因此,请谨慎处理我要说的一切:如果我说Prolog使用深度优先搜索,请注意,许多Prolog实现都支持其他搜索策略,并且其他搜索策略也可以在meta处进行编码。 -解释器级别。 miniKanren和Prolog仍然有不同的设计理念,并做出了不同的取舍。

好。

Prolog是用于符号人工智能编程的两种经典语言之一(另一种经典语言是Lisp)。 Prolog擅长实现基于符号规则的系统,其中声明性知识以一阶逻辑编码。该语言针对这些类型的应用程序的表达性和效率进行了优化,有时会牺牲逻辑上的纯正性。例如,默认情况下,Prolog不统一使用"出现检查"。从数学/逻辑的角度来看,此版本的统一是不正确的。但是,发生检查很昂贵,并且在大多数情况下,缺少发生检查不是问题。这是一个非常务实的设计决策,Prolog使用深度优先搜索以及使用cut(!)来控制回溯也是如此。我确信这些决定在1970年代的硬件上运行时绝对必要,而今天在处理大问题以及处理巨大(通常是无限的!)搜索空间时非常有用。

好。

Prolog支持许多"额外逻辑"或"非逻辑"功能,包括剪切,assertretract,用于使用is进行算术运算的变量投影等。这些功能中的许多功能使表达复杂的控制流程和操作Prolog的全局事实数据库变得更加容易。 Prolog的一个非常有趣的功能是Prolog代码本身存储在事实的全局数据库中,并且可以在运行时进行查询。这使得编写修改解释中的Prolog代码行为的元解释器变得微不足道。例如,可以使用更改搜索顺序的元解释器在Prolog中对广度优先搜索进行编码。这是一种非常强大的技术,在Prolog世界之外尚不为人所知。"序言的艺术"详细介绍了此技术。

好。

改进Prolog的实现已付出了巨大的努力,其中大多数基于Warren Abstract Machine(WAM)。 WAM使用一个副作用模型,在该模型中,将值破坏性地分配给逻辑变量,而这些副作用在回溯时将被撤消。通过扩展WAM的说明,可以将许多功能添加到Prolog中。这种方法的一个缺点是,如果没有对WAM的深入了解,可能很难阅读Prolog实施文件。另一方面,Prolog实现者具有讨论实现问题的通用模型。在并行的Prolog中进行了大量的研究,最终在1990年代的Andorra Prolog中达到顶峰。这些想法中至少有一些存在于Ciao Prolog中。 (Ciao Prolog充满了有趣的想法,其中许多远远超出了Prolog的标准。)

好。

Prolog具有漂亮的基于统一的"模式匹配"样式的语法,从而导致程序非常简洁。序言者喜欢他们的语法,就像Lispers喜欢他们的S表达式一样。 Prolog还具有大量的标准谓词库。由于使WAM快速运行的所有工程技术,因此有非常强大且成熟的Prolog实现。结果,许多大型的基于知识的系统已完全用Prolog编写。

好。

miniKanren被设计为一种最小的逻辑编程语言,具有一个小型,易于理解且易于破解的实现。 miniKanren最初嵌入在Scheme中,并在过去十年中已移植到其他数十种宿主语言中。最受欢迎的miniKanren实现是Clojure中的" core.logic",它现在具有许多类似于Prolog的扩展和许多优化。最近,miniKanren实现的核心得到了进一步简化,从而产生了一个名为" microKanren"的微型"微内核"。然后,可以在此microKanren核心之上实施miniKanren。将microKanren或miniKanren移植到新的宿主语言已成为学习miniKanren的程序员的标准练习。结果,大多数流行的高级语言至少具有一种miniKanren或microKanren实现。

好。

miniKanren和microKanren的标准实现不包含任何突变或其他副作用,唯一的例外是:某些miniKanren版本使用指针相等性来比较逻辑变量。我认为这是"良性效果",尽管许多实现甚至通过在实现中传递计数器来避免这种效果。也没有全局事实数据库。 miniKanren的实现哲学受到函数式编程的启发:应避免突变和影响,所有语言构造应遵循词汇范围。如果仔细看一下实现,您甚至可能会发现几个monad。搜索实现基于合并和处理惰性流,再次不使用任何突变。这些实现选择导致的权衡与Prolog不同。在Prolog中,变量查找是固定时间,但是回溯需要消除副作用。在miniKanren中,变量查找更为昂贵,但回溯是"免费的"。实际上,由于如何处理流,miniKanren中没有回溯。

好。

miniKanren实现的一个有趣的方面是,该代码本质上是线程安全的,并且-至少在理论上-可以并行化。当然,考虑到必须给每个线程或进程足够的工作来弥补并行化的开销,并行化代码而不降低速度并非易事。尽管如此,这还是miniKanren实施的一个领域,我希望它将得到更多关注和试验。

好。

miniKanren使用发生检查进行统一,并使用完整的交织搜索而不是深度优先搜索。交错搜索比深度优先搜索使用更多的内存,但是在深度优先搜索将永远发散/循环的某些情况下,可以找到答案。 miniKanren确实支持一些额外的逻辑运算符,例如condaconduprojectcondacondu可用于模拟Prolog的切割,而project可用于获取与逻辑变量关联的值。

好。

condaconduproject-的存在-以及轻松修改搜索策略的能力-允许程序员使用miniKanren作为类似于Prolog的嵌入式语言。对于Clojure'core.logic'的用户而言尤其如此,其中包括许多类似于Prolog的扩展。 miniKanren的这种"实用"用法似乎占miniKanren在工业中的大多数使用。希望将基于知识的推理系统添加到用Clojure或Python或JavaScript编写的现有应用程序中的程序员通常对用Prolog重写整个应用程序不感兴趣。在Clojure或Python中嵌入小型逻辑编程语言更具吸引力。大概,嵌入式Prolog实现也可以达到此目的。我怀疑miniKanren由于其微小而纯净的内核实现以及自"推理的策划人"发布以来出现的讲座,博客文章,教程和其他教育材料而成为一种流行的嵌入式逻辑语言。

好。

除了将miniKanren用作与Prolog精神相似的实用嵌入式逻辑编程语言外,miniKanren还被用于"关系"编程中的研究。就是说,在编写程序时表现为数学关系而不是数学函数。例如,在Scheme中,append函数可以追加两个列表,并返回新列表:函数调用(append '(a b c) '(d e))返回列表(a b c d e)。但是,我们也可以将append视为三位关系而不是二元函数。然后,调用(appendo '(a b c) '(d e) Z)将逻辑变量Z与列表(a b c d e)关联。当然,当我们将逻辑变量放在其他位置时,事情会变得更加有趣。调用(appendo X '(d e) '(a b c d e))X(a b c)关联,而调用(appendo X Y '(a b c d e))XY与列表对关联,这些列表对在添加时等于(a b c d e)。例如,X = (a b)Y = (c d e)是一对这样的值。我们还可以编写(appendo X Y Z),它将产生无限多个列表XYZ的三元组,以便将X附加到Y会生成Z

好。

append的这种关系版本可以在Prolog中轻松表达,并且实际上在许多Prolog教程中都已显示。在实践中,更复杂的Prolog程序倾向于至少使用一些额外的逻辑功能,例如cut,这会限制将生成的程序视为关联的能力。相反,miniKanren专门设计为支持这种类型的关系编程。 miniKanren的最新版本支持符号约束求解(symbolonumberoabsento,不等式约束,标称逻辑编程),以使将非平凡程序编写为关系变得更容易。在实践中,我从不使用miniKanren的任何逻辑外功能,而是将所有miniKanren程序编写为关系。最有趣的关系程序是Scheme子集的关系解释器。这些解释器具有许多有趣的功能,例如生成一百万个对列表(I love you)求值的Scheme程序,或琐碎生成quines(对自己求值的程序)。

好。

miniKanren进行了一些权衡以实现这种关系编程风格,这与Prolog进行的权衡非常不同。随着时间的流逝,miniKanren增加了更多的符号约束,实际上成为了一种面向符号的约束逻辑编程语言。在许多情况下,使用这些符号约束可以避免使用诸如conduproject之类的逻辑运算符。在其他情况下,这些符号约束是不够的。更好地支持符号约束是miniKanren研究的一个活跃领域,也是一个更广泛的问题,即如何编写更大和更复杂的程序作为关系。

好。

简而言之,miniKanren和Prolog都具有有趣的功能,实现和用法,我认为值得从这两种语言中学习思想。还有其他非常有趣的逻辑编程语言,例如Mercury,Curry和G?del,每种语言都有自己的逻辑编程语言。

好。

我将以一些miniKanren资源结尾:

好。

miniKanren主要网站:
http://minikanren.org/

好。

我对关系编程和miniKanren进行了一次采访,其中包括与Prolog的比较:
http://www.infoq.com/interviews/byrd-relational-programming-minikanren

好。

干杯,

好。

- 将

好。

好。


暂定答案:

AFAIK,"理性的计划者"以Scheme-y语法和函数式编程风格介绍了基本逻辑编程,特别是将常量目标" #u"(失败)和" #s"(推导)添加到布尔值" #t"中"和" #f"。 它使用与Prolog相同的逻辑编程方法:统一和回溯搜索。 我将看看周末是否有时间从书架上取回那本书。 数学的分支是一种受限形式的一阶逻辑,在这种情况下为Horn子句,而其分辨率为Unfication。 请参阅:计算逻辑:过去的回忆
约翰·艾伦·罗宾逊(John Alan Robinson)撰写的《对未来的挑战》和《罗伯特·科瓦尔斯基(Robert Kowalski)的逻辑编程的早期》为冷门起步。