A Variation of the Knapsack Problem (Part 1)

PROBLEM: Imagine you are given $7, and in a store with 5 items, each item has a numerical cost and satisfaction (Yes, satisfaction can be quantified. Deal with it.) as follows:

Name Cost Satisfaction
A 2 1
B 3 5
C 3 4
D 2 2
E 1 3

What is the greatest amount of satisfaction you can get without blowing your budget? This is in fact an occurrence of the 0/1 Knapsack problem and can be solved with dynamic programming, which is a way of solving the problem by storing sub-calculations for sub-problems for later use. We’ll take a look at why storing sub-solutions works for the knapsack problem, before diving in and looking at the code.

Recurrence Relation

Say on your last trip to the store, there were only 4 items available: A, B, C, D, and you’ve already figured out what your favourite items are for all budgets ranging from $1 to $7. With the new item E in the picture, how would this knowledge make your decision simpler? Well, since item E only costs a dollar, and the best items to buy with a budget of $7 – $1 = $6 are B and C, we can increase our satisfaction and remain under budget if we buy item E.

This is the intuition we need to formalise what is called the recurrence relation for the algorithm. \(w_i\) denotes the cost of  item \(i\), while \(v_i\) denotes its satisfaction. Try to imagine \(M\) as a table, and \(i\) and \(j\) as co-ordinates on the table. \[ M[i,j] = \left\{ \begin{array}{l l} 0 & \quad \text{if } i=0 \text{ or } j=0\\ M[i-1,j] & \quad \text{if } w_i > j\\ \max \left( M[i-1,j-w_i] + v_i, M[i-1,j] \right)& \quad \text{if } w_i \leq j\\ \end{array} \right. \] With this recurrence relation, all that remains is to implement the algorithm. To do this, however, we first need to figure out which direction to start filling our table. Top-down-left-right, bottom-up-right-left, or even diagonal (top-left corner to bottom-right corner) methods have been seen in dynamic programming solutions to different problems. In this case, the value at the \((i,j)\)-th cell depends on \((i-1,j)\), and \((i-1,j-w_i)\), if it exists. This tells us that the table should be filled from the left to the right, top to bottom.

The Algorithm

This behaviour of the algorithm can be seen in the animation. The rows represent the \(i\) indices and the columns represent the \(j\) indices. The first column shows the Name, Cost and Satisfaction of each item. A read from a cell in the table shows up as a red indicator, while a write shows up as yellow. Finally, when the table is completely filled, the steps are retraced in order to determine the items to be bought in order to get at the maximum satisfaction. This is is represented by the cell being highlighted as orange.

The main part of the code is shown below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
for(var i=0;i<items.length+1;i++){
	for(var j=0;j<capacity+1;j++){
		if(i==0||j==0) M.$(i,j,0);
		else {
			var w = items[i-1].weight;
			if(w > j) M.$(i,j,M.$(i-1,j));
			else {
				M.$(i,j,
					Math.max(
						M.$(i-1,j-w) + items[i-1].value,
						M.$(i-1,j)
					)
				);
			}
		}
	}
}

Too simple?

NEW PROBLEM: What if every item had a type, and you were limited to only one of each type in your selection? How would that change the recurrence relation? I’ll cover that variation of the knapsack problem in part 2.

DPTable.js

If you liked the animation for the table used to demonstrate the algorithm, the code can be found here. This would allow you to write a dynamic programming algorithm as you normally would, and using M.$(i,j) to access values and M.$(i,j,value) to assign values.

On Optimism

Impossible is Nothing

  1. Now let S be the set of all events. The set is then partitioned into 2 subsets, mutually exclusive:
    • P, the set of all possible events
    • I, the set of all impossible events.

    Let us assume that “Impossible is Nothing” is true. This implies that I is a null set.

  2. Let x be an arbitrary event with either a possible or impossible status.
  3. Consider the following proposition, p: “It is impossible for x to be in I” .
  4. Since I is null, p is clearly true, and as such, implying that an event y: “x being in I” , is an impossible event, and therefore is in I.
  5. This leads to a contradiction of the assumption, and disproves the fact that “Impossible is Nothing”

It is not within the scope of this blog post to discuss if logic (as a reasoning tool) is correct. That is best left to the philosophers.

How to stay awake in class

Don’t pay attention since trying to pay attention tires you.

This really works: Stop paying attention for as long as it takes you to wake up. Do something else that captures your attention instantly (I visit digg). Then start paying attention until it tires you and recurse. Your overall absorption rate should go up.

Life is short…

Consider the length of your fingers. You know that your pinky is short, compared to your ring finger. The shortness of your pinky is relative to the length of your ring finger.

When someone tells you “life is short”, consider what he’s experienced.

He could be the buddha reincarnate, and therefore knows that the length of life, relative to the amount of time he has been in existence, is short.

Or he could just be trying to convince you to buy some insurance.