-
Notifications
You must be signed in to change notification settings - Fork 257
/
Copy pathdiet.py
106 lines (86 loc) · 3.79 KB
/
diet.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
##@file diet.py
# @brief model for the modern diet problem
"""
Copyright (c) by Joao Pedro PEDROSO and Mikio KUBO, 2012
"""
# todo: can we make it work as "from pyscipopt import *"?
from pyscipopt import Model, quicksum, multidict
def diet(F, N, a, b, c, d):
"""diet -- model for the modern diet problem
Parameters:
- F: set of foods
- N: set of nutrients
- a[i]: minimum intake of nutrient i
- b[i]: maximum intake of nutrient i
- c[j]: cost of food j
- d[j][i]: amount of nutrient i in food j
Returns a model, ready to be solved.
"""
model = Model("modern diet")
# Create variables
x, y, z = {}, {}, {}
for j in F:
x[j] = model.addVar(vtype="I", name="x(%s)" % j)
y[j] = model.addVar(vtype="B", name="y(%s)" % j)
for i in N:
z[i] = model.addVar(lb=a[i], ub=b[i], name="z(%s)" % j)
v = model.addVar(vtype="C", name="v")
# Constraints:
for i in N:
model.addCons(quicksum(d[j][i] * x[j] for j in F) == z[i], name="Nutr(%s)" % i)
model.addCons(quicksum(c[j] * x[j] for j in F) == v, name="Cost")
for j in F:
model.addCons(y[j] <= x[j], name="Eat(%s)" % j)
# Objective:
model.setObjective(quicksum(y[j] for j in F), "maximize")
model.data = x, y, z, v
return model
def make_inst():
"""make_inst: prepare data for the diet model"""
F, c, d = multidict({ # cost # composition
"QPounder": [1.84, {"Cal": 510, "Carbo": 34, "Protein": 28,
"VitA": 15, "VitC": 6, "Calc": 30, "Iron": 20}],
"McLean": [2.19, {"Cal": 370, "Carbo": 35, "Protein": 24, "VitA": 15,
"VitC": 10, "Calc": 20, "Iron": 20}],
"Big Mac": [1.84, {"Cal": 500, "Carbo": 42, "Protein": 25,
"VitA": 6, "VitC": 2, "Calc": 25, "Iron": 20}],
"FFilet": [1.44, {"Cal": 370, "Carbo": 38, "Protein": 14,
"VitA": 2, "VitC": 0, "Calc": 15, "Iron": 10}],
"Chicken": [2.29, {"Cal": 400, "Carbo": 42, "Protein": 31,
"VitA": 8, "VitC": 15, "Calc": 15, "Iron": 8}],
"Fries": [.77, {"Cal": 220, "Carbo": 26, "Protein": 3,
"VitA": 0, "VitC": 15, "Calc": 0, "Iron": 2}],
"McMuffin": [1.29, {"Cal": 345, "Carbo": 27, "Protein": 15,
"VitA": 4, "VitC": 0, "Calc": 20, "Iron": 15}],
"1% LFMilk": [.60, {"Cal": 110, "Carbo": 12, "Protein": 9,
"VitA": 10, "VitC": 4, "Calc": 30, "Iron": 0}],
"OrgJuice": [.72, {"Cal": 80, "Carbo": 20, "Protein": 1,
"VitA": 2, "VitC": 120, "Calc": 2, "Iron": 2}],
})
N, a, b = multidict({ # min,max intake
"Cal": [2000, None],
"Carbo": [350, 375],
"Protein": [55, None],
"VitA": [100, None],
"VitC": [100, None],
"Calc": [100, None],
"Iron": [100, None],
})
return F, N, a, b, c, d
if __name__ == "__main__":
F, N, a, b, c, d = make_inst()
for b["Cal"] in [None, 3500, 3000, 2500]:
print("\nDiet for a maximum of {0} calories".format(b["Cal"] if b["Cal"] != None else "unlimited"))
model = diet(F, N, a, b, c, d)
model.hideOutput() # silent mode
model.optimize()
print("Optimal value:", model.getObjVal())
x, y, z, v = model.data
for j in x:
if model.getVal(x[j]) > 0:
print("{0:30s}: {1:3.1f} dishes --> {2:4.2f} added to objective".format(j, model.getVal(x[j]),
model.getVal(y[j])))
print("amount spent:", model.getObjVal())
print("amount of nutrients:")
for i in z:
print("{0:30s}: {1:4.2f}".format(i, model.getVal(z[i])))