18

Consider below inputs for typical Knapsack problem.

V = [10,8,12]
W = [2,3,7]
i =  1,2,3
C = 10

I tried recursion with memoization to solve this sample but found no overlapping sub problem.

Signature of the recursive procedure :

knapsack(int c, int i) 

Called initially as knapsack(10,1)

enter image description here

The method of the solution is like as explained in https://www.youtube.com/watch?v=6h6Fi6AQiRM and https://www.youtube.com/watch?v=ocZMDMZwhCY.

How does Dynamic programming helps in reducing the time complexity for such samples of Knapsack ? If it does not help improving the time complexity of this case then does worst case complexity of DP solution also same as of back track search based i.e. 2 to the power n [ignoring the pruning, as if pruning applied then complexity will reduce for both the solution and again DP will not be better than non memoized recursive solution]

** Is overlapping in sub problems really missing in the above sample or I am missing something ?**

nits.kk
  • 5,204
  • 4
  • 33
  • 55
  • The knapsack problem is known to be either NP-complete or NP-hard, depending on the exact formulation, so it would be [very surprising indeed](http://cs.stackexchange.com/questions/9813/are-there-subexponential-time-algorithms-for-np-complete-problems) to find an algorithm which did not have exponential running time. – Daniel Wagner Aug 18 '16 at 19:58
  • DP is a general term for techniques that allow exponential problems to be solved in polynomial time. Memoization is one technique used in DP, but is not the technique used for the 0/1 knapsack problem. – user3386109 Aug 18 '16 at 20:01
  • [Here's the solution for the 0/1 knapsack problem](https://en.wikipedia.org/wiki/Knapsack_problem#0.2F1_knapsack_problem) – user3386109 Aug 18 '16 at 20:03
  • @user3386109 thanks for the answer, I looked at the wiki link , also I had seen this solution earlier. But as told by the professors in the video links mentioned in my question, recurrence with memoization just another perspective of solving the problem, it does not matter much if we wish to use bottom up methos involving tables or we use recurrence with memo. – nits.kk Aug 18 '16 at 20:25
  • for dynamic programming Overlapping sub problems is a must to have which I am not able to find in my sample. It would be helpful to me if you could help me defining it for the above sample. – nits.kk Aug 18 '16 at 20:43
  • Exactly my question. There is no overlapping. Consider this input: (5kg, $4), (2kg, $2), (5kg, $4), (2kg, $3) and knapsack capacity is 5kg. Now the whole solution space has to be explored. – Mustehssun Iqbal Dec 21 '18 at 18:56
  • @Mustehssun Iqbal please refer https://stackoverflow.com/a/39027863/504133 answer, it says the dp is helpful for large value of n – nits.kk Feb 05 '19 at 10:37

4 Answers4

12

DP doesn't help at all on your specific problem instance. But in general, i.e. over all possible input instances, it never solves more subproblems than the pure recursion, and on many instances it solves much fewer. That's why DP is good.

All your DP formulation guarantees is that it can solve any instance of the problem by solving at most n(c+1) subproblems, and indeed it does so for your example: here n = 3 and c = 10, and it solves the problem by solving 14 <= 33 subproblems (including the original problem).

Similarly, the purely recursive solution guarantees that it can solve any instance of the problem by solving at most 2^n subproblems.

You seem to be thinking that the DP algorithm should solve every problem instance faster than the recursive algorithm, but this is not true, and no one is making this claim. There exist instances (like yours) for which there are no overlapping subproblems, and for these instances the DP solves the problem using the exact same number of subproblems as the recursive solution. This does not say anything about the behaviour of the two algorithms in general. In general, the DP solves every problem using at most as many subproblems as the recursive solution, and sometimes much fewer -- since there do exist problem instances for which the recursive algorithm needs to solve the same subproblem more than once.

In short: The DP is never worse than the recursion, and is better than the recursion in the worst case. That does not imply that it is better on every instance.

j_random_hacker
  • 50,331
  • 10
  • 105
  • 169
7

The 0/1 knapsack problem has a pseudo-polynomial-time solution. The running time of that solution is O(nW) where n is the number of items to choose from, and W is the weight that the knapsack can hold. The running time is described as pseudo polynomial because W is not a function of n.

Or is it? Given a list of n items (by weight and value), there exists a maximum weight for one item, call it k. (That maximum weight can be determined in O(n) time.) If W is greater than or equal to kn, then the problem is trivial, all the items fit in the knapsack. Therefore, we only need to consider the cases where W < kn. So for the purposes of complexity analysis, W can be expressed as a function of n.

Given that nW <= k n^2, the running time of the algorithm is O(k n^2).

Now, the pedants in the audience will argue (correctly) that this is still pseudo-polynomial time, since there's no defined relationship between k and n. But any concrete statement of the problem (which lists items by weights and value) must necessarily have an explicit constant value for k in the problem statement itself.

Enough with the theory. How do we apply this to the example in the question.

  • n is clearly 3
  • k is clearly 7

Hence, the predicted running time is O(k n^2) = O(7x3x3) = 63. But the predicted exponential running time (without DP) is O(2^n) = O(2^3) = 8.

And there's the problem with your example. Big-O analysis describes the asymptotic behavior of algorithms for large values of n. It tells you little to nothing about the performance for small values of n. If the value of n is small enough that 2^n < k n^2, then there's no expectation that DP will improve the running time of the algorithm, or have any effect at all.

Your challenge is to find an example where 2^n > k n^2, and you still don't have overlapping sub problems.

user3386109
  • 34,287
  • 7
  • 49
  • 68
2

The running time of a recursive with memoization solution can approach 2^n if the none of the weights add up to any of the others and the capacity is large enough to include the total weight.

A dynamic programming solution would be O(c*n) though. Which is polynomial in terms of the capacity rather than the number of items.

In your example n=3 and c=10, so 2^n = 8 and c*n = 30. Here c*n is larger than 2^n, so the dp solution isn't helping. If you instead had a larger number of items and a small capacity, then the dp solution would be better. These are the kinds of constraints a dp solution would work well on.

fgb
  • 18,439
  • 2
  • 38
  • 52
0

@nits.kk

Here is an example with 5 elements {1, 2, 3, 4, 5} C = 36

Total sub problems = 31

Overlapping problems = 12

Unique sub-problems = 19

Overlapping problems repetition count:

  1. Capacity = 33 weights: [4, 5] count=2
  2. Capacity = 33 weights: [5] count=2
  3. Capacity = 32 weights: [5] count=2
  4. Capacity = 31 weights:[5] count=2
  5. Capacity = 30 weights: [5] count=2
  6. Capacity = 29 weights: [5] count=2

enter image description here


Obviously, I can't generate an image for 10 elements. But, if you run the problem for elements = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} C = 121, then these are the stats:

Total sub problems = 1023

Over lapping problems = 974

Unique subproblems = 49

I hope this makes it clear that there are overlapping subproblems.

apatniv
  • 1,771
  • 10
  • 13