None
# IMPORT DATA FILES USED BY THIS NOTEBOOK
import os, requests
file_links = [("data/knapsack_data.csv", "https://ndcbe.github.io/CBE60499/data/knapsack_data.csv")]
# This cell has been added by nbpages. Run this cell to download data files required for this notebook.
for filepath, fileurl in file_links:
stem, filename = os.path.split(filepath)
if stem:
if not os.path.exists(stem):
os.mkdir(stem)
if not os.path.isfile(filepath):
with open(filepath, 'wb') as f:
response = requests.get(fileurl)
f.write(response.content)
Due Date: 2/16/2021
# This code cell installs packages on Colab
import sys
if "google.colab" in sys.modules:
!wget "https://raw.githubusercontent.com/ndcbe/CBE60499/main/notebooks/helper.py"
import helper
helper.install_idaes()
helper.install_ipopt()
helper.install_glpk()
helper.download_data(['knapsack_data.xlsx','knapsack_data.csv'])
## IMPORT LIBRARIES
from pyomo.environ import *
import pandas as pd
Special thanks to the Pyomo team for create these excercises as part of their excellent PyomoFest workshop.
Solve the knapsack problem given below using GLPK and answer the following questions:
Which items are acquired in the optimal solution?
What is the value of the selected items?
A = ['hammer', 'wrench', 'screwdriver', 'towel']
b = {'hammer':8, 'wrench':3, 'screwdriver':6, 'towel':11}
w = {'hammer':5, 'wrench':7, 'screwdriver':4, 'towel':3}
W_max = 14
model = ConcreteModel()
model.x = Var( A, within=Binary )
model.obj = Objective(
expr = sum( b[i]*model.x[i] for i in A ),
sense = maximize )
model.weight_con = Constraint(
expr = sum( w[i]*model.x[i] for i in A ) <= W_max )
# YOUR SOLUTION HERE
model.display()
Question Answers
Fill in here
Fill in here
Complete the missing lines in the code below to produce formatted output: print the total weight, the value of the items selected (the objective), and the items acquired in the optimal solution. Note, the Pyomo value function should be used to get the floating point value of Pyomo modeling components (e.g., print(value(model.x[i])).
A = ['hammer', 'wrench', 'screwdriver', 'towel']
b = {'hammer':8, 'wrench':3, 'screwdriver':6, 'towel':11}
w = {'hammer':5, 'wrench':7, 'screwdriver':4, 'towel':3}
W_max = 14
model = ConcreteModel()
model.x = Var( A, within=Binary )
model.obj = Objective(
expr = sum( b[i]*model.x[i] for i in A ),
sense = maximize )
model.weight_con = Constraint(
expr = sum( w[i]*model.x[i] for i in A ) <= W_max )
opt = SolverFactory('glpk')
opt_success = opt.solve(model)
total_weight = sum( w[i]*value(model.x[i]) for i in A )
# YOUR SOLUTION HERE
print('-------------------------')
Using your code from Question 1.2, if we were to increase the value of the wrench, at what point would it become selected as part of the optimal solution?
# YOUR SOLUTION HERE
Question Answer
Fill in here
In the code above, the data is hardcoded at the top of the file. Instead of hardcoding the data, use Python to load the data from a difference source. You may use Pandas to load data from 'knapsack_data.xlsx' into a dataframe. You will then need to write code to obtain a dictionary from the dataframe.
df_items = pd.read_excel('./data/knapsack_data.xlsx', sheet_name='data', header=0, index_col=0)
W_max = 14
A = df_items.index.tolist()
# YOUR SOLUTION HERE
model = ConcreteModel()
model.x = Var( A, within=Binary )
model.obj = Objective(
expr = sum( b[i]*model.x[i] for i in A ),
sense = maximize )
model.weight_con = Constraint(
expr = sum( w[i]*model.x[i] for i in A ) <= W_max )
opt = SolverFactory('glpk')
opt_success = opt.solve(model)
total_weight = sum( w[i]*value(model.x[i]) for i in A )
print('Total Weight:', total_weight)
print('Total Benefit:', value(model.obj))
print('%12s %12s' % ('Item', 'Selected'))
print('=========================')
for i in A:
acquired = 'No'
if value(model.x[i]) >= 0.5:
acquired = 'Yes'
print('%12s %12s' % (i, acquired))
print('-------------------------')
Solve the knapsack problem with IPOPT instead of glpk. Print the solution values for model.x. What happened? Why?
Hint: Switch glpk
to ipopt
in the call to SolverFactory
.
from pyomo.environ import *
A = ['hammer', 'wrench', 'screwdriver', 'towel']
b = {'hammer':8, 'wrench':3, 'screwdriver':6, 'towel':11}
w = {'hammer':5, 'wrench':7, 'screwdriver':4, 'towel':3}
W_max = 14
model = ConcreteModel()
model.x = Var( A, within=Binary )
model.obj = Objective(
expr = sum( b[i]*model.x[i] for i in A ),
sense = maximize )
model.weight_con = Constraint(
expr = sum( w[i]*model.x[i] for i in A ) <= W_max )
# YOUR SOLUTION HERE
opt_success = opt.solve(model)
model.pprint()
Question Answers
Fill in here
Rules are important for defining in-dexed constraints, however, they can also be used for single (i.e. scalar) constraints. Reimplement the knapsack model from Question 1.1 using rules for the objective and the constraints.
# YOUR SOLUTION HERE
Consider again the knapsack problem. Assume now that we can acquire multiple items of the same type. In this new formulation, $x_i$ is now an integer variable instead of a binary variable. One way to formulate this problem is as follows:
$\max_{q,x} \sum_{i\in{A}}v_ix_i$
s.t. $\sum_{i\in{A}}w_ix_i\leq W_{max}$
$x_i=\sum_{j=0}^Njq_{i,j}, \forall i \in{A}$
$0\leq x\leq N$
$q_{i,j} \in {0,1}, \forall i \in A, j \in {0...N}$
Starting with your code from Question 2.1, implement this new formulation and solve. Is the solution surprising?
# YOUR SOLUTION HERE
Question Answer
Fill in here