In [1]:
from pyomo.environ import *
from pyomo.opt import *
opt = solvers.SolverFactory("glpk")
In [2]:
t = {'Team 1': 100, 'Team 2': 60, 'Team 3': 80}                                     # [Hours]
p = {'Microscope': 28, 'Thermometer': 5, 'Safety Goggles': 11, 'Bunsen Burner': 13} # [EUR]
r = {'Microscope': 40, 'Thermometer': 0, 'Safety Goggles': 0, 'Bunsen Burner': 20}  # [Units]

w = {('Team 1', 'Microscope'):     0.78, # [Hours]
     ('Team 1', 'Thermometer'):    0.30,
     ('Team 1', 'Safety Goggles'): 0.33,
     ('Team 1', 'Bunsen Burner'):  0,
     ('Team 2', 'Microscope'):     0.15,
     ('Team 2', 'Thermometer'):    0.43,
     ('Team 2', 'Safety Goggles'): 0,
     ('Team 2', 'Bunsen Burner'):  0.23,
     ('Team 3', 'Microscope'):     0.75,
     ('Team 3', 'Thermometer'):    0,
     ('Team 3', 'Safety Goggles'): 0.27,
     ('Team 3', 'Bunsen Burner'):  0.47}

P = list(p.keys())
T = list(t.keys())

model = ConcreteModel()
model.x = Var(P, within=NonNegativeReals)

def profit_rule(model):
    return sum(p[j]*model.x[j] for j in P)
model.profit = Objective(rule=profit_rule, sense=maximize)

def capacity_rule(model, i):
    return sum(w[i,j]*model.x[j] for j in P) <= t[i]
model.capacity_constraint = Constraint(T, rule=capacity_rule)

def fixed_contract_rule(model, j):
    return model.x[j] >= r[j]
model.contract_constraint = Constraint(P, rule=fixed_contract_rule)

model.dual = Suffix(direction=Suffix.IMPORT)
results = opt.solve(model)

model.x.get_values()
Out[2]:
{'Microscope': 40.0,
 'Thermometer': 103.757251854717,
 'Safety Goggles': 114.16007407147,
 'Bunsen Burner': 40.8016595759643}
In [3]:
model.profit.expr()
Out[3]:
3424.968648547291
In [4]:
for i in T:
    print ('{0:14s}: {1:6.2f}, {2:6.2f}'.format(i, 
           model.dual[model.capacity_constraint[i]],
           model.capacity_constraint[i].uslack()))
Team 1        :  12.00,  -0.00
Team 2        :   3.25,  -0.00
Team 3        :  26.07,  -0.00
In [5]:
for j in P:
    print ('{0:14s}: {1:6.2f}, {2:6.2f}'.format(j, 
           model.dual[model.contract_constraint[j]],
           model.contract_constraint[j].lslack()))
Microscope    :  -1.40,   0.00
Thermometer   :   0.00, 103.76
Safety Goggles:   0.00, 114.16
Bunsen Burner :   0.00,  20.80