Simple optimization notebook

A demonstration of the ease with which a novice could build experience by building a simple yet functional notebook that combines Python, MIP and ticdat.

This notebook reads a diet problem data set from the local file "diet_sample_data.xlsx". It optimizes the model, and if the solution is feasible, it displays the solution information.

Once a notebook like this is working, it should be an easy task to recycle the code into a robust, stand-alone solver such as this.


In [1]:
from ticdat import TicDatFactory
input_schema = TicDatFactory (
    categories = [["Name"],["Min Nutrition", "Max Nutrition"]],
    foods  = [["Name"],["Cost"]],
    nutrition_quantities = [["Food", "Category"], ["Quantity"]])

In [2]:
dat = input_schema.xls.create_tic_dat("diet_sample_data.xlsx")

In [3]:
import gurobipy as gu
mdl = gu.Model("diet")

In [4]:
nutrition = {c:mdl.addVar(lb=n["Min Nutrition"], ub=n["Max Nutrition"], name=c)
            for c,n in dat.categories.items()}
buy = {f:mdl.addVar(name=f) for f in dat.foods}

In [5]:
for c in dat.categories:
    mdl.addConstr(gu.quicksum(dat.nutrition_quantities[f,c]["Quantity"] * buy[f]
                  for f in dat.foods) == nutrition[c],
                  name = c)

In [6]:
mdl.setObjective(gu.quicksum(buy[f] * c["Cost"] for f,c in dat.foods.items()),
                     sense=gu.GRB.MINIMIZE)
mdl.optimize()


Optimize a model with 4 rows, 13 columns and 40 nonzeros
Coefficient statistics:
  Matrix range     [1e+00, 2e+03]
  Objective range  [9e-01, 3e+00]
  Bounds range     [6e+01, 2e+03]
  RHS range        [0e+00, 0e+00]
Presolve removed 0 rows and 3 columns
Presolve time: 0.01s
Presolved: 4 rows, 10 columns, 37 nonzeros

Iteration    Objective       Primal Inf.    Dual Inf.      Time
       0    0.0000000e+00   4.601562e+00   0.000000e+00      0s
       4    1.1828861e+01   0.000000e+00   0.000000e+00      0s

Solved in 4 iterations and 0.01 seconds
Optimal objective  1.182886111e+01

In [7]:
mdl.status == gu.GRB.OPTIMAL


Out[7]:
True

In [8]:
for f,x in buy.items():
    if x.x > 0:
        print "%-20s %s"%(f, x.x)


hamburger            0.604513888889
milk                 6.97013888889
ice cream            2.59131944444

In [9]:
for c,x in nutrition.items():
    print "%-20s %s"%(c, x.x)


protein              91.0
calories             1800.0
fat                  59.0559027778
sodium               1779.0

In [10]:
print "Total Cost: %s"%sum(dat.foods[f]["Cost"] * x.x for f,x in buy.items())


Total Cost: 11.8288611111

In [ ]: