Pseudopolynomial time number partitioning
In computer science, pseudopolynomial time number partitioning is a pseudopolynomial time algorithm for solving the partition problem.
The problem can be solved using dynamic programming when the size of the set and the size of the sum of the integers in the set are not too big to render the storage requirements infeasible.
Suppose the input to the algorithm is a multiset of cardinality :
- S = {x1, ..., xN}
Let K be the sum of all elements in S. That is: K = x1 + ... + xN. We will build an algorithm that determines whether there is a subset of S that sums to . If there is a subset, then:
- if K is even, the rest of S also sums to
- if K is odd, then the rest of S sums to . This is as good a solution as possible.
e.g.1 S = {1, 2, 3, 5}, K = sum(S) = 11, K/2 = 5, Find a subset from S that is closest to K/2 -> {2, 3} = 5, 11 - 5 * 2 = 1
e.g.2 S = {1, 3, 7}, K = sum(S) = 11, K/2 = 5, Find a subset from S that is closest to K/2 -> {1, 3} = 4, 11 - 4 * 2 = 3
Recurrence relation
We wish to determine if there is a subset of S that sums to . Let:
- p(i, j) be True if a subset of { x1, ..., xj } sums to i and False otherwise.
Then p(, N) is True if and only if there is a subset of S that sums to . The goal of our algorithm will be to compute p(, N). In aid of this, we have the following recurrence relation:
- p(i, j) is True if either p(i, j − 1) is True or if p(i − xj, j − 1) is True
- p(i, j) is False otherwise
The reasoning for this is as follows: there is some subset of S that sums to i using numbers
- x1, ..., xj
if and only if either of the following is true:
- There is a subset of { x1, ..., xj−1 } that sums to i;
- there is a subset of { x1, ..., xj−1 } that sums to i − xj, since xj + that subset's sum = i.
The pseudo-polynomial algorithm
The algorithm consists of building up a table of size by containing the values of the recurrence. Remember that is the sum of all elements in . Once the entire table is filled in, we return . Below is a depiction of the table . There is a blue arrow from one block to another if the value of the target-block might depend on the value of the source-block. This dependence is a property of the recurrence relation.
function can_be_partitioned_equally(S) is input: A list of integers S. output: True if S can be partitioned into two subsets that have equal sum. n ← |S| K ← sum(S) P ← empty boolean table of size ( + 1) by (n + 1) initialize top row (P(0,x)) of P to True initialize leftmost column (P(x, 0)) of P, except for P(0, 0) to False for i from 1 to for j from 1 to n x = S[j-1] if (i-x) >= 0 then P(i, j) ← P(i, j-1) or P(i-x, j-1) else P(i, j) ← P(i, j-1) return P(, n)
Example
Below is the table P for the example set used above S = {3, 1, 1, 2, 2, 1}:
Analysis
This algorithm runs in time O(K/2 N), where N is the number of elements in the input set and K is the sum of elements in the input set.
The algorithm can be extended to the k-way multi-partitioning problem, but then takes O(n(k − 1)mk − 1) memory where m is the largest number in the input, making it impractical even for k = 3 unless the inputs are very small numbers.[1]
This algorithm can be generalized to a solution for the subset sum problem.
References
- Korf, Richard E. (2009). Multi-Way Number Partitioning (PDF). IJCAI.