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

标签 prolog logic-programming minikanren

关闭。这个问题需要更多focused .它目前不接受答案。












想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post .

4年前关闭。



Improve this question




当我想阅读逻辑编程时,我总是偶然发现两种“主要”方法:

  • 迷你看人 ,在 The Reasoned Schemer 中引入的迷你语言由于core.logic而目前很受欢迎.
  • 序言 ,第一个“大”逻辑编程语言。

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

    最佳答案

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

    这是一个很难回答的问题,主要是因为 miniKanren 和 Prolog 的变体太多了。 miniKanren 和 Prolog 是真正的语言家族,这使得很难比较它们的功能,甚至很难比较它们在实践中的使用方式。因此,请谨慎对待我要说的一切:如果我说 Prolog 使用深度优先搜索,请注意许多 Prolog 实现支持其他搜索策略,并且备用搜索策略也可以在元数据中编码- 翻译级别。尽管如此,miniKanren 和 Prolog 有不同的设计理念,并做出不同的权衡。

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

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

    在改进 Prolog 实现方面付出了巨大的努力,其中大部分都基于 Warren Abstract Machine (WAM)。 WAM 使用副作用模型,其中值被破坏性地分配给逻辑变量,这些副作用在回溯时被撤销。通过扩展 WAM 的指令,可以将许多功能添加到 Prolog。这种方法的一个缺点是,如果没有对 WAM 的深刻理解,Prolog 实现论文可能难以阅读。另一方面,Prolog 实现者有一个共同的模型来讨论实现问题。对并行 Prolog 进行了大量研究,并在 1990 年代在安道尔 Prolog 中达到高潮。至少其中一些想法存在于 Ciao Prolog 中。 (Ciao Prolog 充满了有趣的想法,其中很多都远远超出了 Prolog 的标准。)

    Prolog 有一个漂亮的基于统一的“模式匹配”风格的语法,可以生成非常简洁的程序。 Prologers 喜欢他们的语法,就像 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 的标准实现不包含突变或其他副作用,只有一个异常(exception):一些版本的 miniKanren 使用指针相等来比较逻辑变量。我认为这是一个“良性效果”,尽管许多实现通过在实现中传递一个计数器来避免这种效果。也没有全局事实数据库。 miniKanren 的实现哲学受到函数式编程的启发:应该避免变异和效果,并且所有语言构造都应该尊重词法范围。如果您仔细查看实现,您甚至可能会发现几个 monad。搜索实现基于组合和操作惰性流,再次不使用变异。这些实现选择导致与 Prolog 中非常不同的权衡。在 Prolog 中,变量查找是常数时间,但回溯需要撤消副作用。在 miniKanren 中,变量查找更昂贵,但回溯是“免费的”。事实上,由于流的处理方式,miniKanren 中没有回溯。

    miniKanren 实现的一个有趣方面是代码本质上是线程安全的,并且——至少在理论上——可以简单地并行化。当然,并行化代码而不使其变慢并非易事,因为必须为每个线程或进程提供足够的工作来弥补并行化的开销。尽管如此,这是 miniKanren 实现的一个领域,我希望能得到更多的关注和实验。

    miniKanren 使用出现检查进行统一,并使用完整的交错搜索而不是深度优先搜索。交错搜索比深度优先搜索使用更多的内存,但在深度优先搜索将永远发散/循环的某些情况下可以找到答案。 miniKanren 确实支持一些额外的逻辑运算符--- conda , condu , 和 project ,例如。 condacondu可以用来模拟Prolog的cut,project可用于获取与逻辑变量关联的值。
    conda的存在, condu , 和 project ---以及轻松修改搜索策略的能力---允许程序员使用 miniKanren 作为嵌入式 Prolog 类语言。对于 Clojure 的“core.logic”的用户来说尤其如此,其中包括许多类似 Prolog 的扩展。 miniKanren的这种“务实”使用似乎占了miniKanren在工业中使用的大部分。想要将基于知识的推理系统添加到用 Clojure、Python 或 JavaScript 编写的现有应用程序的程序员通常对在 Prolog 中重写他们的整个应用程序不感兴趣。在 Clojure 或 Python 中嵌入一种小型逻辑编程语言更具吸引力。一个嵌入式 Prolog 实现大概也能达到这个目的。我怀疑 miniKanren 作为一种嵌入式逻辑语言已经变得流行,因为它的核心实现很小而且很纯,以及自“The Reasoned Schemer”出版以来出现的演讲、博客文章、教程和其他教育 Material 。

    除了使用 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) ,这将产生无限多个列表的三元组 X , Y , 和 Z使得附加 XY生产 Z .
    append的这个关系版本可以很容易地用 Prolog 表达,并且确实在许多 Prolog 教程中都有展示。在实践中,更复杂的 Prolog 程序往往至少使用一些额外的逻辑特征,例如 cut,这抑制了将结果程序视为关系的能力。相比之下,miniKanren 被明确设计为支持这种关系编程风格。最新版本的 miniKanren 支持符号约束求解( symbolonumberoabsento 、不等式约束、名义逻辑编程),以便更轻松地将非平凡程序编写为关系。在实践中,我从不使用 miniKanren 的任何超逻辑功能,并且我将所有 miniKanren 程序编写为关系。最有趣的关系程序是 Scheme 子集的关系解释器。这些解释器有很多有趣的能力,比如生成一百万个评估到列表 (I love you) 的 Scheme 程序。 ,或简单地生成 quines(对自身进行评估的程序)。

    miniKanren 进行了许多权衡以启用这种关系式编程风格,这与 Prolog 所做的权衡非常不同。随着时间的推移,迷你看人添加了更多符号约束,真正成为面向符号的约束逻辑编程语言。在许多情况下,这些符号约束使得避免使用像 condu 这样的额外逻辑运算符变得切实可行。和 project .在其他情况下,这些符号约束是不够的。更好地支持符号约束是 miniKanren 研究的一个活跃领域,以及如何将更大、更复杂的程序编写为关系的更广泛问题。

    总之,miniKanren 和 Prolog 都有有趣的特性、实现和用途,我认为值得从这两种语言中学习思想。还有其他非常有趣的逻辑编程语言,例如 Mercury、Curry 和 Gödel,每种语言都有自己的逻辑编程语言。

    我将以一些迷你看人资源结束:

    主要迷你看人网站:
    http://minikanren.org/

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

    干杯,

    --威尔

    关于prolog - 在逻辑编程方面,Prolog 和 miniKanren 之间的主要技术区别是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28467011/

    相关文章:

    prolog - 从歧义语法转换为明确语法

    prolog - CLP:对结构化变量的约束?

    clojure - 迷你看人、core.logic、clojure : Reasoned Scheme Exercise 60

    list - A U B U C的序言联盟

    list - prolog 中的配方函数

    prolog - 逻辑编程和自动定理证明之间的区别

    programming-languages - Erlang 中非短路 bool 运算符的用途是什么?

    prolog - 逻辑编程中如何处理重复更新?

    scheme - minikanren 中的特征结构统一