Knapsack & DP / FPTAS

Pseudo-polynomial profit DP, then profit rounding for a fully polynomial approximation scheme.

The idea

In the 0/1 knapsack problem we are given $n$ items, item $j$ weighing $w_{j}$ and worth a profit $p_{j}$, and a capacity $W$. Choose a subset whose total weight is at most $W$ — each item taken whole or left behind — so that the total profit is as large as possible.

A dynamic program indexed by profit solves the problem exactly. For the first $j$ items and a profit target $P$, let $x(j, P)$ be the smallest total weight of a subset of those items whose profit is exactly $P$, and $\infty$ if none of them reaches $P$. Item $j$ is either left out, so the first $j-1$ items must supply $P$ themselves, or taken, so they must supply $P - p_{j}$ and its weight is added:

$x(j, P) = \min\{\, x(j-1, P),\ w_{j} + x(j-1, P - p_{j}) \,\}.$

Starting from $x(0, 0) = 0$, the table fills one row per item, and the answer is the largest profit $P$ with $x(n, P) \le W$.

Algorithm.

Algorithm: Profit-Indexed Knapsack DP Input: weights w_1, ..., w_n, profits p_1, ..., p_n, capacity W Output: the largest total profit of a subset of total weight ≤ W 1. x(0, 0) = 0; x(0, P) = ∞ for every P ≥ 1 // with no items, only profit 0 is reachable 2. j = 1 3. for every P from 0 to p_1 + ... + p_n: x(j, P) = min{ x(j-1, P), w_j + x(j-1, P - p_j) } // leave item j out, or take it; P - p_j < 0 gives ∞ 4. if j < n, set j = j + 1 and go to step 3 // one row per item 5. return the largest P with x(n, P) ≤ W

The table has a column for every profit up to $\sum_{j} p_{j}$, so the running time $O(n \sum_{j} p_{j})$ is pseudo-polynomial: polynomial in the profit values, but exponential in the number of bits that encode them. Rounding each profit down to $\lfloor p_{j}/K \rfloor$ for a scale factor $K$ chosen from a target accuracy $\varepsilon$ shrinks the table and yields a $(1 - \varepsilon)$-approximation in time polynomial in $n$ and $1/\varepsilon$ — a fully polynomial-time approximation scheme.

Algorithm.

Algorithm: Knapsack FPTAS Input: a knapsack instance, an accuracy ε with 0 < ε < 1 Output: a feasible subset with profit at least (1 - ε) × the optimum 1. K = ε × p_max / n // p_max = the largest profit; larger ε means coarser rounding 2. replace every profit p_j by ⌊p_j / K⌋ // each item forfeits less than K of true profit 3. run the profit-indexed DP on the rounded profits // original weights and capacity W 4. return the subset achieving the DP optimum // traced back through the table

Ways to work on it

Not sure where to start? Take the ten-question placement test.