Quick Start using lists and dictionaries#
Description: Quick Start using lists and dictionaries to load and retrieve data
Tags: amplpy, quick-start, highlights
Notebook author: Filipe Brandão <fdabrandao@gmail.com>
# Install dependencies
%pip install -q amplpy pandas numpy
# Google Colab & Kaggle integration
from amplpy import AMPL, ampl_notebook
ampl = ampl_notebook(
modules=["highs"], # modules to install
license_uuid="default", # license to use
) # instantiate AMPL object and register magics
Diet Model#
Consider the problem of choosing prepared foods to meet certain nutritional requirements.
Sets:
NUTR
: set of nutrients to considerFOOD
: set of food to consider
Parameters:
cost {FOOD}
: cost of each foodf_min {FOOD}
: minimum amount of food to buyf_max {FOOD}
: maximum amount of food to buyn_min {NUTR}
: minimum amount required of each nutrientn_max {NUTR}
: maximum amount allowed of each nutrientamt {NUTR, FOOD}
: amount of each nutrient in each food
Variables:
Buy {FOOD}
: amount of food to buy
Objective:
Total_Cost
: total cost of the diet
Constraints:
Diet {NUTR}
: ensure that the nutritional requirements are satisfied by the diet.
The problem is then modeled as follows:
%%ampl_eval
reset;
set NUTR;
set FOOD;
param cost {FOOD} > 0;
param f_min {FOOD} >= 0;
param f_max {j in FOOD} >= f_min[j];
param n_min {NUTR} >= 0;
param n_max {i in NUTR} >= n_min[i];
param amt {NUTR,FOOD} >= 0;
var Buy {j in FOOD} >= f_min[j], <= f_max[j];
minimize Total_Cost: sum {j in FOOD} cost[j] * Buy[j];
subject to Diet {i in NUTR}:
n_min[i] <= sum {j in FOOD} amt[i,j] * Buy[j] <= n_max[i];
Load the data using lists and dictionaries#
# foods[food] = (cost, f_min, f_max)
foods = {
"BEEF": (3.59, 2, 10),
"CHK": (2.59, 2, 10),
"FISH": (2.29, 2, 10),
"HAM": (2.89, 2, 10),
"MCH": (1.89, 2, 10),
"MTL": (1.99, 2, 10),
"SPG": (1.99, 2, 10),
"TUR": (2.49, 2, 10),
}
# nutrients[nutr] = (n_min, n_max)
nutrients = {
"A": (700, 20000),
"C": (700, 20000),
"B1": (700, 20000),
"B2": (700, 20000),
"NA": (0, 50000),
"CAL": (16000, 24000),
}
ampl.set["FOOD"] = list(foods.keys())
ampl.param["cost"] = {food: cost for food, (cost, _, _) in foods.items()}
ampl.param["f_min"] = {food: f_min for food, (_, f_min, _) in foods.items()}
ampl.param["f_max"] = {food: f_max for food, (_, _, f_max) in foods.items()}
ampl.set["NUTR"] = list(nutrients.keys())
ampl.param["n_min"] = {nutr: n_min for nutr, (n_min, _) in nutrients.items()}
ampl.param["n_max"] = {nutr: n_max for nutr, (_, n_max) in nutrients.items()}
amounts = [
[60, 8, 8, 40, 15, 70, 25, 60],
[20, 0, 10, 40, 35, 30, 50, 20],
[10, 20, 15, 35, 15, 15, 25, 15],
[15, 20, 10, 10, 15, 15, 15, 10],
[928, 2180, 945, 278, 1182, 896, 1329, 1397],
[295, 770, 440, 430, 315, 400, 379, 450],
]
ampl.param["amt"] = {
(nutrient, food): amounts[i][j]
for i, nutrient in enumerate(nutrients)
for j, food in enumerate(foods)
}
Solve with HiGHS#
# Specify the solver to use (e.g., HiGHS)
ampl.option["solver"] = "highs"
# Solve
ampl.solve()
# Stop if the model was not solved
assert ampl.get_value("solve_result") == "solved"
# Get objective entity by AMPL name
totalcost = ampl.get_objective("Total_Cost")
# Print it
print("Objective is:", totalcost.value())
HiGHS 1.4.0:HiGHS 1.4.0: optimal solution; objective 119.9897589
4 simplex iterations
0 barrier iterations
absmipgap=119.99, relmipgap=inf
Objective is: 119.98975893599335
Reassign data for specific instances and resolve#
# Reassign data - specific instances
cost = ampl.get_parameter("cost")
cost.set_values({"BEEF": 5.01, "HAM": 4.55})
print("Increased costs of beef and ham.")
# Resolve and display objective
ampl.solve()
# Stop if the model was not solved
assert ampl.get_value("solve_result") == "solved"
print("New objective value:", totalcost.value())
Increased costs of beef and ham.
HiGHS 1.4.0:HiGHS 1.4.0: optimal solution; objective 144.0120033
0 simplex iterations
0 barrier iterations
absmipgap=144.012, relmipgap=inf
New objective value: 144.01200332502077
Reassign data for all instances and resolve#
# Reassign data - all instances
cost.set_values(
{
"BEEF": 3,
"CHK": 5,
"FISH": 5,
"HAM": 6,
"MCH": 1,
"MTL": 2,
"SPG": 5.01,
"TUR": 4.55,
}
)
print("Updated all costs.")
# Resolve and display objective
ampl.solve()
# Stop if the model was not solved
assert ampl.get_value("solve_result") == "solved"
print("New objective value:", totalcost.value())
Updated all costs.
HiGHS 1.4.0:HiGHS 1.4.0: optimal solution; objective 164.10625
4 simplex iterations
0 barrier iterations
absmipgap=164.106, relmipgap=inf
New objective value: 164.10625
Get the values of the variable Buy in a pandas.DataFrame object#
df = ampl.get_variable("Buy").to_pandas()
df
Buy.val | |
---|---|
BEEF | 10.000000 |
CHK | 2.000000 |
FISH | 2.000000 |
HAM | 6.851974 |
MCH | 10.000000 |
MTL | 10.000000 |
SPG | 6.765351 |
TUR | 2.000000 |
Get the values of an expression into a pandas.DataFrame object#
df = ampl.get_data("{j in FOOD} 100*Buy[j]/Buy[j].ub").to_pandas()
df
100*Buy[j]/(Buy[j].ub) | |
---|---|
BEEF | 100.000000 |
CHK | 20.000000 |
FISH | 20.000000 |
HAM | 68.519737 |
MCH | 100.000000 |
MTL | 100.000000 |
SPG | 67.653509 |
TUR | 20.000000 |