Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions hw1/xiweipan/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Task 9.6

In `knapsack.jl`, `knapsack_dp` realizes an exact algorithom with the complexity $O(lV)=O(l^2 v_\text{max})$, where $V=lv_\text{max}$ is the upper bound of the maximum value.

This doesn't mean $\mathbf{P}=\mathbf{NP}$. Because although the algorithm runs in polynomial time with respect to the numeric values of the inputs (namely, the number of items $l$ and the maximum item value $v_{\text{max}}$), it is not polynomial in the size of the input, which is measured in **bits**. And this algorithm is exponential in the bit size of the input.


# Task 9.7

In this task,we need to design a FPTAS version of the algorithm in Task 9.6 with approximation ratio $1-\epsilon$ and time complexity $\text{poly}(l, \frac{1}{\epsilon})$.

The main idea is to scale down the item values by a factor of $K$, i.e. $v'_i = \lfloor v_i / K \rfloor$.

However, in this process, $K v'_i \leq v_i < K (v'_i + 1)$, so for the whole problem, the maximum value loss is $lK$.

Considering the scaled-down problem, we apply the exact dynamic programming algorithm from Task 9.6 to the instance with scaled values $v'_i$, and denote the result of this algorithm as $\text{APX}$. Then we have

$\text{APX} \ge \text{OPT} - lK$,

where $\text{OPT}$ is the optimal value of the original problem.

To ensure the approximation ratio is $1-\epsilon$, i.e.

$\text{APX} \ge (1-\epsilon) \text{OPT}$,

we can simply let

$\text{OPT}-l K \geq (1-\epsilon) \text{OPT}$,

which is equivalent to

$l K \leq \epsilon \text{OPT}$.

Since the optimal solution must at least match the best item that fits into the knapsack, we have $\text{OPT} \ge v^* $, where $v^* = \max \{ v_i \mid w_i \le W \}$. We can simply assume for all $i$, $w_i \le W$ (otherwise, we can remove it from the problem).

Therefore, we have the sufficient condition

$l K \leq \epsilon v_\text{max}$.

Thus, for any $\epsilon > 0$, by choosing $K = \frac{\epsilon v_\text{max}}{l}$, we can ensure the approximation ratio is $1-\epsilon$.

For the time complexity, the dynamic programming algorithm is still $O(lV')=O(l^2 v'_\text{max}) = O(l^3 \frac{1}{\epsilon})$, which is polynomial of $l$ and $\frac{1}{\epsilon}$.










45 changes: 45 additions & 0 deletions hw1/xiweipan/knapsack.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
function knapsack_dp(weights::Vector{Int}, values::Vector{Int}, W::Int)
l = length(weights)
vmax = maximum(values)
V = l * vmax
INF = typemax(Int) # mark the impossible case

# dp is a (l+1) x (V+1) matrix
# dp[i, j] is the minimum weight of the knapsack with value j-1 using the last i to l items
dp = fill(INF, l + 1, V + 1)
# i = l+1: no available item, only value 0 is possible with weight 0
dp[l + 1, 1] = 0
# j = 1: max value is 0
for i in 1:l
dp[i, 1] = 0
end

for i in l:-1:1
w, v = weights[i], values[i]
for val in 0:V
# without the i-th item
without = dp[i + 1, val + 1]
# with the i-th item
with = INF
if val >= v && dp[i + 1, val - v + 1] != INF
with = w + dp[i + 1, val - v + 1]
end
dp[i, val + 1] = min(without, with)
end
end

result = 0
for val in 0:V
if dp[1, val + 1] <= W
result = val
end
end

return result
end

# test
weights = [2, 3, 4, 5]
values = [3, 4, 5, 6]
W = 5
println(knapsack_dp(weights, values, W))