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


123

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

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


3
遗憾地看到这个问题关闭。正如非常有力的答案和大量投票所表明的,这是一个非常有用的问题。我投票决定重新开放
。...– nealmcb

@nealmcb问题曾经是很多支持的话题,现在不再可能了,支持的数量不是定义它是否有效的原因。
Tiago Martins Peres李大仁19/12/24

Answers:


280

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

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

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

Prolog支持许多“额外逻辑”或“非逻辑”功能,包括cut assert和and retract变量的投影,以便使用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具有漂亮的基于统一的“模式匹配”样式的语法,从而导致程序非常简洁。序言者喜欢他们的语法,就像利珀斯喜欢他们的s表达式一样。Prolog还具有大量的标准谓词库。由于使WAM快速运行的所有工程技术,因此有非常强大且成熟的Prolog实现。结果,许多大型的基于知识的系统已完全用Prolog编写。

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

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

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

miniKanren使用出现检查进行统一,并使用完整的交织搜索而不是深度优先搜索。交错搜索比深度优先搜索使用更多的内存,但是在深度优先搜索将永远发散/循环的某些情况下,可以找到答案。miniKanren 支持一些额外的逻辑操作符- condacondu以及project,例如。 condacondu可用于模拟的Prolog的切口,并且project可以被用来获得与一个逻辑变量相关联的值。

的存在下condaconduproject---以及轻松修改搜索策略的能力---允许程序员使用miniKanren作为类似于Prolog的嵌入式语言。对于Clojure的'core.logic'用户而言尤其如此,其中包括许多类似于Prolog的扩展。miniKanren的这种“实用”用法似乎占miniKanren在工业中的大多数使用。希望将基于知识的推理系统添加到用Clojure或Python或JavaScript编写的现有应用程序中的程序员通常对用Prolog重写整个应用程序不感兴趣。在Clojure或Python中嵌入小型逻辑编程语言更具吸引力。大概,为此目的,嵌入式Prolog实现也将很好地工作。

除了将miniKanren用作与Prolog精神相似的实用嵌入式逻辑编程语言外,miniKanren还被用于“关系”编程中的研究。也就是说,在编写程序时,它们表现为数学关系而不是数学函数。例如,在Scheme中,该append函数可以追加两个列表,并返回一个新列表:函数调用(append '(a b c) '(d e))返回list (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这样追加XY生产Z

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

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

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

我将以一些miniKanren资源结尾:

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

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

干杯,

- 将


9
对不起,如果我现在被吓死了。我刚刚开始了基于逻辑和基于约束的编程的第一个思想实验,这就是我得到的答复。:)实际上,正如您在回答中提到的那样,我也很怀疑逻辑计算是实现为Monad的理想选择。事实证明,它更像是MonadPlus,而您的同事Friedman 确实有论文和参考实现!因此,我正在阅读并开始使用它,对此有任何想法吗?
Profpatsch

4
我怀疑您还会发现microKanren论文和代码有趣:webyrd.net/scheme-2013/papers/HemannMuKanren2013.pdfgithub.com/jasonhemann/microKanren
William E. Byrd

5
此外,我每周一次在东部标准时间周日下午3点(格林尼治标准时间-5:00)组织有关Google Hangouts的miniKanren课程。如果您想加入我们,我总是在我的@webyrd Twitter帐户上发布该链接。先前录制的视频群聊位于:youtube.com/playlist?list=PLO4TbomOdn2cks2n5PvifialL8kQwt0aW
William E. Byrd

2
我认为它与'05论文中的搜索词基本相同。另外,请参见Seres和Spivey的“在Haskell中嵌入序言”:spivey.oriel.ox.ac.uk/~mike/silvija/seres_haskell99.pdf
William E. Byrd

1
@ WilliamE.Byrd-很棒的答案!假设有一个,可以嵌入到C / C ++程序中的最佳miniKanren实现是什么?另外,miniKanren是否具有Prolog的生成性质?就是说,在程序声明的当前关系给定的情况下,将变量留在表达式中的能力以及核心引擎是否会为该变量提供所有可能的值?
罗伯特·奥施勒

4

暂定答案:

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


3
这两个引用与Kanren或MiniKanren有什么关系?

2
看到最后一个问题:“它们来自数学的哪些分支,其理论基础是什么?”
弗兰克·希勒
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.