Model

The focus of this article is recovering a sparse vector x∈Rnx \in \mathbb{R}^n in the streaming setting. Initially, x=0x = 0. Then we see a sequence of updates (i,Δ)(i, \Delta) each causing the change xi←xi+Δx_i \leftarrow x_i + \Delta. There are three popular studied models

  1. insertion only: Δ=1\Delta = 1 for each update.
  2. strict turnstile: Δ\Delta can be negative, but it is guaranteed that x≥0x \ge 0 all the time.
  3. general turnstile: Δ\Delta can be negative, and entries of xx can be negative.

Let supp(x)⊂[n]\text{supp}(x) \subset [n] be the set of nonzero indices of xx. The vector xx is called kk sparse if supp(x)≤k\text{supp}(x) \le k.

Goal. Given an integer kk, design a data structure such that, if xx is kk sparse, the structure returns xx exactly; otherwise, the return can be arbitrary.

As we can't actually store real numbers, we use the following assumption:

The updates are integers and the entries of xx are bounded by ±M\pm M.

With this restriction, it suffices to solve this problem in a finite field Fp\mathbb{F}_p where p≥max⁡{n,M}p \ge \max \{ n, M \}. As opposed to the naive solution that keeps all entries of xx and uses O(nlog⁡M)O(n \log M) bits of memory, we show that the memory can be reduced to O(klog⁡(nM))O( k \log (nM) ) bits.

Algorithm

The problem is easy to solve in the insertion only model. We can use a hash set that keeps the first kk occurrence of the indices. If the we detect the k+1k + 1 new index, we can just report error.

The scenario is a little more complicated for the other two models. E.g., let n=4n = 4 and k=1k = 1. Consider the following stream

(1,1),(2,1),(3,−1),(4,1),(1,−1),(2,−1),(3,1). (1, 1), (2, 1), (3, -1), (4, 1), (1, -1), (2, -1), (3, 1).

The vector xx is finally 11-sparse and the only non-zero index is revealed at the end of the stream.

Solution 1

Encode

In the first approach, we use a matrix H∈Fpm×nH \in \mathbb{F}_p^{m \times n} (mm to be determined) and encode xx as Enc(x)=Hx\mathbb{Enc}(x) = H x. If the following property holds, we are guaranteed to recover xx if it is kk sparse.

For every kk sparse x,x′∈Fpnx, x' \in \mathbb{F}_p^n, if x≠x′x \neq x', then Hx≠Hx′Hx \neq H x'.

If Hx≠Hx′H x \neq Hx', then H(x−x′)≠0H (x - x') \neq 0. Observe that x−x′x - x' is a 2k2k sparse vector. This is equivalent to that Hz≠0H z \neq 0 for every nonzero 2k2k sparse vector z∈Fpnz \in \mathbb{F}_p^n.

Such HH does exists, with m=2km = 2k. Let a1,a2,...,an∈Fpa_1, a_2, ..., a_n \in \mathbb{F}_p be different integers. Then HH is given as

H=[11...1...1a1a2...ai...ana12a22...ai2...an2...a12k−1a22k−1...ai2k−1...an2k−1] H = \begin{bmatrix} 1 &1 &... &1 &... &1 \\ a_1 &a_2 &... &a_i &... &a_n \\ a_1^2 &a_2^2 &... &a_i^2 &... &a_n^2 \\ ...\\ a_1^{2k - 1} &a_2^{2k - 1} &... &a_i^{2k - 1} &... &a_n^{2k - 1} \end{bmatrix}

Let S=supp(z)⊂[n]S = \text{supp}(z) \subset [n] be a set of size 2k2k. Denote zSz_S be the vector by keeping only the nonzero dimensions of zz and HSH_S be an 2k×2k2k \times 2k matrix by keeping only columns indexed by SS. Then Hz=HSzSH z = H_S z_S. We show that the rows of HSH_S are linearly independently, hence its columns. It follows that if zS≠0⟹HSzS≠0z_S \neq 0 \Longrightarrow H_S z_S \neq 0.

It is left to show that ∀c∈Fp2k\forall c \in \mathbb{F}_p^{2k}, c≠0→HSTc≠0c \neq 0 \rightarrow H_S^T c \neq 0. Define the polynomial in Fp\mathbb{F}_p

f(x)=c2kx2k−1+c2k−1x2k−1+...+c1. f(x) = c_{2k} x^{2k - 1} + c_{2k - 1} x^{2k - 1} + ... + c_1.

Then HSTc=(f(ai))i∈[S]H_S^T c = ( f(a_i ) )_{i \in [S] }. As f(x)f(x) has at most 2k−12k - 1 distinct roots, and the (ai)i∈[S](a_i)_{i \in [S] } are different, there exists some i∈[S]i \in [S] such that f(ai)≠0f(a_i) \neq 0.

Decode

Given y=Enc(x)=Hxy = \mathbb{Enc}(x) = H x, how can we recover xx? We can loop over every subset S⊂[n]S \subset [n ] of size 2k2k and compute x′=HS−1yx' = H_S^{-1} y. If x′x' is kk sparse, by the property of HH, it is the unique kk-sparse vector such that HSx′=yH_S x' = y.

Remark: The proposed method is exponential respect to kk. However, there is an algorithm (called syndrome decoding) to perform the recovery in O(k2poly(log⁡p))O(k^2 poly(\log p)) time.

Space and Time

Space. The algorithm uses O(klog⁡(nM))O(k \log (nM)) bits.

This is because we don't store HH. For the finite field Fp\mathbb{F}_p, there exists at least one primitive element whose powers give all nonzero elements. We can pick such a primitive element aa, and set a1=aa_1 = a, a2=a2a_2 = a^2, ..., an=ana_n = a^n. Storing y=Hxy = Hx requires only O(klog⁡(nM))O(k \log (nM)) bits.

Time. Processing each update (i,Δ)(i, \Delta) in the stream takes O(k)O(k) time.

Solution 2

We first show how to recover an 11 sparse vector when negative updates are allowed, then use it as a black box to recover kk sparse vector.

1 sparse recovery

We show an algorithm that successes with probability n/pn / p.

First, we pick a non-zero integer zz uniformly at random from Fp\mathbb{F}_p. Let

H=[111...1123...nzz2z3...zn]. H = \begin{bmatrix} 1 &1 &1 &... &1 \\ 1 &2 &3 &... &n \\ z &z^2 &z^3 &... &z^n \end{bmatrix}.

The algorithm consists of 3 parts.

Initialize:
\qquad w←{0}3w \leftarrow \{ 0 \}^3
\qquad Sample zz uniformly from 1,...,p−11, ..., p - 1.

Updates: (i,Δ)(i, \Delta)
\qquad w←w+Δ⋅Hiw \leftarrow w + \Delta \cdot H_i, where HiH_i is the iith column of HH.

Output:
\qquad If w1=0w_1 = 0 or w3≠w1⋅zw2/w1w_3 \neq w_1 \cdot z^{w_2 / w_1}:
\qquad\qquad Return xx is not 11 sparse;
\qquad Else:
\qquad\qquad Return j≐w2/w1j \doteq w_2 / w_1

Failure Analysis

Theorem. The algorithm fails with probability n/pn / p.

Observe that

w1=∑i∈[n]xi,w2=∑i∈[n]i⋅xi,w3=∑i∈[n]zi⋅xi. w_1 = \sum_{i \in [n] } x_i, \qquad w_2 = \sum_{i \in [n] } i \cdot x_i, \qquad w_3 = \sum_{i \in [n] } z^i \cdot x_i.

If w1=0w_1 = 0, either x=0x = 0 or there is cancellation. Conditioned on w1≠0w_1 \neq 0, if xx is 11 sparse, then

w1=xj,w2=j⋅xj,w3=zj⋅xj. w_1 = x_j, \qquad w_2 = j \cdot x_j, \qquad w_3 = z^j \cdot x_j.

Hence, j=w2/w1j = w_2 / w_1 is exactly the non-zero index, and w3=w1⋅zjw_3 = w_1 \cdot z^{j}.

If xx is not 11 sparse, then

w3−w1⋅zj w_3 - w_1 \cdot z^{j}

is a polynomial of degree at most nn. It has at most nn distinct roots with one of them being 00. The probability that zz being a root is at most (n−1)/(p−1)≤n/p(n - 1) / (p - 1) \le n / p.

Space and Time

Space. The algorithm uses O(log⁡(nM))O(\log (nM)) bits.

Time. Processing each update (i,Δ)(i, \Delta) takes O(1)O(1) time.

kk sparse recovery

To apply the 11 sparse recovery data structure, we partition xx into 2k2k subsets randomly. In particular, we use a pairwise hash function that maps each i∈[n]i \in [n] to [2k][2k] uniformly at random. For ℓ∈[2k]\ell \in [2k], let SℓS_\ell be the set of indices mapped to ℓ\ell:

Sℓ≐{i∈[n]:h(i)=ℓ}. S_\ell \doteq \{ i \in [n]: h(i) = \ell \}.

Then we run 11 sparse recovery on each partition. If some partition contains only one nonzero index, then we recover it successfully.

Theorem. If xx is kk sparse, an nonzero dimension ii is recovered with probability 1/21 / 2.

Proof. It suffices to prove that ii is the only nonzero index in Sh(i)S_{h (i) }. For j∈supp(x)j \in \text{supp}(x), define the indicator variable XjX_j which equals 11 if h(j)=h(i)h(j) = h(i) and equals 0 otherwise. By Markov's inequality and linearity of expectation,

Pr⁡[∑i≠j∈supp(x)Xj≥1]≤E[∑i≠j∈supp(x)Xj]=∑i≠j∈supp(x)E[Xj]≤k−12k≤12. \Pr\left[ \sum_{ i \neq j \in \text{supp}(x) } X_j \ge 1 \right] \le \mathbb{E} \left[ \sum_{ i \neq j \in \text{supp}(x) } X_j \right] = \sum_{ i \neq j \in \text{supp}(x) } \mathbb{E} \left[ X_j \right] \le \frac{k - 1}{2k} \le \frac{1}{2}.

Remark. The Markov's inequality is rather tight here. Even if we have a fully independent hash function hh, the probability that none of the nonzero indices collides with ii is given by

(1−12k)k−1⪅exp⁡(−k−12k)≈exp⁡(−12)≈0.60653. \left( 1 - \frac{1}{2k} \right)^{k - 1} \lessapprox \exp \left( - \frac{k - 1}{2k} \right) \approx \exp \left( - \frac{1}{2} \right) \approx 0.60653.

□\square

Corollary. Running log⁡(k/δ)\log (k / \delta) independent copies of the above structure reduce the failure probability to δ\delta.

Space and Time

Space. The algorithm uses O(k(log⁡(k/δ))log⁡(nM))O(k (\log (k / \delta)) \log (nM)) bits.

Time. Processing each update (i,Δ)(i, \Delta) takes O(log⁡(k/δ))O(\log (k / \delta)) time.

Reference

[1]. Jelani Nelson, Chapter 4, Sketching Algorithms, 2020.

[2]. Moses Charikar, ℓ0\ell_{0} Sampling and Sketching Distances, CS369G: Algorithmic Techniques for Big Data, 2016