Algorithm Search⌘K

Proofs: Sparse vector

These are the human proofs of Sparse vector, at full length.

The sparse vector operations return the vector values and keep the invariant full

This proof shows: correctness.

Statement. Let each sparse vector satisfy (I1) to (I3) of the page, and let viv_i denote the entry that (I3) assigns. Assume the table TT behaves as a map: after T-PUT(T,i,x)(T, i, x) the key ii maps to xx, after DELETE(T,i)(T, i) the key ii is absent, the other keys keep their values, and iteration visits each pair of TT once. Then, for indices 0≤i<d0 \le i < d and vectors of equal dimension:

  1. after PUT(v,i,x)(v, i, x), the vector satisfies (I1) to (I3) with vi=xv_i = x and every other entry unchanged;
  2. GET(v,i)(v, i) returns viv_i;
  3. DOT(u,w)(u, w) returns ∑i=0d−1uiwi\sum_{i=0}^{d-1} u_i w_i, and DOT-DENSE(u,a)(u, a) returns ∑i=0d−1uia[i]\sum_{i=0}^{d-1} u_i a[i];
  4. PLUS(u,w)(u, w) returns a vector rr that satisfies (I1) to (I3) with ri=ui+wir_i = u_i + w_i for every ii, and leaves uu and ww unchanged.

Proof.

Part 1. If x=0x = 0, line L1 deletes ii, so ii is not a key and (I3) gives vi=0=xv_i = 0 = x. If x≠0x \ne 0, line L2 maps ii to xx, so (I3) gives vi=xv_i = x, and the new value is nonzero. In both cases the other keys and their values are unchanged, so the other entries are unchanged and still satisfy (I2) and (I3). The only key that may be added is ii, and 0≤i<d0 \le i < d, so (I1) holds.

Part 2. Line L3 returns T[i]T[i] if ii is a key and 0 otherwise, which is viv_i by (I3).

Part 3. Exchanging uu and ww on line L4 does not change the sum, since uiwi=wiuiu_i w_i = w_i u_i. Let KK be the set of keys of u.Tu.T after line L4. We show the loop invariant: after the loop has visited a set S⊆KS \subseteq K of pairs, s=∑i∈Suiwis = \sum_{i \in S} u_i w_i. It holds with S=∅S = \emptyset and s=0s = 0 by line L5. A round visits a new pair (i,x)(i, x) with x=uix = u_i by (I3), and adds x⋅GET(w,i)=uiwix \cdot \mathrm{GET}(w, i) = u_i w_i by part 2, so the invariant holds for S∪{i}S \cup \{i\}. The loop visits each pair once, so at line L8 S=KS = K and s=∑i∈Kuiwis = \sum_{i \in K} u_i w_i. For an index i∉Ki \notin K, (I3) gives ui=0u_i = 0, so uiwi=0u_i w_i = 0, and ∑i∈Kuiwi=∑i=0d−1uiwi\sum_{i \in K} u_i w_i = \sum_{i=0}^{d-1} u_i w_i. The proof for DOT-DENSE is the same with a[i]a[i] in place of GET(w,i)(w, i).

Part 4. Line A1 makes rr a copy of uu, so rr satisfies (I1) to (I3) with r=ur = u, and later changes to rr do not touch uu. The loop reads ww and never writes it. Let SS be the set of keys of w.Tw.T visited so far. The loop invariant is: rr satisfies (I1) to (I3), and ri=ui+wir_i = u_i + w_i for i∈Si \in S, and ri=uir_i = u_i for i∉Si \notin S. It holds at the start with S=∅S = \emptyset. A round visits a new pair (i,x)(i, x) with x=wix = w_i. Before the round, ri=uir_i = u_i since i∉Si \notin S, and GET(r,i)(r, i) returns it by part 2. Line A3 calls PUT(r,i,ui+wi)(r, i, u_i + w_i), which by part 1 keeps (I1) to (I3), sets ri=ui+wir_i = u_i + w_i, and changes no other entry. So the invariant holds for S∪{i}S \cup \{i\}. At line A4 every key of w.Tw.T is in SS. For i∉Si \notin S, (I3) for ww gives wi=0w_i = 0, so ri=ui=ui+wir_i = u_i = u_i + w_i. Hence ri=ui+wir_i = u_i + w_i for every ii. When ui+wi=0u_i + w_i = 0, part 1 shows that index ii is not stored, so (I2) holds for rr.

Each loop visits a finite table once and each round takes finitely many steps, so every operation stops. ■\blacksquare

Back to Sparse vector