[go: nahoru, domu]

Jump to content

Universal hashing

From Wikipedia, the free encyclopedia

This is an old revision of this page, as edited by 96.20.156.153 (talk) at 03:55, 9 February 2011 (→‎Hashing vectors). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

Using universal hashing (in a randomized algorithm or data structure) refers to selecting a hash function at random from a family of hash functions with a certain mathematical property (see definition below). This guarantees a low number of collisions in expectation, even if the data is chosen by an adversary. Many universal families are known (for hashing integers, vectors, strings), and their evaluation is often very efficient. Universal hashing has numerous uses in computer science, for example in implementations of hash tables, randomized algorithms, and cryptography.

Introduction

Assume we want to map keys from some universe into bins (labelled ). The algorithm will have to handle some data set of keys, which is not known in advance. Usually, the goal of hashing is to obtain a low number of collisions (keys from that land in the same bin). A deterministic hash function cannot offer any guarantee in an adversarial setting if : the adversary may choose to be precisely the preimage of a bin. This means that all data keys land in the same bin, making hashing useless. Furthermore, a deterministic hash function does not allow for rehashing: sometimes the input data turns out to be bad for the hash function (e.g. there are too many collisions), so one would like to change the hash function.

The solution to these problems is to pick a function randomly from a family of hash functions. A family is called a universal family if,

.

In other words, any two keys of the universe collide with probability at most when the hash function is drawn randomly from . This is exactly the probability of collision we would expect if the hash function assigned truly random hash codes to every key. Sometimes, the definition is relaxed to allow collision probability . This concept was introduced by Carter and Wegman[1] in 1977, and has found numerous applications in computer science (see, for example [2]).

If the collisions are supposed to be 'independent' in some sense, we might expect that collision probabilities multiply. Precisely, a family of hash functions is said to be a strongly k-independent universal family if for any collection from and in

The case for this definition is still slightly stronger than the definition given above but, since most algorithms used in practice produce strongly 2-independent universal families, a distinction isn't always drawn between the two[3].

Mathematical guarantees

For any fixed set of keys, universal hashing guarantees that:

  1. for any fixed , the expected number of keys in the bin is . When implementing hash tables by chaining, this is the expected running time of an operation involving key (query, insertion, deletion).
  2. the number of key pairs that collide () is, in expectation, . In particular, when hashing into bins, the expected number of collisions is . When hashing into bins, we have no collisions at all with probability at least a half.
  3. the expected number of keys in bins with at least keys in them is [4]. Thus, if we cap the capacity of each bin to 3 times the average (), the total number of keys in overflowing bins is at most . As observed in [4], this only holds for the stringent definition where two keys are allowed to collide with probability .

As the above guarantees hold for any fixed set , they hold if the data set is chosen by an adversary. However, the adversary has to make this choice before (or independent of) the algorithm's random choice of a hash function. (If the adversary can observe the random choice of the algorithm, randomness serves no purpose, and the situation is the same as deterministic hashing.)

Guarantees 2. and 3. are typically used in conjunction with rehashing. For instance, a randomized algorithm may be prepared to handle some number of collisions. If it observes too many collisions, it chooses another random from the family and repeats. Universality guarantees that the number of repetitions is a geometric random variable.

Constructions

Since any computer data can be represented as one or more machine words, one generally needs hash functions for three types of domains: machine words ("integers"); fixed-length vectors of machine words; and variable-length vectors ("strings").

Hashing integers

This section refers to the case of hashing integers that fit in machines words; thus, operations like multiplication, addition, division, etc. are cheap machine-level instructions. Let the universe to be hashed be .

The original proposal of Carter and Wegman[1] was to pick a prime and define

for chosen randomly, .

To see that is a universal family, one can observe that only if , for some . Solving for , we obtain: , where has an inverse since . A collision only happens for choices of out of possible choices ( is excluded). This is roughly a probability of if is large enough. It can be seen that removing the addition of a random does not hurt universality.

The state of the art for hashing integers is the multiply-shift scheme of [5]. This is the preferred method in practice due to its superior speed and simplicity[6]. This scheme assumes the number of bins is a power of two, . Let be the number of bits in a machine word. The hash function chooses a random odd number (on bits), multiplies by (modulo , as these are machine words), and keeps the high order bits as the hash code. The function can be written as:

  • C programming language: is (unsigned) (a*x) >> (w-M)
  • mathematical notation: .

Hashing vectors

This section is concerned with hashing a fixed-length vector of machine words. As for the case of integers, let be the number of bits in a word, and assume the number of bins is .

A fast almost universal hash family[7] is the following. Interpret the input as a vector of half words (integers of bits each). Initialized the hash function with a random vector of full words (-bit integers). Then:

, where denotes XOR.

Division can be implemented by an unsigned shift, so the most expensive operation is typically the multiplication. This scheme uses multiplications, i.e. one multiplication for every word of input (remember that was the number of half-words in the vector). On modern architectures, 64-bit multiplication is available, so each would be a 32-bit integer.

If you wish a fast strongly universal hash function, with the same notation, you can use

.

Hashing strings

This refers to hashing a variable-sized vector of machine words. If the length of the string can be bounded by a small number, it is best to use the vector solution from above, padding the array with zeros. The space required is the maximal length of the string, but the time to evaluate is just the length of (multiplication by zero yields zero, so the padding can be ignored when evaluating the hash function).

Now assume we want to hash , where a good bound on is not known a priori. A universal family proposed by [8] treats the string as the coefficients of a polynomial modulo a large prime. In , let be a prime and define:

, where is uniformly random.

To speed up computation, one chooses the prime to be close to a power of two, such as a Mersenne prime. This allows arithmetic modulo to be implemented without division (using faster operations like addition and shifts). For instance, on modern architectures one can work with , while 's are 32-bit values.

For further speed ups, one can combine this idea with vector hashing[7]. For instance, one applies vector hashing to each 16-word chunk of the string, and applies string hashing to the results. Since the slower string hashing is applied on a much smaller vector, this will essentially be as fast as vector hashing.

See also

References

  1. ^ a b Carter, Larry; Wegman, Mark N. (1979). "Universal Classes of Hash Functions". Journal of Computer and System Sciences. 18 (2): 143–154. doi:10.1016/0022-0000(79)90044-8. Conference version in STOC'77.
  2. ^ Miltersen, Peter Bro. "Universal Hashing". Archived from the original (PDF) on 24th June 2009. {{cite web}}: Check date values in: |archivedate= (help)
  3. ^ Motwani, Rajeev; Raghavan, Prabhakar (1995). Randomized Algorithms. Cambridge University Press. p. 221. ISBN 0-521-47465-5.
  4. ^ a b Baran, Ilya; Demaine, Erik D.; Pătraşcu, Mihai (2008). "Subquadratic Algorithms for 3SUM" (PDF). Algorithmica. 50 (4): 584–596.
  5. ^ Dietzfelbinger, Martin; Hagerup, Torben; Katajainen, Jyrki; Penttonen, Martti (1997). "A Reliable Randomized Algorithm for the Closest-Pair Problem". Journal of Algorithms. 25 (1): 19–51.
  6. ^ Thorup, Mikkel. "Text-book algorithms at SODA".
  7. ^ a b Thorup, Mikkel (2009). "String hashing for linear probing". Proc. 20th ACM-SIAM Symposium on Discrete Algorithms (SODA). pp. 655–664. {{cite conference}}: Unknown parameter |booktitle= ignored (|book-title= suggested) (help)
  8. ^ Dietzfelbinger, Martin; Gil, Joseph; Matias, Yossi; Pippenger, Nicholas (1992). "Polynomial Hash Functions Are Reliable (Extended Abstract)". Proc. 19th International Colloquium on Automata, Languages and Programming (ICALP). pp. 235–246. {{cite conference}}: Unknown parameter |booktitle= ignored (|book-title= suggested) (help)

Further reading