Sometimes we must answer "is the element there?" over a huge collection, and a set eats too much memory. A Bloom filter is a memory-efficient probabilistic structure. It gives only two answers: "definitely not" or "maybe yes". So false positives are possible, while false negatives never happen.
w6 gives a false positive, cow gives "definitely not"The idea
- An array of
mbits, all0at first. kdifferent hash functions.add(x): sets to1thekbits pointed to by thekhashes.x in filter: looks at the samekbits; if all are1the answer is "maybe yes", if any is0it is "definitely not".
Bits only go 0 → 1, so an added element is always found (no false negatives). But other elements may have set the same bits to 1, so an element that was never added can also get "maybe yes".
Implementation
Instead of k separate hash functions we use two hashes: h1 + i * h2 (the Kirsch-Mitzenmacher trick). We take the hashes from hashlib.sha256 so they are deterministic (hash() changes between processes, see hash functions).
import hashlib
import math
class BloomFilter:
def __init__(self, m, k):
self.m = m
self.k = k
self.bits = bytearray((m + 7) // 8)