Definition (Compression Function). Given an input stream X, we might have a compression functionf(X) whose value we would like to compute.
Definition (Sketch). A sketchC(X) is a “summary” of the stream X, with the property that C(X∪{x}) is a simple function of C(X) and x, and that C(X) alone is enough to compute or approximate f(X).
Roughly speaking, the quality of our streaming algorithm has to do with:
The size of the sketch C(X).
How well we can compute f(X) given C(X).
How long it takes to update C(X∪{x}) given C(X) and {x}.
Remark. An easy exercise: find a streaming algorithm for finding the maximum element of a list, such that…
The sketch C(X) has size O(1).
We can compute f(X) exactly given C(X).
Updating C(X) takes O(1) time.
Problem. (Distinct Elements) Compute the number of distinct elements of a list X.
In general, our standards for the quality of our estimate f~(X) can be summarized by constants ϵ,δ∈[0,1].
Pr[f~(X)∈((1−ϵ)f(X),(1+ϵ)f(X))]≥1−δ.
The smaller the values of ϵ and δ, the better.
Solution. (Flajolet-Martin 1985) Suppose the elements of X come from a universe U, and pick a “truly random” function h:U→[0,1]. Omit the details of randomness for simplicity.
Initialize C(X)=1, and update C(X∪{x})=min{C(X),h(x)}. Then output f~(X)=(C(X))−1−1.
Perhaps expectedly, Flajolet-Martin sucks; let's analyze its quality using the (ϵ,δ) definition from above.
Proof: For any ϵ∈[0,1] and sufficiently large n:=(# distinct elements of X)=f(X), we have:
Notably, δ≈1−(e−1/(1+ϵ)−e−1/(1−ϵ)) does not tend to be very small for large n—especially for small ϵ. ■
Here's a better algorithm than Flajolet-Martin.
Solution. (KMV) Say the elements of X come from a universe U of size u:=∣U∣. Say M={1,2,…,u3}. Pick a hash function h:U→M at random from a 2-wise independent hash family.
Initialize C(X)=∅, define k:=⌈24ϵ−2⌉, where ϵ is one of the “quality constants” from earlier. Update like so:
C(X)=kmin{C(X)∪{h(xi)}}, where kmin♣:={the k smallest elements of ♣}.
Remark. Think of this as an improved Flajolet-Martin.
Rather than hashing h:U→[0,1], we discretize the interval [0,1] into ∣U∣3 pieces.
Rather than only considering the minimum hashed value, we consider the k least hashed values.
Claim. For all ϵ<21, assuming u>ϵ21, we have that δ=31 holds.
Proof: Say that X has d:=f(X) distinct values. Let's justify only the bound Pr[f~(X)≥(1+ϵ)d]≤121.
If ∣C(X)∣<k, then we are in the “top case” for f~(X), so this probability is obviously zero.
Otherwise, f~(X)≥(1+ϵ)d means that at least k hash values are at most L=ku3⋅[(1+ϵ)d]−1. Consider indicator variables Yi that measure whether the ith distinct element is hashed to a value at most L. If Y:=∑i=1dYi, then:
E[Y]=d⋅E[Yi]=1+ϵk and V[Y]=d⋅V[Yi]=d⋅(E[Yi2]−(E[Yi])2)≤d⋅E[Yi2]=1+ϵk.
We're allowed to say V[Y]=∑i=1dV[Yi] because the 2-wise independence means cov(Yi,Yj)=0 for i=j.
The other direction is Pr[f~(X)≤(1−ϵ)d]≤41 hence the δ=31 constant. It's not exactly symmetric. ■
The space is O(klogu)=O(ϵ2logu), and the update time is O(logk); the logk comes from max-heap insertion operations.
Remark. We used the term “2-wise independent hashing” earlier. Here are the details of what that means:
Definition. A hash family H={hi:U→M} is t-wise independent if, for all distinct keys k1,…,kt∈U and (not necessarily distinct!) values i1,…,it∈M, we have:
h∼HPr[j=1⋀th(kj)=ij]=∣M∣t1.
For prime values of m:=∣M∣, one possible t-wise independent hash family is:
Note that 2-wise independent hash families are guaranteed universal, and s-wise independence implies t-wise independence for s>t.
Problem. (Majority) Given an input stream X with an element x that appears more than half the time, find x.
Solution. (BM81) Store two variables c and x. Initialize c=0 and x=Null. Upon reading a new xi,
If x=Null, then set c=1 and x=xi.
If x=xi, then increment c and leave x unchanged.
If x=xi, then decrement c. If c=0 now, set x=Null.
Then x is the desired answer.
Proof: Say M is the majority element. Consider some transition (c,x)→(c−1,[x or Null]) upon reading in a new xi. Think of this instance of xi as “eliminating” an instance of x earlier in the stream.
In this way, instances of x form disjoint pairs with different values xi later in the stream. And removing any one of these pairs from the stream does not affect the final answer of the algorithm!
But if we remove all such pairs, the result is an input stream of only M's—the leftovers are all copies of the final x, and M is too frequent to be paired away entirely. So M must be the final answer. ■
Problem. (Heavy Hitters) Given an input stream X, find all elements that appear more than k1 of the time.
Solution. (MG82) Have k−1 copies of the (c,x) setup from before. Upon reading a new xi,
If xi matches any of the x values, increment its corresponding c.
Otherwise, if some x equals Null, replace that Null with xi and set c=1.
Otherwise, decrement all c. Set any x whose c becomes 0 to Null.
Then every element that appears more than k1 of the time will be one of the x values.
Remark. Note that the algorithm might return values that don't appear more than k1 of the time.
Proof: Similar argument as before. Every transition of the form
can be viewed as an instance of xi “eliminating” an instance of each of x1,x2,…,xk−1.
Removing any of these k-tuples from the input stream does not affect the final result of the algorithm. Remove k-tuples until you cannot any longer; the resulting stream still has every x that appears more than k1 of the time. ■
Problem. (Approximate Heavy Hitters) Given an input stream X, find a set H of elements such that:
If an element appears more than k1 of the time, it must be in H.
If an element appears at most k1−ϵ of the time, it is in H with probability at most δ.
In other words, we want to never return elements that barely appear in the stream.
Solution. (Count-Min) Take d:=⌈log2δ−1⌉ and m:=⌈2ϵ−1⌉. Furthermore, consider a 2-wise independent hash family H:={hi:U→{1,2,…,m}} and sample d hash functions {h1,h2,…,hd} from H.
Our sketch is a d×m two-dimensional array C, where C[i][j] stores the # of xk in the input stream with hi(xk)=j. Then we estimate that the frequency of xk is #(xk):=1≤i≤dminC[i][hi(xk)].
Based on these frequency estimates, we select the heavy hitters to be all xk with #(xk)≥kn, where n:=∣X∣. (Finding these xk requires updating a min-heap that keeps track of high-frequency xk incrementally.)
In other words, Count-Min has d hash functions, each using m space, to try to estimate the frequency of each xk. Hash collisions will cause hash functions to overestimate, so we use the minimum estimate across all hi.
Proof: There are two conditions that Approximate Heavy Hitters demands of us. The former is obvious.
Claim 1. If an element appears more than k1 of the time, Count-Min will return it.
Proof: The point is that #(xk) is never an underestimate. □
The latter takes some work.
Claim 2. If an element appears at most k1−ϵ of the time, Count-Min returns it with probability at most δ.
Proof: Count-Min returns such an xk only if every single hi overestimates by at least ϵn. Well,
hi∼HE[how much hi overestimates (true #)(xk)]=xj=xk∑hi∼HPr[hi(xj)=hi(xk)]<mn.
(This step requires H to be universal.) Therefore, by Markov's inequality,
hi∼HPr[hi overestimates (true #)(xk) by more than ϵn]≤ϵnn/m≤21.
So the probability that every single hi overestimates by too much is at most (21)d≤δ. □
And that's why we chose d:=⌈log2δ−1⌉ and m:=⌈2ϵ−1⌉. ■
Definition (Jaccard Similarity). Given sets S and T, their Jaccard similarity is J(S,T):=∣S∪T∣∣S∩T∣.
Problem. (Similarity Search) Consider a collection of n sets A1,…,An⊆U and a target set A⊆U, all of size at most d. Given 1>s>s′>0, output Yes if there is some Ai such that J(Ai,A)≥s, and No if J(Ai,A)<s′ for all Ai.
The solution to this problem is fairly complex and generalizable, so we only give a rough sketch here.
Solution. (Approximate Similarity Search) Sample tL random hash functions h1,1,…,hL,t:U→[0,1], and define:
Then output Yes if there is some set Aj and some 1≤ℓ≤L such that σℓ(Aj)=σℓ(A), and No otherwise.
Claim. If J(Aj,A)=λ, then Pr[σℓ(Aj)=σℓ(A) for some ℓ]≥1−(1−λt)L.
Thus, we should tune the parameters t and L so that 1−(1−(s′)t)L is small and 1−(1−st)L is big. (Bigger t eliminates false positives, whereas bigger L eliminates false negatives.)