PatriciaTree
Association maps from key to values, and sets, implemented with Patricia Trees, allowing fast merge operations by making use of physical equality between subtrees; and custom implementation of tree nodes (allowing normal maps, hash-consed maps, weak key or value maps, sets, custom maps, etc.)
This is similar to OCaml's Map, except that:
The main benefit of Patricia Tree is that their representation is stable (contrary to maps, inserting nodes in any order will return the same shape), which allows different versions of a map to share more subtrees in memory, and the operations over two maps to benefit from this sharing. The functions in this library attempt to maximally preserve sharing and benefit from sharing, allowing very important improvements in complexity and running time when combining maps or sets is a frequent operation.
pop_minimum
and pop_maximum
make our Set suitable as priority queue (but remember that each element in the queue must map to a distinct integer).Note on complexity: in the following, n represents the size of the map when there is one (and |map1|
is the number of elements in map1
). The term log(n) correspond to the maximum height of the tree, which is log(n) if we assume an even distribution of numbers in the map (e.g. random distribution, or integers chosen contiguously using a counter). The worst-case height is O(max(n,64)) which is actually constant, but not really informative; log(n) corresponds to the real complexity in usual distributions.
module type Node = sig ... end
This module explains how a node is stored in memory, with functions to create and view nodes.
module type NodeWithId = sig ... end
module type BaseMap_S = sig ... end
module type Set_S = sig ... end
Signature for sets implemented using Patricia trees.
module type Map_S = sig ... end
The signature for maps with a single type for keys and values.
module type HomogeneousKey = sig ... end
The signature of keys when they are all of the same type.
module MakeSet (Key : HomogeneousKey) : Set_S with type _ BaseMap.key = Key.t
Same as above, but with Heterogeneous keys (and values, for maps).
module type HeterogeneousSet_S = sig ... end
Module type of a set containing different keys, very similar to Set_S
, but with simple type key
being replaced by type constructor 'a key
.
module type HeterogeneousMap_S = sig ... end
This is the same than Map_S
, except that:
To have heterogeneous keys, we must define a polymorphic equality function. Like in the homogeneous case, it should have the requirement that (to_int a) = (to_int b) ==> polyeq a b = Eq
.
module type HeterogeneousKey = sig ... end
module type Value = sig ... end
The moodule type of values, which can be heterogeneous.
module HomogeneousValue : Value with type ('a, 'map) t = 'map
To use when the type of the value is the same (but the keys can still be heterogeneous).
module MakeHeterogeneousSet
(Key : HeterogeneousKey) :
HeterogeneousSet_S with type 'a BaseMap.key = 'a Key.t
module MakeHeterogeneousMap
(Key : HeterogeneousKey)
(Value : Value) :
HeterogeneousMap_S
with type 'a key = 'a Key.t
and type ('k, 'm) value = ('k, 'm) Value.t
We can also customize the representation and creation of nodes, to gain space or time.
Possibitities include having weak key and/or values, hash-consing, giving unique number to nodes or keeping them in sync with the disk, lazy evaluation and/or caching, etc.
module MakeCustomHomogeneous
(Key : HomogeneousKey)
(Node : Node with type 'a key = Key.t and type ('key, 'map) value = 'map) :
Map_S with type key = Key.t and type 'm t = 'm Node.t
Create a Homogeneous Map with a custom Node
.
module MakeCustom
(Key : HeterogeneousKey)
(Value : Value)
(Node :
Node
with type 'a key = 'a Key.t
and type ('key, 'map) value = ('key, 'map) Value.t) :
HeterogeneousMap_S
with type 'a key = 'a Key.t
and type ('k, 'm) value = ('k, 'm) Value.t
and type 'm t = 'm Node.t
Create an Heterogeneous map with a custom Node
.
Some implementations of Node.
module SimpleNode
(Key : sig ... end)
(Value : Value) :
Node
with type 'a key = 'a Key.t
and type ('key, 'map) value = ('key, 'map) Value.t
This module is such that 'map t = 'map view.
module NodeWithId
(Key : sig ... end)
(Value : Value) :
NodeWithId
with type 'a key = 'a Key.t
and type ('key, 'map) value = ('key, 'map) Value.t
Here, nodes also contain a unique id, e.g. so that they can be used as keys of maps or hashtables.
Maybe: we can make variations around NodeWithId; e.g. a version that does HashConsing, or a version that replicates the node to a key-value store on disk, etc.
module SetNode
(Key : sig ... end) :
Node with type 'a key = 'a Key.t and type ('key, 'map) value = unit
An optimized representation for sets, i.e. maps to unit: we do not store a reference to unit (note that you can further optimize when you know the representation of the key).
module WeakNode
(Key : sig ... end)
(Value : Value) :
Node
with type 'a key = 'a Key.t
and type ('key, 'map) value = ('key, 'map) Value.t
Node used to implement weak key hashes (the key-binding pair is an Ephemeron, the reference to the key is weak, and if the key is garbage collected, the binding disappears from the map