【问题标题】:Guard clauses in prolog?序言中的保护条款?
【发布时间】:2012-11-25 10:44:20
【问题描述】:

它们存在吗?它们是如何实现的?

SWI-Prolog 的coroutining 谓词(freezewhendif 等)具有guards 的功能。它们如何适应首选的 Prolog 编程风格?

我对逻辑编程非常陌生(使用 Prolog 和全部),并且对它不是纯粹的声明性事实感到有些困惑,即使在非常简单的情况下也需要程序考虑(参见 question about using \== or dif)。我错过了什么重要的东西吗?

【问题讨论】:

  • 如下面的编辑“false”所指出的,“守卫”一词在这里是错误的,因为“守卫”用于表示沼泽标准precondition,例如在“如果-那么”表达式中。正确的是“受保护的暂停”。我希望。不过,我在问题中将原始表述保留为“守卫”。
  • 通过一些数学运算,您可以安全地进行 freeze/2,请参见此处:stackoverflow.com/a/35688017/502187

标签: prolog prolog-dif guard-clause prolog-coroutining


【解决方案1】:

首先是术语问题:freeze/2when/2dif/2 在任何情况下都不能称为守卫。守卫出现在CHR等扩展名中,或GHC(日文链接)或其他Concurrent logic programming languages等相关语言中;您甚至(在某些限制下)可能会考虑以下形式的子句

:-Guard, !,...

as 包含保护和剪切的子句在这种情况下称为提交。但没有一个适用于上述原语。 Guards 的灵感来自 Dijkstra 1975 年的Guarded Command Language

freeze(X, Goal)(最初称为geler)与when(nonvar(X), Goal) 相同,它们在声明上都等同于Goal。与守卫的功能没有直接关系。但是,当与 if-then-else 一起使用时,您可能会实现这样的保护。但那是完全不同的。

freeze/2 和类似的构造在一段时间内被认为是改进 Prolog 执行机制的一般方法。然而,事实证明它们使用起来非常脆弱。通常,他们过于保守,从而不必要地延迟了目标。也就是说,几乎每个有趣的查询都会产生一个“挣扎”的答案,如下面的查询。此外,终止程序和非终止程序之间的界限现在要复杂得多。对于终止的纯单调 Prolog 程序,在程序中添加一些终止目标将保留整​​个程序的终止。但是,freeze/2 不再是这种情况。然后从概念的角度来看,freeze/2 并没有得到系统顶层的很好支持:只有少数系统以全面的方式(例如 SICStus)显示了延迟目标,这对于理解成功/答案和解决方案之间的区别至关重要。对于延迟的目标,Prolog 现在可能会产生一个没有解决方案的答案:

?- 冻结(X,X = 1),冻结(X,X = 2)。 冻结(X,X=1), 冻结(X,X=2)。

freeze/2 的另一个困难是终止条件更难确定。因此,虽然 freeze 应该解决所有终止问题,但它经常会产生新问题。

还有更多与freeze/2 相关的技术困难,特别是 w.r.t 表格和其他防止循环的技术。清楚地考虑一个目标freeze(X, Y = 1)Y 现在是1,即使它还没有绑定,它仍然等待X 先绑定。现在,一个实现可能会考虑为目标g(Y) 提交表格。 g(Y) 现在要么没有解决方案,要么只有一个解决方案 Y = 1。这个结果现在将作为g/1only 解决方案存储,因为freeze-goal 对目标不直接可见。

正是由于这些原因,freeze/2 被认为是约束逻辑编程的 goto。

另一个问题是 dif/2 今天被认为是一个约束。与freeze/2 和其他协同程序原语相比,约束能够更好地管理一致性并保持更好的终止属性。这主要是因为约束引入了定义明确的语言,具体属性可以得到证明,并且已经开发了特定的算法并且不允许一般目标。然而,即使对他们来说,也有可能获得不是解决方案的答案。更多关于answer and success in CLP

【讨论】:

  • 更多的术语混乱,我担心。在 Prolog 世界之外,“守卫”是Guards:Dijkstra 使用的前提条件,一个布尔表达式,计算结果为真或假,用于以声明方式指定控制流。 GHC 和 GDC 的“守卫”和Parlog 是子句主体的一部分,它们在满足条件之前暂停执行主体目标,类似于生产系统规则头。听起来很像“freeze/2”(协程,对吗?),不像 Dijkstra。
  • @DavidTonhofer:关键是他们,非常类似于 Dijkstren 的守卫,只是 if-then 的。没有别的了。如果守卫重叠,则选择是随机/按时间顺序的回溯。所以你不能将否定表达为守卫的失败。
  • 更多关于 GHC/GDC,尤其是 "Agent-Oriented Programming - From Prolog to Guarded Definite Clauses" 的第 3 章(“变形”)中的历史,计算机科学 Springer 书中的讲义,也可以通过...其他方式获得.不过,它的编写速度相当快,并且包含许多技术错误和令人困惑的表述。还是值得的。
  • 他们不是更像“一旦……那么”吗?控制流来自天空中可用线程的大袋子(这与 Dijkstra 的守卫不同,后者具有单线程流)。等等,当在冻结时回溯时会发生什么?人们永远无法摆脱它,因为它等待的条件可能在以后仍然成为现实。还是我在这里误解了语义?我需要一份论文参考。
  • 如果,何时,......我会说研究这个方向对你没有多大帮助。 Concurrent Prolog 之类的,与 Prolog 很接近,但并不完全。目前唯一受此启发的语言是 CHR。
【解决方案2】:

freeze/2 和 when/2 就像逻辑编程的“goto”。它们不是纯的、可交换的等。

另一方面,

dif/2 是完全纯的和声明性的、单调的、可交换的等。dif/2 是一个声明性谓词,如果它的参数不同,它就成立。至于“首选的 Prolog 编程风格”:说明什么是成立的。如果你想表达两个通用术语不同的约束,dif/2 正是说明了这一点。

当您不在 Prolog 的纯声明性子集中编程时,通常最需要程序考虑,而是使用不可交换的不纯谓词等。在现代 Prolog 系统中,几乎没有理由离开纯声明性子集。

【讨论】:

  • 这里的“可交换”是什么意思?能举个例子吗?
  • 我在考虑一般情况:由于 freeze/2 和 when/2 对它们的第二个参数没有限制,例如,您甚至可以将它们用于输出,其中目标的顺序很重要。
  • 是的,约束逻辑编程。显然我们还不够分散。
  • @mat “在现代 Prolog 系统中,几乎没有理由离开纯粹的声明性子集” 一个强制性的声明,我的好伙伴。我肯定我们的解释器很少是自下而上的(也许是 Starlog?肯定是 Datalog),我们要求有副作用,以免我们陷入唯我论!
  • 始终以纯洁为目标。例如,要读取文件,请使用带有 Ulrich Neumerkel 的 library(pio) 的纯输入。要打印内容,请使用顶层的内置功能来显示解决方案。使用约束集中一个清晰的声明性描述,您可以获得更多可用于更多方向的通用程序。
【解决方案3】:

Evan Tick 有一篇论文解释 CC:

非正式地,过程调用通过匹配 主要论点(被动统一)并满足守卫目标。 当一个目标可以在一个程序中提交多个子句时,它 不确定地承诺其中一个(其他候选人 被扔掉)。出现在头部和后卫中的结构 如果相应的参数从句导致执行暂停 目标的实例化不充分。暂停的调用 当与挂起的变量关联时,可能会在稍后恢复 调用变得充分实例化。

并发逻辑编程语言的演变
埃文·蒂克 - 1995
https://core.ac.uk/download/pdf/82787481.pdf

所以我猜想通过一些 when/2 魔法,一个提交的选择代码可以 改写成普通的Prolog。该方法将是 跟随。对于同一谓词的一组提交选择规则:

H1 :- G1 | B1.
...
H2 :- Gn | Bn.

这可以改写为以下形式,其中 Hi' 和 Gi' 需要实施被动统一。例如通过使用 ISO 勘误 subsumes_term/2.

H1' :- G1', !, B1.
..
H1' :- Gn', !, Bn.
H :- term_variables(H, L), when_nonvar(L, H).

上述翻译不适用于 CHR,因为 CHR 不 抛弃候选人。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-06
    • 2011-10-06
    • 2017-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-13
    • 1970-01-01
    相关资源
    最近更新 更多