NB you will might need some sort of %env PATH =
statement here to get insure the AMPL engine can be found
In [2]:
from amplpy import AMPL
import amplpy
from pandas import DataFrame
FYI - ticdat.testing.testampl.convert_to_dicts_that_can_be_turned_into_DataFrames
makes it easy to create
the hardcoded dict
objects that are then used to create the DataFrame
objects below.
In [3]:
categories = DataFrame({'Name': {0: u'calories',
1: u'fat',
2: u'protein',
3: u'sodium'},
'n_max': {0: 2200.0, 1: 65.0, 2: float('inf'), 3: 1779.0},
'n_min': {0: 1800, 1: 0, 2: 91, 3: 0}})
In [4]:
foods = DataFrame({'Name': {0: u'chicken',
1: u'fries',
2: u'hamburger',
3: u'hot dog',
4: u'ice cream',
5: u'macaroni',
6: u'milk',
7: u'pizza',
8: u'salad'},
'cost': {0: 2.8900000000000001,
1: 1.8899999999999999,
2: 2.4900000000000002,
3: 1.5,
4: 1.5900000000000001,
5: 2.0899999999999999,
6: 0.89000000000000001,
7: 1.99,
8: 2.4900000000000002}})
In [5]:
nutrition_quantities = DataFrame({'Category': {0: u'calories', 1: u'fat', 2: u'protein', 3: u'sodium',
4: u'calories', 5: u'fat', 6: u'protein', 7: u'sodium', 8: u'calories', 9: u'fat', 10: u'protein',
11: u'sodium', 12: u'calories', 13: u'fat', 14: u'protein', 15: u'sodium', 16: u'calories', 17: u'fat',
18: u'protein', 19: u'sodium', 20: u'calories', 21: u'fat', 22: u'protein', 23: u'sodium', 24: u'calories',
25: u'fat', 26: u'protein', 27: u'sodium', 28: u'calories', 29: u'fat', 30: u'protein', 31: u'sodium',
32: u'calories', 33: u'fat', 34: u'protein', 35: u'sodium'},
'Food': {0: u'chicken', 1: u'chicken', 2: u'chicken', 3: u'chicken', 4: u'fries', 5: u'fries', 6: u'fries',
7: u'fries', 8: u'hamburger', 9: u'hamburger', 10: u'hamburger', 11: u'hamburger', 12: u'hot dog',
13: u'hot dog', 14: u'hot dog', 15: u'hot dog', 16: u'ice cream', 17: u'ice cream', 18: u'ice cream',
19: u'ice cream', 20: u'macaroni', 21: u'macaroni', 22: u'macaroni', 23: u'macaroni', 24: u'milk', 25: u'milk',
26: u'milk', 27: u'milk', 28: u'pizza', 29: u'pizza', 30: u'pizza', 31: u'pizza', 32: u'salad', 33: u'salad',
34: u'salad', 35: u'salad'},
'amt': {0: 420.0, 1: 10.0, 2: 32.0, 3: 1190.0, 4: 380.0, 5: 19.0, 6: 4.0, 7: 270.0, 8: 410.0, 9: 26.0,
10: 24.0, 11: 730.0, 12: 560.0, 13: 32.0, 14: 20.0, 15: 1800.0, 16: 330.0, 17: 10.0, 18: 8.0, 19: 180.0,
20: 320.0, 21: 10.0, 22: 12.0, 23: 930.0, 24: 100.0, 25: 2.5, 26: 8.0, 27: 125.0, 28: 320.0, 29: 12.0,
30: 15.0, 31: 820.0, 32: 320.0, 33: 12.0, 34: 31.0, 35: 1230.0}})
In [6]:
mod_str = """
set CAT;
set FOOD;
param cost {FOOD} > 0;
param n_min {CAT} >= 0;
param n_max {i in CAT} >= n_min[i];
param amt {FOOD, CAT} >= 0;
var Buy {j in FOOD} >= 0;
var Consume {i in CAT } >= n_min [i], <= n_max [i];
minimize Total_Cost: sum {j in FOOD} cost[j] * Buy[j];
subject to Diet {i in CAT}:
Consume[i] = sum {j in FOOD} amt[j,i] * Buy[j];
"""
In [7]:
ampl = AMPL()
ampl.setOption('solver', 'gurobi')
ampl.eval(mod_str)
In [8]:
def df_to_ampl_df(df, pkfields):
assert set(df.columns).issuperset(pkfields)
rtn = amplpy.DataFrame(index=pkfields)
for f in pkfields:
rtn.setColumn(f, list(df[f]))
for f in df.columns:
if f not in pkfields:
rtn.addColumn(f, list(df[f]))
return rtn
In [9]:
ampl.setData(df_to_ampl_df(categories, ("Name",)), "CAT")
ampl.setData(df_to_ampl_df(foods, ("Name",)), "FOOD")
ampl.setData(df_to_ampl_df(nutrition_quantities, ('Food', 'Category')))
In [10]:
# should find objective 11.82886111
ampl.solve()