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

当我想阅读逻辑编程时,我总是绊倒现在做的两种“主要”方式:

  • miniKanren ,在The Reasoned Schemer中引入的一种微型语言 ,由于core.logic而受欢迎 。
  • Prolog ,第一个“大”的逻辑编程语言。

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

首先,请允许我恭维你的好pw0n1e图标。

这个问题很难回答,主要是因为miniKanren和Prolog有很多变种。 miniKanren和Prolog实际上是语言的家族,这使得难以比较它们的特征,甚至难以在实践中使用它们。 因此,请谨慎对待我所说的一切:如果我说Prolog使用深度优先search,请注意许多Prolog实现支持其他search策略,并且也可以在元 – 解释器级别。 不过,miniKanren和Prolog有不同的devise理念,并做出不同的折衷。

Prolog是象征性人工智能编程的两种经典语言之一(另一种经典语言是Lisp)。 Prolog擅长实施以一阶逻辑编码声明性知识的符号规则系统。 该语言针对这些types的应用程序的performance力和效率进行了优化,有时以牺牲逻辑纯度为代价。 例如,默认情况下,Prolog不会在统一中使用“发生检查”。 从math/逻辑的angular度来看,这个统一版本是不正确的。 然而,发生检查是昂贵的,并且在大多数情况下缺乏发生检查不是问题。 这是一个非常实用的devise决策,Prolog使用深度优先search,并使用cut( ! )来控制回溯。 我敢肯定,这些决定在20世纪70年代的硬件上运行时是绝对必要的,今天在处理大问题和处理巨大(通常是无限的)search空间时非常有用。

Prolog支持许多“非逻辑”或“非逻辑”特性,包括剪切, assert和回retract ,用于算术运算的variables投影等等。 这些function中的许多function使得更容易expression复杂的控制stream程,并操纵Prolog的事实全局数据库。 Prolog的一个非常有趣的function是Prolog代码本身存储在事实的全局数据库中,可以在运行时查询。 这使得编写元语言解释器来修改Prolog代码的行为是很简单的。 例如,可以使用改变search顺序的元解释器在Prolog中对广度优先search进行编码。 这是一个非常强大的技术,在Prolog世界以外是不为人知的。 “序言艺术”详细描述了这一技术。

巨大的努力已经在改进Prolog实现,其中大部分是基于沃伦抽象机器(WAM)。 WAM使用一个副作用模型,其中的值被破坏性地分配给逻辑variables,这些副作用在回溯时被撤消。 通过扩展WAM的指令可以将许多function添加到Prolog中。 这种方法的一个缺点是,如果没有对WAM的深入理解,Prolog的实现文件就很难被阅读。 另一方面,Prolog实现者有一个共同的模型来讨论实现问题。 并行Prolog已经进行了大量的研究,最终在20世纪90年代达到了安道尔Prolog的水平。 这些想法中至less有一些是在Ciao Prolog中生存的。 (Ciao Prolog充满了有趣的想法,其中许多超出了Prolog标准。)

Prolog有一个美丽的统一为基础的“模式匹配”式的语法,导致非常简洁的程序。 Prologers喜欢他们的语法,就像Lispers喜欢他们的sexpression式一样。 Prolog也有一个大型的标准谓词库。 由于所有的工程已经进入了快速的WAM,有非常有能力和成熟的Prolog实现。 因此,许多大型的基于知识的系统完全是在Prolog中编写的。

miniKanren被devise成一个最小的逻辑编程语言,具有一个小的,易于理解的,易于开发的实现。 miniKanren最初被embedded到Scheme中,并且在过去的十年中已经被移植到其他几十种主机语言。 最受欢迎的miniKanren实现是Clojure中的'core.logic',现在有许多类似Prolog的扩展和一些优化。 最近,miniKanren实现的核心进一步被简化,形成了一个叫做“微观人”的微型“微内核”。 miniKanren可以在这个microKanren核心上实现。 将microKanren或miniKanren移植到新的宿主语言已成为程序员学习miniKanren的标准练习。 因此,大多数stream行的高级语言至less有一个miniKanren或microKanren实现。

miniKanren和microKanren的标准实现不包含突变或其他副作用,只有一个例外:某些版本的miniKanren使用指针相等来比较逻辑variables。 我认为这是一个“良性的效果”,尽pipe很多实现都通过实施来避免这种影响。 也没有全球事实数据库。 miniKanren的实现哲学受函数式编程的启发:应该避免变异和效应,所有的语言结构都应该尊重词法范围。 如果仔细观察执行情况,您甚至可能会发现一些单子。 search实现基于组合和操纵惰性stream,再次不使用突变。 这些实现select导致了与Prolog不同的折衷。 在Prolog中,variables查找是恒定的,但是回溯需要消除副作用。 在miniKanrenvariables查找是更昂贵的,但回溯是“自由”。 事实上,由于stream是如何处理的,所以miniKanren没有回溯。

miniKanren实现的一个有趣的方面是代码本质上是线程安全的,至less在理论上是平行的。 当然,如果每个线程或进程都必须有足够的工作来弥补并行化的开销,那么并行化代码的速度并不 。 不过,这是miniKanren实施的一个领域,我希望能够得到更多的关注和试验。

miniKanren使用发生检查统一,并使用完整的交叉search,而不是深度优先search。 交错search比深度优先search使用更多的内存,但在某些情况下可以find答案,其中深度优先search将永远发散/循环。 miniKanren支持一些额外的逻辑运算符,例如conduconduprojectconducondu可以用来模拟Prolog的切割, project可以用来获得与逻辑variables相关联的值。

conduconduproject的存在—以及轻松修改search策略的能力—允许程序员使用miniKanren作为embedded式Prolog类语言。 对于Clojure的“core.logic”用户尤其如此,其中包含许多类似Prolog的扩展。 miniKanren的这种“实用”的使用似乎占MiniKanren在工业中的大部分使用。 希望将基于知识的推理系统添加到用Clojure或Python或JavaScript编写的现有应用程序的程序员通常不希望在Prolog中重写他们的整个应用程序。 在Clojure或Python中embedded一个小的逻辑编程语言更吸引人。 据推测,embedded式Prolog实现同样适用于此目的。 我怀疑miniKanren作为一种embedded式的逻辑语言已经变得stream行起来,因为它的核心实现方式很细小,还有自“理性图式”出版以来出版的讲座,博客,教程和其他教材。

除了使用miniKanren作为实用的embedded式逻辑编程语言,与Prolog相似,miniKanren被用于“关系”编程的研究。 也就是说,在书写那些performance为math关系而不是math函数的程序。 例如,在Scheme中, append函数可以附加两个列表,返回一个新列表:函数调用(append '(abc) '(de))返回列表(abcde) 。 但是,我们也可以把append当作三位关系而不是两个参数的函数。 调用(appendo '(abc) '(de) Z)然后将逻辑variablesZ与列表(abcde)相关联。 当然,当我们把逻辑variables放在其他位置时,事情会变得更有趣。 调用(appendo X '(de) '(abcde)) X(abc) (appendo X '(de) '(abcde))相关联,而调用(appendo XY '(abcde)) XY与成对的列表相关联, (abcde) 。 例如, X = (ab)Y = (cde)就是这样的一对值。 我们还可以编写(appendo XYZ) ,这将产生列表XYZ无限多个三元组,使得将X附加到Y产生Z

这个append关系版本可以很容易地用Prolog来表示,而且在Prolog的很多教程中都有介绍。 在实践中,更复杂的Prolog程序倾向于使用至less一些额外的逻辑特征,例如剪切,这会抑制将结果程序视为关系的能力。 相比之下,miniKanren明确地被devise来支持这种风格的关系编程。 最近版本的miniKanren支持符号约束求解( symbolosymbolonumberoabsento约束,名义逻辑程序devise),使得把非重要的程序写成关系更容易。 在实践中,我从来没有使用过任何miniKanren的逻辑外特征,而且我把所有的迷你Kanan程序写成关系。 最有趣的关系程序是Scheme的一个子集的关系解释器。 这些口译员有很多有趣的能力,比如产生一百万个计划程序,评估列表(I love you) ,或者生成一个简单的程序(对自己进行评估的程序)。

miniKanren进行了一些权衡,以实现这种关系式编程风格,这与Prolog所做的权衡是非常不同的。 随着时间的推移,miniKanren增加了更多的符号约束,真正成为符号化的约束逻辑编程语言。 在许多情况下,这些符号约束使得避免使用像conduproject这样的逻辑condu算符是condu 。 在其他情况下,这些符号限制是不够的。 对象征性约束的更好的支持是miniKanren研究的一个活跃领域,同时也是如何将更大更复杂的程序写成关系的更广泛的问题。

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

我将以一些miniKanren资源结束:

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

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

干杯,

– 将

暂定答案:

AFAIK“The Reasoned Schemer”以Scheme-y语法和函数式编程风格介绍了基本的逻辑编程,特别是将常量目标“#u”(失败)和“#s”(成功)join到布尔值“#t “和”#f“。 它使用与Prolog相同的方法来进行逻辑编程:统一和回溯search。 我会看看我周末是否有时间从书架上取回那本书。 math的分支是一种限制forms的一阶逻辑,在这种情况下,angular函数的条款和决议理由。 请参阅: 计算逻辑:过去的记忆和对未来的挑战 John Alan Robinson和Robert Kowalski 的早期逻辑编程为冷启动。