prolog中的哈希表
Posted
技术标签:
【中文标题】prolog中的哈希表【英文标题】:Hash tables in prolog 【发布时间】:2010-11-21 20:38:17 【问题描述】:前几天我在 prolog 中解决了一个难题,并意识到如果我使用另一种编程语言,我会使用哈希表/字典,但据我所知,这在 prolog 中是不可能的。
所以我的第一个问题是,是否有任何 prolog 支持具有哈希表性能特征的类字典数据结构?
其次,我想到,由于大多数 prolog 使用哈希表来存储谓词,我可以编写一个包装谓词来断言和收回事实,创建一个字典接口,该接口将利用谓词的底层哈希表。但是我会得到哈希表的性能特征,还是接口会增加会降低性能的开销?
【问题讨论】:
【参考方案1】:一些 Prolog 环境具有关联列表,可用于创建和编辑字典:
SWI-Prolog SICStus Prolog编辑:
您可以通过在外语中实现谓词来获得更好的性能,例如:
SWI-Prolog Java 或 C++ GNU Prolog C interface SICStus C, C++ 和 Java/.Net。【讨论】:
啊酷,那当然是我所追求的。虽然值得指出的是,这两种实现都有 O(log(N)) 的查找复杂度,因此不如哈希表的性能。 好点。我已经编辑了我的答案并添加了一些 Prolog 外语界面的链接。 还可以查看 YAP Prolog,它非常高效并且实现了多种数据结构(AVL 树、Splay 树、红黑树等):dcc.fc.up.pt/~vsc/Yap @Jay,SWI-Prolog 也将 AVL 树用于library(assoc)
【参考方案2】:
我不是 Prolog 人(只是一个外部观察者),但我发现了这个:
http://www.sics.se/sicstus/docs/4.0.7/html/sicstus/lib_002davl.html
当我搜索“prolog 有限映射平衡树”时。它说这是关联列表的另一种实现方式。
(为什么我想到这个:在 Haskell 中,一种纯粹的函数式语言,而不是关联列表或哈希表,通常使用树来表示(持久)字典或有限映射。查找也是 O(log(N) ). 请参阅Data.Map 获取有关使用平衡树实现地图的一些参考资料。)
【讨论】:
【参考方案3】:在 SICStus Prolog 中,使用 assoc 或 avl 库。
【讨论】:
【参考方案4】:我刚刚发现:
SWI-Prolog 版本 7 引入了 dicts 作为抽象对象,具有 访问成员的具体现代语法和功能符号 以及用户定义的访问功能。
语法如下:
TagKey1:Value1, Key2:Value2, ...
详情请见Dicts: structures with named arguments。
请注意:
These are first-class citizens of the language dict 之间统一的语义将来可能会发生变化 ./2 运算符,以前用于 cons-ing,已重新用于通过pointx:1,y:2.x
之类的表达式访问 dict 成员
Dicts can be destructively modified 但不建议这样做,因为“不合逻辑”,更不用说没有功能了。
The current underlying implementation 是“使用函子 dict
的复合术语。第一个参数是标签。其余参数创建一个排序键值对数组”
当前(2019 年)实施的操作的时间复杂度在 SWI Prolog 手册中的"5.4.5: Implementation Notes about dicts" 下给出:
字典目前使用函子表示为复合词
dict
。第一个参数是标签。其余参数创建 排序后的键值对数组。这种表示是紧凑的 保证良好的局部性。查找顺序为log(N),同时添加 值、删除值和与其他字典合并的顺序为 N。 主要缺点是在大字典中改变值是 在内存和时间方面都很昂贵。未来的版本可能会以单独的结构共享密钥或使用二进制文件 树以允许更便宜的更新。问题之一是 表示必须保持规范或统一 扩展以补偿替代表示。
还有
SWI-Prolog 字典是内置的和 SWI-Prolog 扩展。另一种选择是library(assoc)
,通过库提供基于 AVL 树的地图(因此可能在其他实现中可用)。
【讨论】:
我刚刚看到他最近发生了 - 更改为接受的答案。我们只需要等待几年才能开发出来。 你碰巧知道dict计算、get和set的时间复杂度吗?它们是 O(logn),比如有序映射,还是 O(1)(几乎)在良好的 STL C++ 哈希表中,或者更糟? @Jason 我在参考手册中给出的时间复杂度上添加了一些时间。【参考方案5】:以下 cmets 以大致从“更具体”到“更一般”的顺序解决您的问题。
首先,解决您的具体评论:
我会使用哈希表/字典,但据我所知,这在 Prolog 中是不可能的。
所有重要的 Prolog 实现都允许您破坏性地修改 Prolog 术语,例如使用 setarg/3
。使用 arg/3
和 setarg/3
可以 O(1) 访问术语的每个参数,这足以像在其他语言中一样实现哈希表,假设您的系统没有对术语的数量设置任意限制。
自己做这件事不是一个好主意,因为您必须考虑到所有条款的意外复制和共享。相反,请依靠库来完成。
哪些图书馆?我赞同其他人所写的内容:不要使用散列库,而是使用 基于树的 库,例如 library(assoc)
、library(avl)
等。在一般情况下,这些库不如散列有效,但是:
正如其他人所写,破坏性修改与逻辑编程不兼容,树库具有巨大的优势,它们可以在 ISO Prolog 中以纯方式实现strong> 渐近 最优效率。
最后,SWI-Prolog 的 dict 扩展不符合 ISO 标准,甚至不符合 语法,因此不能移植到符合标准的 Prolog 系统!请参阅 Ulrich Neumerkel 的 comments,了解如何以符合 ISO 标准的方式添加中缀点。
【讨论】:
以上是关于prolog中的哈希表的主要内容,如果未能解决你的问题,请参考以下文章