【问题标题】:Attributed variables: library interfaces / implementations / portability属性变量:库接口/实现/可移植性
【发布时间】:2015-04-21 15:37:16
【问题描述】:

最近在浏览一些与相关的问题时,偶然发现this answer by @matHow to represent directed cyclic graph in Prolog with direct access to neighbour verticies提问。

到目前为止,我个人在 Prolog 中使用属性变量的经验非常有限。但是@mat 给出的用例引起了我的兴趣。所以我尝试用它来回答另一个问题,ordering lists with constraint logic programming

首先,好消息:我第一次使用属性变量的结果如我所愿。

然后,不太好的消息:当我通过答案发布时,我意识到 Prolog 中有几个 API 和属性变量的实现。

我觉得我在这里不知所措......我特别想知道以下内容:

  • 广泛使用哪些 API?到目前为止,我找到了两个:SICStus 和 SWI。
  • 不同的属性变量实现提供了哪些功能?一样的吗?还是一个包含另一个?
  • 语义上有区别吗?
  • 实际执行情况如何?有些比其他的更有效吗?
  • 使用属性变量是否会(或是否)存在可移植性问题?

这里有很多问号...请分享您的经验/立场? 提前谢谢!


编辑 2015-04-22

这是上面提到的answer的代码sn-p:

init_att_var(X,Z) :-
    put_attr(Z,value,X).

get_att_value(Var,Value) :-
    get_attr(Var,value,Value).

到目前为止,我“只”使用 put_attr/3 and get_attr/3,但是——根据 SICStus Prolog 关于属性变量的文档——SICStus 提供 put_attr/2 and get_attr/2

所以即使是这个非常浅的用例 需要一些仿真层(一种或另一种)。

【问题讨论】:

  • 请不要忘记用户的观点。也就是说,只使用约束的人! call_residue_vars/2 是最重要的。
  • ...和copy_term/3

标签: prolog prolog


【解决方案1】:

我想重点谈谈我在为属性变量使用不同接口时注意到的一个重要的一般点:在为属性变量设计接口时,实现者还应牢记以下几点:

  • 在推理同时统一时是否可以考虑属性,例如[X,Y] = [0,1]

这在例如 SICStus Prolog 中是可能的,因为在调用 verify_attributes/3 之前,此类绑定已撤消。在 hProlog 提供的接口中(attr_unify_hook/2,在统一之后调用 并且所有绑定都已经到位)在推理时很难考虑Y 的(以前的)属性在attr_unify_hook/2 中统一X,因为此时Y 不再是变量!这对于可以仅根据基本值做出决策的求解器来说可能就足够了,但对于需要额外数据(通常存储在属性中)来查看统一是否应该成功以及随后不再容易获得的求解器来说,这是一个严重的限制.一个明显的例子:布尔统一与决策图。

截至 2016 年,SWI-Prolog 的 verify-attributes branch 也支持 verify_attributes/3,这要感谢 Douglas Miles 的出色实施工作。该分支已准备好进行测试,并打算在它正确有效地工作后立即合并到 master 中。为了与 hProlog 兼容,该分支还支持 attr_unify_hook/2:它通过在编译时将此类定义重写为更通用的 verify_attributes/3 来实现。

在性能方面,很明显verify_attributes/3 可能存在缺点,因为同时使多个变量接地可能会让您更快地看到(在attr_unify_hook/2 中)统一无法成功。但是,我很乐意随时将这种通常可以忽略不计的优势换成更通用的界面为您提供的更高的可靠性、易用性和更多的功能,并且无论如何这已经是 SICStus Prolog 中最重要的标准行为它的一般性也是更快的 Prolog 系统之一。

SICStus Prolog 还具有一个重要的谓词project_attributes/2:顶层使用它来投影查询变量的约束。 SWI-Prolog 在最近的版本中也支持这一点。

SWI 界面还有一个巨大的优势:attribute_goals//1 和因此copy_term/3 给您的剩余目标始终是一个列表。这有助于用户避免代码中的默认值,并鼓励使用更具声明性的界面,因为纯约束目标列表不能包含控制结构

有趣的是,除了语法之外,这两个界面都不允许您解释统一。就个人而言,我认为在某些情况下,您可能希望以不同于句法的方式解释统一,但是,也可能有很好的反对理由。

属性变量的其他接口谓词大多很容易与不同系统的简单包装谓词互换。

【讨论】:

  • 颇具讽刺意味的是,SICStus 界面中被提及的特性在 Udine 举行的 ICLP 2008 上被称为 fat
  • 你能确认 YAP 和 SWI 有同样的缺点吗?
  • 最近 SWI 的变化现在实现了这一点吗? - 请更新你的答案,以防万一。
【解决方案2】:

Jekejeke Minlog 具有无状态或 thin 属性变量。不完全是,一个属性变量可以有零个、一个或多个钩子,它们可以是闭包,因此可以携带一些状态。

但通常情况下,实现会管理 elsewere 状态。为了这 Jekejeke Minlog 允许从变量创建引用类型, 以便它们可以用作表的索引。

如果结合尾随和/或 前向链接。作为一个例子,我们已经实现了 CLP(FD)。还有一个小求解器教程。

在我们的例子中,原语ingredients 是:

1) 无状态属性变量
2) 尾随键和可变键
3) 继续队列

属性变量钩子可能对扩展延续队列有绑定效果,但只执行一次。来自延续队列的目标可能是不确定的。

在实现应用程序之前还有一些额外的层,它们主要是基元的聚合,用于临时进行更改。

目前主要的应用是开源的herehere

a) 有限域约束求解器
b) Herbrand 约束
c) 目标暂停

再见

【讨论】:

  • 编辑:自 1.1.2 版以来,Jekejeke Prolog 还有一个延续队列,允许实现诸如 freeze/2 之类的谓词。所以帖子中有一个新的条目 3) 和一个新的示例应用程序 c)。
【解决方案3】:

属性变量库的另一个观点是每个模块可以定义多少个属性。对于 SWI-Prolog/YAP 并引用 SWI 文档:

每个属性都关联到一个模块,而钩子 (attr_unify_hook/2) 在这个模块中执行。

这对于 CLP(FD) 等库的实现者来说是一个严重的限制,因为它强制使用附加模块的唯一目的是拥有多个属性,而不是能够在实现其库的模块中定义尽可能多的属性。 SICStus Prolog 接口不存在此限制,该接口提供指令attribute/1,允许每个模块声明任意数量的属性。

【讨论】:

  • 不完全是一个严重的限制。将许多小属性实现为单个每个模块属性的参数非常简单。
  • @jschimpf 是的,但这种解决方法远非理想。你从属性名称到整数。您不需要直接访问属性值,而是需要访问超级属性值、复合术语,然后使用其位置而不是属性名称访问其参数之一。删除一个属性可能意味着重新洗牌其他属性。此类更改将需要传播到该大型属性的任何处理程序。
【解决方案4】:

您可以在 ECLiPSe 中找到最古老、最精细的属性变量实现之一,它构成了实现约束求解器的更广泛基础架构的一部分。

这种设计的主要特点是:

  • 必须声明属性,作为回报,编译器支持高效访问
  • 属性变量的语法,以便它们可以被读取和写入
  • 更完整的属性操作处理程序集,因此属性不仅可以用于统一,还可以用于其他通用操作,例如术语复制和包含测试
  • 明确区分可变属性和暂停目标的概念
  • 在十几个 ECLiPSe 的库中使用

This paper (section 4) 和 ECLiPSe 文档有更多详细信息。

【讨论】:

  • @false 他写的是“最古老的”,而不是“最古老的”。
  • 这些属性变量可以读写。在将 Prolog 文本作为子句的一部分进行咨询时,它们是否也可以被阅读?这个子句可以按预期实例化/使用吗?
猜你喜欢
  • 1970-01-01
  • 2014-08-30
  • 1970-01-01
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-11
相关资源
最近更新 更多