简体   繁体   English

序言中的哈希表

[英]Hash tables in prolog

I was solving a puzzle in prolog the other day and realized that were I using another programming language, I would have made use of a hash table/dictionary, but as far as I know this isn't really possible in prolog.前几天我在 prolog 中解决了一个难题,并意识到如果我使用另一种编程语言,我会使用哈希表/字典,但据我所知,这在 prolog 中是不可能的。

So my first question is are there any prologs that support a dictionary-like data structure with the performance characteristics of a hash table?所以我的第一个问题是是否有任何序言支持具有哈希表性能特征的类字典数据结构?

Secondly, it occurred to me that since most prologs use a hash table to store predicates, I could write a wrapper predicate to assert and retract facts, creating a dictionary interface which would leverage the underlying hash table of predicates.其次,我想到由于大多数 prolog 使用哈希表来存储谓词,我可以编写一个包装谓词来断言和撤回事实,创建一个字典接口来利用谓词的底层哈希表。 But would I get the performance characteristics of a hash table, or would the the interface add overheads that would reduce the performance?但是我会获得哈希表的性能特征,还是接口会增加会降低性能的开销?

I just found out that:我刚刚发现:

SWI-Prolog version 7 introduces dicts as an abstract object with a concrete modern syntax and functional notation for accessing members and as well as access functions defined by the user. SWI-Prolog 版本 7 将dicts作为抽象对象引入,具有用于访问成员以及用户定义的访问函数的具体现代语法和功能符号。

The syntax is as follows:语法如下:

Tag{Key1:Value1, Key2:Value2, ...}

See Dicts: structures with named arguments for the details.有关详细信息,请参阅Dicts:具有命名参数的结构

Note that :注意 :

The time-complexity of operations of the present (2019) implementation is given in the SWI Prolog manual under "5.4.5: Implementation Notes about dicts" :当前(2019 年)实现的操作的时间复杂度在 SWI Prolog 手册中的 “5.4.5:关于 dicts 的实现说明”下给出

Dicts are currently represented as a compound term using the functor dict .字典目前使用函子dict表示为复合术语。 The first argument is the tag.第一个参数是标签。 The remaining arguments create an array of sorted key-value pairs.其余参数创建一个排序的键值对数组。 This representation is compact and guarantees good locality.这种表示是紧凑的并保证了良好的局部性。 Lookup is order log( N ) , while adding values, deleting values and merging with other dicts has order N .查找的顺序是log( N ) ,而添加值、删除值和与其他字典合并的顺序是N The main disadvantage is that changing values in large dicts is costly, both in terms of memory and time.主要缺点是在大字典中更改值在内存和时间方面都是昂贵的。

Future versions may share keys in a separate structure or use a binary trees to allow for cheaper updates.未来的版本可能会在单独的结构中共享密钥或使用二叉树以允许更便宜的更新。 One of the issues is that the representation must either be kept cannonical or unification must be extended to compensate for alternate representations.问题之一是表示必须要么保持规范,要么必须扩展统一以补偿替代表示。

And also并且

The SWI-Prolog dicts are built-ins and an SWI-Prolog extension. SWI-Prolog dicts 是内置的和 SWI-Prolog 扩展。 An alternative is library(assoc) , providing maps based on AVL trees via a library (thus available in other implementations, possibly).另一种方法是library(assoc) ,通过库提供基于 AVL 树的地图(因此可能在其他实现中可用)。

Some Prolog environments have Association lists , which can be used to create and edit a dictionary:一些 Prolog 环境具有关联列表,可用于创建和编辑字典:

Edit:编辑:

You might be able to get better performance by implementing predicates in foreign languages , for example:您可以通过在外语中实现谓词来获得更好的性能,例如:

I'm not a Prolog guy (just an outside observer) but I found this:我不是 Prolog 人(只是一个外部观察者),但我发现了这一点:

http://www.sics.se/sicstus/docs/4.0.7/html/sicstus/lib_002davl.html http://www.sics.se/sicstus/docs/4.0.7/html/sicstus/lib_002davl.html

when I searched for "prolog finite map balanced trees".当我搜索“序言有限映射平衡树”时。 It says it's an alternative implementation of association lists.它说这是关联列表的另一种实现。

(Why I thought of this: In Haskell, a purely functional language, instead of association lists or hash tables, it is common to use trees for (persistent) dictionaries or finite maps. Lookups are also O(log(N)). See Data.Map for some references on implementing maps with balanced trees.) (为什么我会这么想:在 Haskell 中,一种纯函数式语言,而不是关联列表或哈希表,通常将树用于(持久)字典或有限映射。查找也是 O(log(N))。见Data.Map提供了一些关于使用平衡树实现地图的参考。)

在 SICStus Prolog 中,使用assocavl库。

The following comments address your question in an order going roughly from "more specific" to "more general".以下评论按大致从“更具体”到“更一般”的顺序解决了您的问题。

First, addressing your concrete comment:首先,解决您的具体评论:

I would have made use of a hash table/dictionary, but as far as I know this isn't really possible in Prolog.我会使用哈希表/字典,但据我所知,这在 Prolog 中是不可能的。

All serious Prolog implementations allow you to destructively modify Prolog terms, using for example setarg/3 .所有严肃的 Prolog 实现都允许您破坏性地修改 Prolog 术语,例如使用setarg/3 Using arg/3 and setarg/3 gives you O(1) access to each argument of a term, which is enough to implement a hash table exactly as in other languages, assuming your system does not place arbitrary limits on the arities of terms.使用arg/3setarg/3为您提供对术语的每个参数的 O(1) 访问权限,这足以像在其他语言中一样实现哈希表,假设您的系统没有对术语的数量设置任意限制。

It is not a good idea to do this yourself , since you have to take into account unexpected copying and sharing of terms at all terms.自己这样做不是一个好主意,因为您必须考虑到所有术语的意外复制和共享。 Instead, rely on libraries to do it.相反,依靠库来做到这一点。

Which libraries?哪些图书馆? I second what others have written: Instead of hashing libraries, use tree-based libraries like library(assoc) , library(avl) etc. These are not quite as efficient as hashes in the average case, but:我支持其他人写的内容:不要使用散列库,而是使用基于树的库,如library(assoc)library(avl)等。在一般情况下,这些library(avl)不如散列有效,但是:

  • they are often efficient enough它们通常足够高效
  • they scale very predictably: Most important operations are always in O(log(n)).它们的扩展性非常可预测:最重要的操作总是在 O(log(n)) 中。

Also as others have written, destructive modifications are incompatible with logic programming, and the tree libraries have the huge advantage that they can be implemented in ISO Prolog and in a pure way with asymptotically optimal efficiency .此外,正如其他人所写,破坏性修改与逻辑编程不兼容,树库具有巨大的优势,它们可以在ISO Prolog中以渐近最优效率纯粹方式实现

Finally, the dict extensions of SWI-Prolog are not ISO conformant , not even syntactically , and hence not portable to conformant Prolog systems!最后,SWI-Prolog 的 dict 扩展不符合 ISO ,甚至在语法上也不符合,因此不能移植到符合 Prolog 系统! See Ulrich Neumerkel'scomments for how an infix dot can be added in an ISO-conformant way.请参阅 Ulrich Neumerkel 的评论,了解如何以符合 ISO 的方式添加中缀点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM