简体   繁体   中英

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.

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. 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.

The syntax is as follows:

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

See Dicts: structures with named arguments for the details.

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" :

Dicts are currently represented as a compound term using the functor 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 . 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. An alternative is library(assoc) , providing maps based on AVL trees via a library (thus available in other implementations, possibly).

Some Prolog environments have Association lists , which can be used to create and edit a dictionary:

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:

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.)

在 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.

All serious Prolog implementations allow you to destructively modify Prolog terms, using for example 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.

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:

  • they are often efficient enough
  • they scale very predictably: Most important operations are always in 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 .

Finally, the dict extensions of SWI-Prolog are not ISO conformant , not even syntactically , and hence not portable to conformant Prolog systems! See Ulrich Neumerkel'scomments for how an infix dot can be added in an ISO-conformant way.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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