MIT 6.1220 — Lecture 19

Streaming Algorithms

Definition (Compression Function). Given an input stream XX, we might have a compression function f(X)f(X) whose value we would like to compute.

Definition (Sketch). A sketch C(X)C(X) is a “summary” of the stream XX, with the property that C(X{x})C(X \cup \{x\}) is a simple function of C(X)C(X) and xx, and that C(X)C(X) alone is enough to compute or approximate f(X)f(X).

Roughly speaking, the quality of our streaming algorithm has to do with:

Remark. An easy exercise: find a streaming algorithm for finding the maximum element of a list, such that…

Problem. (Distinct Elements) Compute the number of distinct elements of a list XX.

In general, our standards for the quality of our estimate f~(X)\tilde{f}(X) can be summarized by constants ϵ,δ[0,1]\epsilon, \delta \in [0, 1].

Pr[f~(X)((1ϵ)f(X),(1+ϵ)f(X))]1δ.\mathrm{Pr}\left [ \tilde{f}(X) \in ((1 - \epsilon) f(X), (1 + \epsilon)f(X)) \right] \geq 1 - \delta.

The smaller the values of ϵ\epsilon and δ\delta, the better.

Solution. (Flajolet-Martin 1985) Suppose the elements of XX come from a universe U\mathcal{U}, and pick a “truly random” function h:U[0,1]h: \mathcal{U} \to [0, 1]. Omit the details of randomness for simplicity.

Initialize C(X)=1C(X) = 1, and update C(X{x})=min{C(X),h(x)}C(X \cup \{x\}) = \min\{C(X), h(x)\}. Then output f~(X)=(C(X))11\tilde{f}(X) = (C(X))^{-1} - 1.

Perhaps expectedly, Flajolet-Martin sucks; let's analyze its quality using the (ϵ,δ)(\epsilon, \delta) definition from above.

Proof: For any ϵ[0,1]\epsilon \in [0, 1] and sufficiently large n:=(# distinct elements of X)=f(X)n := (\# \text{ distinct elements of } X) = f(X), we have:

Pr[f~(X)((1ϵ)n,(1+ϵ)n)]=(11(1+ϵ)n+1)n(11(1ϵ)n+1)ne1/(1+ϵ)e1/(1ϵ).\begin{align*}\mathrm{Pr}\left [ \tilde{f}(X) \in ((1 - \epsilon) n, (1 + \epsilon)n) \right] = \left(1 - \dfrac{1}{(1 + \epsilon)n + 1}\right)^n - \left(1 - \dfrac{1}{(1 - \epsilon)n + 1}\right)^n \approx e^{-1/(1 + \epsilon)} - e^{-1/(1 - \epsilon)}.\end{align*}

Notably, δ1(e1/(1+ϵ)e1/(1ϵ))\delta \approx 1 - (e^{-1/(1 + \epsilon)} - e^{-1/(1 - \epsilon)}) does not tend to be very small for large nn—especially for small ϵ\epsilon.   \blacksquare

Here's a better algorithm than Flajolet-Martin.

Solution. (KMV) Say the elements of XX come from a universe U\mathcal{U} of size u:=Uu := |\mathcal{U}|. Say M={1,2,,u3}M = \{1, 2, \dots, u^3\}. Pick a hash function h:UMh: \mathcal{U} \to M at random from a 22-wise independent hash family.

Initialize C(X)=C(X) = \emptyset, define k:=24ϵ2k := \lceil 24 \epsilon^{-2} \rceil, where ϵ\epsilon is one of the “quality constants” from earlier. Update like so:

C(X)=mink{C(X){h(xi)}}, where mink:={the k smallest elements of }.C(X) = \min_k\{C(X) \cup \{h(x_i)\}\}, \text{ where } \min_k \clubsuit := \{ \text{the $k$ smallest elements of $\clubsuit$}\}.

Finally, return the value:

f~(X):={C(X)if C(X)<k.ku3(max{C(X)})1otherwise.\tilde{f}(X) := \begin{cases} |C(X)| & \text{if } |C(X)| < k. \\ k u^3 \cdot \left(\max\{C(X)\}\right)^{-1} & \text{otherwise.} \end{cases}

Remark. Think of this as an improved Flajolet-Martin.

Claim. For all ϵ<12\epsilon < \frac{1}{2}, assuming u>1ϵ2u > \frac{1}{\epsilon^2}, we have that δ=13\delta = \frac{1}{3} holds.

Proof: Say that XX has d:=f(X)d := f(X) distinct values. Let's justify only the bound Pr[f~(X)(1+ϵ)d]112\mathrm{Pr}\left [\tilde{f}(X) \geq (1 + \epsilon) d\right ] \leq \frac{1}{12}.

If C(X)<k|C(X)| < k, then we are in the “top case” for f~(X)\tilde{f}(X), so this probability is obviously zero.

Otherwise, f~(X)(1+ϵ)d\tilde{f}(X) \geq (1 + \epsilon) d means that at least kk hash values are at most L=ku3[(1+ϵ)d]1L = k u^3 \cdot \left [ (1 + \epsilon) d \right ]^{-1}. Consider indicator variables YiY_i that measure whether the ithi^{\text{th}} distinct element is hashed to a value at most LL. If Y:=i=1dYiY := \sum_{i = 1}^d Y_i, then:

E[Y]=dE[Yi]=k1+ϵ    and    V[Y]=dV[Yi]=d(E[Yi2](E[Yi])2)dE[Yi2]=k1+ϵ.\mathbb{E}[Y] = d \cdot \mathbb{E}[Y_i] = \dfrac{k}{1 + \epsilon} ~~~ \text{ and } ~~~ \mathbb{V}[Y] = d \cdot \mathbb{V}[Y_i] = d \cdot\left(\mathbb{E}[Y_i^2] - (\mathbb{E}[Y_i])^2\right) \leq d \cdot \mathbb{E}[Y_i^2] = \dfrac{k}{1 + \epsilon}.

We're allowed to say V[Y]=i=1dV[Yi]\mathbb{V}[Y] = \sum_{i = 1}^d \mathbb{V}[Y_i] because the 22-wise independence means cov(Yi,Yj)=0\mathrm{cov}(Y_i, Y_j) = 0 for iji \neq j.

Now Chebyshev's inequality gives us:

Pr[Yk]=Pr[Yk1+ϵϵk1+ϵ]Pr[YE[Y]ϵk1+ϵ]V[Y](ϵk1+ϵ)21+ϵϵ2k112.\mathrm{Pr}[Y \geq k] = \mathrm{Pr}\left [ Y - \dfrac{k}{1 + \epsilon} \geq \dfrac{\epsilon k}{1 + \epsilon} \right ] \leq \mathrm{Pr} \left [ |Y - \mathbb{E}[Y]| \geq \dfrac{\epsilon k}{1 + \epsilon} \right] \leq \dfrac{\mathbb{V}[Y]}{\left(\frac{\epsilon k}{1 + \epsilon}\right)^2} \leq \dfrac{1 + \epsilon}{\epsilon^2k} \leq \dfrac{1}{12}.

The other direction is Pr[f~(X)(1ϵ)d]14\mathrm{Pr}\left [\tilde{f}(X) \leq (1 - \epsilon) d\right ] \leq \frac{1}{4} hence the δ=13\delta = \frac{1}{3} constant. It's not exactly symmetric.   \blacksquare

The space is O(klogu)=O(loguϵ2)O(k \log u) = O\left(\frac{\log u}{\epsilon^2}\right), and the update time is O(logk)O(\log k); the logk\log k comes from max-heap insertion operations.

Remark. We used the term “22-wise independent hashing” earlier. Here are the details of what that means:

Definition. A hash family H={hi:UM}\mathcal{H} = \{h_i: \mathcal{U} \to M\} is tt-wise independent if, for all distinct keys k1,,ktUk_1, \dots, k_t \in \mathcal{U} and (not necessarily distinct!) values i1,,itMi_1, \dots, i_t \in M, we have:

PrhH[j=1th(kj)=ij]=1Mt.\underset{h \sim \mathcal{H}}{\mathrm{Pr}} \left [ \bigwedge_{j = 1}^t h(k_j) = i_j \right ] = \dfrac{1}{|M|^t}.

For prime values of m:=Mm := |M|, one possible tt-wise independent hash family is:

H:={h(a0,,at1)(k):=((i=0t1aiki)%m)}(a0,,at1)Mt.\mathcal{H} := \left \{ h_{(a_0, \dots, a_{t - 1})}(k) := \left( \left(\sum_{i = 0}^{t - 1} a_i k^i\right) \% m \right) \right \}_{(a_0, \dots, a_{t - 1}) \in M^t}.

Note that 22-wise independent hash families are guaranteed universal, and ss-wise independence implies tt-wise independence for s>ts > t.

Problem. (Majority) Given an input stream XX with an element xx that appears more than half the time, find xx.

Solution. (BM81) Store two variables cc and xx. Initialize c=0c = 0 and x=Nullx = \textsc{Null}. Upon reading a new xix_i,

Then xx is the desired answer.

Proof: Say MM is the majority element. Consider some transition (c,x)(c1,[x or Null])(c, x) \to (c - 1, [x \text{ or } \textsc{Null}]) upon reading in a new xix_i. Think of this instance of xix_i as “eliminating” an instance of xx earlier in the stream.

In this way, instances of xx form disjoint pairs with different values xix_i 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 MM's—the leftovers are all copies of the final xx, and MM is too frequent to be paired away entirely. So MM must be the final answer.   \blacksquare

Problem. (Heavy Hitters) Given an input stream XX, find all elements that appear more than 1k\frac{1}{k} of the time.

Solution. (MG82) Have k1k - 1 copies of the (c,x)(c, x) setup from before. Upon reading a new xix_i,

Then every element that appears more than 1k\frac{1}{k} of the time will be one of the xx values.

Remark. Note that the algorithm might return values that don't appear more than 1k\frac{1}{k} of the time.

Proof: Similar argument as before. Every transition of the form

{(c1,x1),(c2,x2),,(ck1,xk1)}xi{(c11,x1),(c21,x2),,(ck11,xk1)}\{(c_1, x_1), (c_2, x_2), \dots, (c_{k - 1}, x_{k - 1})\} \stackrel{x_i}{\longrightarrow} \{(c_1 - 1, x_1), (c_2 - 1, x_2), \dots, (c_{k - 1} - 1, x_{k - 1})\}

can be viewed as an instance of xix_i “eliminating” an instance of each of x1,x2,,xk1x_1, x_2, \dots, x_{k - 1}.

Removing any of these kk-tuples from the input stream does not affect the final result of the algorithm. Remove kk-tuples until you cannot any longer; the resulting stream still has every xx that appears more than 1k\frac{1}{k} of the time.   \blacksquare

Problem. (Approximate Heavy Hitters) Given an input stream XX, find a set HH of elements such that:

In other words, we want to never return elements that barely appear in the stream.

Solution. (Count-Min) Take d:=log2δ1d := \lceil \log_2 \delta^{-1} \rceil and m:=2ϵ1m := \lceil 2 \epsilon^{-1} \rceil. Furthermore, consider a 22-wise independent hash family H:={hi:U{1,2,,m}}\mathcal{H} := \{ h_i : \mathcal{U} \to \{1, 2, \dots, m\}\} and sample dd hash functions {h1,h2,,hd}\{h_1, h_2, \dots, h_d\} from H\mathcal{H}.

Our sketch is a d×md \times m two-dimensional array CC, where C[i][j]C[i][j] stores the # of xkx_k in the input stream with hi(xk)=jh_i(x_k) = j. Then we estimate that the frequency of xkx_k is #(xk):=min1idC[i][hi(xk)]\#(x_k) := \underset{1 \leq i \leq d}{\min} C[i][h_i(x_k)].

Based on these frequency estimates, we select the heavy hitters to be all xkx_k with #(xk)nk\#(x_k) \geq \frac{n}{k}, where n:=Xn := |X|. (Finding these xkx_k requires updating a min-heap that keeps track of high-frequency xkx_k incrementally.)

In other words, Count-Min has dd hash functions, each using mm space, to try to estimate the frequency of each xkx_k. Hash collisions will cause hash functions to overestimate, so we use the minimum estimate across all hih_i.

Proof: There are two conditions that Approximate Heavy Hitters demands of us. The former is obvious.

Claim 1. If an element appears more than 1k\frac{1}{k} of the time, Count-Min will return it.

Proof: The point is that #(xk)\#(x_k) is never an underestimate.   \square

The latter takes some work.

Claim 2. If an element appears at most 1kϵ\frac{1}{k} - \epsilon of the time, Count-Min returns it with probability at most δ\delta.

Proof: Count-Min returns such an xkx_k only if every single hih_i overestimates by at least ϵn\epsilon n. Well,

EhiH[how much hi overestimates (true #)(xk)]=xjxkPrhiH[hi(xj)=hi(xk)]<nm.\underset{h_i \sim \mathcal{H}}{\mathbb{E}}[\text{how much } h_i \text{ overestimates } (\text{true \#})(x_k)] = \sum_{x_j \neq x_k} \underset{h_i \sim \mathcal{H}}{\mathrm{Pr}} \left [ h_i(x_j) = h_i(x_k) \right ] < \dfrac{n}{m}.

(This step requires H\mathcal{H} to be universal.) Therefore, by Markov's inequality,

PrhiH[hi overestimates (true #)(xk) by more than ϵn]n/mϵn12.\underset{h_i \sim \mathcal{H}}{\mathrm{Pr}}[h_i \text{ overestimates (true \#)($x_k$) by more than } \epsilon n] \leq \dfrac{n / m}{\epsilon n} \leq \dfrac{1}{2}.

So the probability that every single hih_i overestimates by too much is at most (12)dδ\left(\frac{1}{2}\right)^{d} \leq \delta.   \square

And that's why we chose d:=log2δ1d := \lceil \log_2 \delta^{-1} \rceil and m:=2ϵ1m := \lceil 2 \epsilon^{-1} \rceil.   \blacksquare

Definition (Jaccard Similarity). Given sets SS and TT, their Jaccard similarity is J(S,T):=STSTJ(S, T) := \frac{|S \cap T|}{|S \cup T|}.

Problem. (Similarity Search) Consider a collection of nn sets A1,,AnUA_1, \dots, A_n \subseteq \mathcal{U} and a target set AUA \subseteq \mathcal{U}, all of size at most dd. Given 1>s>s>01 > s > s' > 0, output Yes if there is some AiA_i such that J(Ai,A)sJ(A_i, A) \geq s, and No if J(Ai,A)<sJ(A_i, A) < s' for all AiA_i.

The solution to this problem is fairly complex and generalizable, so we only give a rough sketch here.

Solution. (Approximate Similarity Search) Sample tLtL random hash functions h1,1,,hL,t:U[0,1]h_{1, 1}, \dots, h_{L, t}: \mathcal{U} \to [0, 1], and define:

σ(K):=(minkK{h,1(k)}, minkK{h,2(k)}, , minkK{h,t(k)}).\sigma_{\ell}(K) := \left( \underset{k \in K}{\min} \{ h_{\ell, 1}(k) \}, \ \underset{k \in K}{\min} \{ h_{\ell, 2}(k) \}, \ \dots, \ \underset{k \in K}{\min} \{ h_{\ell, t}(k) \} \right).

Then output Yes if there is some set AjA_j and some 1L1 \leq \ell \leq L such that σ(Aj)=σ(A)\sigma_{\ell}(A_j) = \sigma_{\ell}(A), and No otherwise.

Claim. If J(Aj,A)=λJ(A_j, A) = \lambda, then Pr[σ(Aj)=σ(A) for some ]1(1λt)L\mathrm{Pr}[\sigma_{\ell}(A_j) = \sigma_{\ell}(A) \text{ for some } \ell] \geq 1 - (1 - \lambda^t)^L.

Thus, we should tune the parameters tt and LL so that 1(1(s)t)L1 - (1 - (s')^t)^L is small and 1(1st)L1 - (1 - s^t)^L is big. (Bigger tt eliminates false positives, whereas bigger LL eliminates false negatives.)