My doctor told me to limit the calories in my weekly diet. In addition, the minimum required amount of nutrient A and nutrient B was also instructed. How can I eat what I like as much as possible?
It is an allocation problem in Combinatorial optimization problem. Let's assume that cooking candidates are given, and let's express which one to choose with the 0-1 variable $ x $.
Variables td> | $ x_i \ in \ {0, 1 \} $ td> | $ i $ Whether to choose the second dish td> tr> > |
Objective Function td> | $ \ sum_i {Preference_i x_i} $ td> | $ \ rightarrow $ Maximum td> tr> |
Constraints td> | $ \ sum_i {x_i} = 7 $ td> | Choose 7 days td> tr> |
td> | $ \ sum_i {calorie_i x_i} \ le 90 $ td> | calorie restriction td> tr> |
td> | $ \ sum_i {Nutrients A_i x_i} \ ge 95 $ td> | Minimum acquisition amount td> tr> |
td> | $ \ sum_i {Nutrients B_i x_i} \ ge 95 $ td> | Minimum acquisition amount td> tr> |
The optimization library is [pulp](http://qiita.com/Tsutomu-KKE@github/items/bfbf4c185ed7004b5721#%E3%82%BD%E3%83%95%E3%83%88%E3%81% Use AE% E3% 82% A4% E3% 83% B3% E3% 82% B9% E3% 83% 88% E3% 83% BC% E3% 83% AB). First, let's create dummy data.
python
import numpy as np, pandas as pd
from pulp import *
menu = ['beef bowl', 'Oyakodon', 'Pork cutlet on rice', 'Tuna bowl', 'Negitoro bowl', 'chirashi sushi',
'Eggplant with Mao', 'Doria', 'Omelette rice', 'Fried rice', 'Curry and rice']
n = len(menu)
np.random.seed(1)
a = pd.DataFrame({
'Cooking name': menu,
'calorie': np.random.randint(10,20,n),
'Nutrient A': np.random.randint(10,20,n),
'Nutrient B': np.random.randint(10,20,n),
'Preference': np.random.randint(10,20,n),
})
print(a)
Cooking name | Preference | calorie | Nutrient A | Nutrient B |
---|---|---|---|---|
0 | beef bowl | 18 | 15 | 14 |
1 | Oyakodon | 13 | 18 | 15 |
2 | Pork cutlet on rice | 19 | 19 | 12 |
3 | Tuna bowl | 18 | 15 | 14 |
4 | Negitoro bowl | 17 | 10 | 12 |
5 | chirashi sushi | 13 | 10 | 14 |
6 | Eggplant with Mao | 16 | 11 | 17 |
7 | Doria | 15 | 17 | 17 |
8 | Omelette rice | 11 | 16 | 19 |
9 | Fried rice | 19 | 19 | 11 |
10 | Curry and rice | 13 | 12 | 17 |
Let's solve it.
python
m = LpProblem(sense=LpMaximize) #Maximization problem
a['x'] = [LpVariable('x%d'%i, cat=LpBinary) for i in range(n)] #select/do not do
m += lpDot(a.Preference, a.x) # Preferenceを最大化
m += lpSum(a.x) == 7 #Menu for one week
m += lpDot(a.calorie, a.x) <= 90
m += lpDot(a.Nutrient A, a.x) >= 95
m += lpDot(a.Nutrient B, a.x) >= 95
m.solve()
if m.status == 1: # Optimal
a['val'] = a.x.apply(lambda v: value(v)) #result
print(a[a.val == 1].Cooking name)
>>>
0 beef bowl
3 Tekkadon
4 Negitoro bowl
5 Chirashizushi
6 Eggplant with Mao
7 Doria
10 curry rice
Docker If you want to give it a try with Docker, run the following to open the host in your browser and Jupyter will start. The library is also installed variously.
docker run -d -p 80:8888 tsutomu7/jupyter
that's all
Recommended Posts