Algorithm Search⌘K

Proofs: Sum over subsets dynamic programming

These are the human proofs of Sum over subsets dynamic programming, at full length.

SOS DP computes the sum over all submasks for every mask full

This proof shows: correctness.

Let n≥0n \ge 0, let (R,+,0)(R, +, 0) be a commutative monoid, and let f[0…2n−1]f[0 \ldots 2^n - 1] be the input. For a mask mm write mjm_j for bit jj of mm, and s⊆ms \subseteq m when sj≤mjs_j \le m_j for every jj.

Definition. For 0≤i≤n0 \le i \le n, let

Si(m)={ s⊆m:sj=mj for all j with i≤j≤n−1 }.S_i(m) = \{\, s \subseteq m : s_j = m_j \text{ for all } j \text{ with } i \le j \le n - 1 \,\}.

A submask in Si(m)S_i(m) may differ from mm only on bits 00 to i−1i - 1. So S0(m)={m}S_0(m) = \{m\} and Sn(m)={ s:s⊆m }S_n(m) = \{\, s : s \subseteq m \,\}.

Lemma 1. Let 0≤i<n0 \le i < n.

(a) If mi=0m_i = 0, then Si+1(m)=Si(m)S_{i+1}(m) = S_i(m).

(b) If mi=1m_i = 1, then Si+1(m)S_{i+1}(m) is the disjoint union of Si(m)S_i(m) and Si(m⊕2i)S_i(m \oplus 2^i).

Proof. (a) Let s∈Si+1(m)s \in S_{i+1}(m). Then s⊆ms \subseteq m and mi=0m_i = 0 give si=0=mis_i = 0 = m_i, so ss agrees with mm on bits ii to n−1n - 1 and s∈Si(m)s \in S_i(m). The other inclusion holds because the condition of SiS_i is stronger than that of Si+1S_{i+1}.

(b) Let m′=m⊕2im' = m \oplus 2^i, which is mm with bit ii cleared. Let s∈Si+1(m)s \in S_{i+1}(m). If si=1s_i = 1, then ss agrees with mm on bits ii to n−1n - 1, so s∈Si(m)s \in S_i(m). If si=0s_i = 0, then s⊆m′s \subseteq m' (bit ii of both is 0 and the other bits of m′m' are those of mm), and ss agrees with m′m' on bits ii to n−1n - 1, so s∈Si(m′)s \in S_i(m'). Conversely, each member of Si(m)S_i(m) is in Si+1(m)S_{i+1}(m); and each s∈Si(m′)s \in S_i(m') satisfies s⊆m′⊆ms \subseteq m' \subseteq m and agrees with mm on bits i+1i + 1 to n−1n - 1, so s∈Si+1(m)s \in S_{i+1}(m). Every member of Si(m)S_i(m) has bit ii equal to 1, and every member of Si(m′)S_i(m') has it equal to 0, so the union is disjoint. □\square

Theorem. SOS-DP(f,n)(f, n) returns FF with F[m]=∑s⊆mf[s]F[m] = \sum_{s \subseteq m} f[s] for every 0≤m<2n0 \le m < 2^n.

Proof. We prove this invariant of the loop of line L2.

(I) Before the pass with index ii, for 0≤i≤n0 \le i \le n: F[m]=∑s∈Si(m)f[s]F[m] = \sum_{s \in S_i(m)} f[s] for every mask mm.

Initialization. Line L1 sets F[m]=f[m]F[m] = f[m], and S0(m)={m}S_0(m) = \{m\}, so (I) holds for i=0i = 0.

Maintenance. Assume (I) before pass ii, with i<ni < n. Let FoldF_{\text{old}} be the array before the pass. In the pass, line L5 writes only to entries F[m]F[m] with mi=1m_i = 1, and only once to each, in the iteration for that mm. The entry it reads, F[m⊕2i]F[m \oplus 2^i], has bit ii of its index equal to 0, so no iteration of this pass writes it, and it equals Fold[m⊕2i]F_{\text{old}}[m \oplus 2^i] at the time of the read, in any order of the masks.

  • If mi=0m_i = 0, the pass does not change F[m]F[m], and by Lemma 1(a) and (I), F[m]=∑s∈Si(m)f[s]=∑s∈Si+1(m)f[s]F[m] = \sum_{s \in S_i(m)} f[s] = \sum_{s \in S_{i+1}(m)} f[s].
  • If mi=1m_i = 1, line L5 sets F[m]=Fold[m]+Fold[m⊕2i]=∑s∈Si(m)f[s]+∑s∈Si(m⊕2i)f[s]F[m] = F_{\text{old}}[m] + F_{\text{old}}[m \oplus 2^i] = \sum_{s \in S_i(m)} f[s] + \sum_{s \in S_i(m \oplus 2^i)} f[s] by (I). By Lemma 1(b), the two index sets are disjoint and their union is Si+1(m)S_{i+1}(m); since ++ is associative and commutative, the sum is ∑s∈Si+1(m)f[s]\sum_{s \in S_{i+1}(m)} f[s].

So (I) holds before pass i+1i + 1.

Termination. The loop of line L2 runs for i=0,…,n−1i = 0, \ldots, n - 1 and stops. Then (I) holds for i=ni = n, and Sn(m)S_n(m) is the set of all submasks of mm. Line L6 returns FF. ■\blacksquare

Cost. Pass ii runs line L4 for all 2n2^n masks and line L5 for the 2n−12^{n-1} masks with bit ii set. So there are n2nn 2^n tests and exactly n2n−1n 2^{n-1} additions, and the time is Θ(n2n)\Theta(n 2^n) when each test and addition costs O(1)O(1).

Supersets and the inverse. The superset version is the same proof with each mask complemented: the map m↦¬mm \mapsto \lnot m (on nn bits) turns submasks into supermasks, the test "bit ii is 1" into "bit ii is 0", and m⊕2im \oplus 2^i into m∣2im \mathbin{|} 2^i. For the Möbius transform over a commutative group, pass ii with subtraction is the inverse of pass ii with addition (it maps (a,b)(a, b) to (a,b−a)(a, b - a) on each pair (F[m⊕2i],F[m])(F[m \oplus 2^i], F[m]), and the pairs of a pass are disjoint), and the passes for distinct bits commute because each acts on one coordinate of the cube {0,1}n\{0, 1\}^n; so running all nn subtracting passes inverts SOS-DP.

Back to Sum over subsets dynamic programming