title: "Lecture 3: Integer Linear Programming" author: "Junaid Hasan" date: "June 25, 2021"¶

Knapsack Problem¶

  • Alice wants to pack a set of items into her knapsack (backpack). However she can carry at most 100 pounds. The weights and values are given below

    | Item | Weight | Value | |---------|---------|---------| | 1 | 30 | 240 | | 2 | 35 | 300 | | 3 | 10 | 100 | | 4 | 15 | 150 | | 5 | 35 | 360 | | 6 | 22 | 180 | | 7 | 29 | 220 | | 8 | 18 | 140 | | 9 | 11 | 90 |

  • Which items must she pack to maximize total value if there is just one of each item.

  • For instance the items could be paintings at an art show.

Thoughts¶

  • Which items seem more enticing?

Mathematical Model¶

  • Let us introduce a variable $ x_i $ such that
  • $ x_i = 0 $ if object i is not in the knapsack.
  • $ x_i = 1 $ if object i is in the knapsack.
  • Can you formulate the problem?
  • Note that $x_i$ is known as a binary variable.

(contd..)¶

  • Then the LP is
  • Maximize $$ 240x_1 + 300 x_2 + 100x_3 + 150 x_4 + 360x_5 + 180x_6 + 220x_7 + 140x_8 + 90x_9 $$ subject to
  • $$ 30 x_1 + 35 x_2 + 10 x_3 + 15 x_4 + 35 x_5 + 22 x_6 + 29 x_7 + 18 x_8 + 11 x_9 \leq 100 $$
  • $$ x_1, x_2, x_3, x_4, x_5, x_6, x_7, x_8, x_9 \in \{0,1 \} $$.
  • Note that the variables are constrained to be integers (more specifically binary in this case).
  • This program is called an integer linear program.

Solution (code)¶

In [31]:
objects = [1,2,3,4,5,6,7,8,9]
weights = {1:30,
          2:35,
          3:10,
          4:15,
          5:35,
          6:22,
          7:29,
          8:18,
          9:11}
value = {1:240,
        2:300,
        3:100,
        4:150,
        5:360,
        6:180,
        7:220,
        8:140,
        9:90}
maxweight = 100
In [32]:
def knapsackModel(objects, weights, value, maxweight):
    n = len(weights)
    
    from pyscipopt import Model, quicksum
    model = Model("Alice's knapsack")
    x = {}
    
    for i in objects:
        x[i] = model.addVar(vtype="B", name="x%s"%i)
    
    model.addCons(quicksum(weights[i]*x[i] for i in objects) <= maxweight, "weight constraint")
    
    model.setObjective(quicksum(value[i]*x[i] for i in objects), "maximize")
    model.data = x
    return model
In [33]:
def solveKnapsack(objects, weights, value, maxweight):
    
    model = knapsackModel(objects, weights, value, maxweight)
    model.optimize()
    x = model.data
    
    print("Total value", model.getObjVal())
    for i in objects:
        print("Object %s "%i, model.getVal(x[i]))
    
    
    return model.getObjVal()
In [34]:
solveKnapsack(objects, weights, value, maxweight)
Total value 930.0
Object 1  -0.0
Object 2  -0.0
Object 3  1.0
Object 4  1.0
Object 5  1.0
Object 6  1.0
Object 7  -0.0
Object 8  1.0
Object 9  -0.0
Out[34]:
930.0

Remarks¶

  • This means that Alice must put items 3,4,5,6,8.
  • Moreover the total weight of these is 10+15+35+22+18 = 100
  • So the constraint is binding (equality is acheived).
  • Let us try another experiment. Let us vary the weight capacity and see what total value she can pack.

Plot¶

In [17]:
M = sum(weights[i] for i in objects)
totalWeightsList = [i for i in range(10, M+1)]
totalValueList = [solveKnapsack(objects, weights, value, i) for i in range(10, M+1)]
In [20]:
import matplotlib.pyplot as graph
graph.plot(totalWeightsList, totalValueList)
graph.xlabel("Max Weights of Knapsack")
graph.ylabel("Total Value gathered")
graph.show()
No description has been provided for this image
In [ ]:
 

Thoughts¶

  • What other questions can we ask?
  • Any other ideas?

Variation¶

  • Suppose now that the objects are not limited to 1 in quantity, but rather there is an unlimited number of each.
  • This can happen if its not an art show but say a grocery store.
  • What should we change in the LP?
  • Answer: Now $ x_i $ is not just 0 or 1, but $ x_i $ can be any non-negative integer.

Solution¶

In [37]:
def unlimitedknapsackModel(objects, weight, value, maxweight):
    n = len(weight)
    
    from pyscipopt import Model, quicksum, multidict
    model = Model("knapsack")
    x = {}
    
    for i in objects:
        x[i] = model.addVar(vtype="I", name="x(%s)"%i)
    
    model.addCons(quicksum(weight[i]*x[i] for i in objects) <= maxweight, "weight limit")
    
    model.setObjective(quicksum(value[i]*x[i] for i in objects), "maximize")
    model.data = x
    return model
In [38]:
def solveKnapsack2(objects, weight, value, maxweight):
    
    model = unlimitedknapsackModel(objects, weight, value, maxweight)
    model.optimize()
    x = model.data
    
    print("Total Price: ", model.getObjVal())
    for i in objects:
        print("%s" %i, model.getVal(x[i]))
    return model.getObjVal()

Let change the name of the items. This can be done because we were using a dictionary.

In [39]:
from pyscipopt import Model, multidict, quicksum
objects, weight, value = multidict({"almonds":[30, 240],
                                    "walnuts":[35, 300],
                                    "cashew":[10,100],
                                    "pistachio":[15,150],
                                    "plum":[35, 360],
                                    "cherry":[22,180],
                                    "mango":[29,220],
                                    "apple":[18, 140],
                                    "banana":[11, 90]})
# objects = [1,2,3,4,5,6,7,8,9]
# weight = {1:30, 2:35, 3:10, 4:15, 5:35, 6:22, 7:29, 8:18, 9:11}
# value = {1:240, 2:300, 3:100, 4:150, 5:360, 6:180, 7:220, 8:140, 9:90}
maxweight = 100
In [40]:
solveKnapsack2(objects, weight, value, maxweight)
Total Price:  1020.0
almonds 0.0
walnuts 0.0
cashew 3.0
pistachio 0.0
plum 2.0
cherry 0.0
mango 0.0
apple 0.0
banana -0.0
Out[40]:
1020.0

Remarks¶

  • Now it seems that object 3 is picked 3 times and object 5 twice.
  • Why?

Ideas¶

  • Where can you apply the Knapsack problem idea?
  • An example can be to determine the best movies to show in a film festival of a total time of 24 hours, with weights being the movie lengths and the price being the ratings (obtained from movielens).
  • Similarly what songs to sing in a Karaoke.
  • Another example can be if you were planning a trip, and the places you want to go are valued by some method and the time spent is the weight.
In [ ]: