[PYTHON] Penser les menus par l'optimisation des combinaisons

Problème

Le médecin m'a dit de limiter les calories dans mon alimentation hebdomadaire. De plus, la quantité minimale requise d'éléments nutritifs A et d'éléments nutritifs B a également été indiquée. Comment puis-je manger ce que j'aime le plus possible?

Formulation

C'est le problème d'allocation dans Problème d'optimisation de combinaison. Supposons que les candidats pour la cuisine soient donnés, et exprimons lequel choisir avec la variable 0-1 $ x $.

Variables $ x_i \ in \ {0, 1 \} $ $ i $ Choix du troisième plat >
Objectif Fonction $ \ sum_i {Preference_i x_i} $ $ \ rightarrow $ Maximum
Contraintes $ \ sum_i {x_i} = 7 $ Choisissez 7 jours
$ \ sum_i {calorie_i x_i} \ le 90 $ limite calorique
$ \ sum_i {nutriments A_i x_i} \ ge 95 $ Montant minimum d'acquisition
$ \ sum_i {Nutrition B_i x_i} \ ge 95 $ Montant minimum d'acquisition

Essayez de résoudre avec python

La bibliothèque d'optimisation est [pulp](http://qiita.com/Tsutomu-KKE@github/items/bfbf4c185ed7004b5721#%E3%82%BD%E3%83%95%E3%83%88%E3%81% AE% E3% 82% A4% E3% 83% B3% E3% 82% B9% E3% 83% 88% E3% 83% BC% E3% 83% AB). Tout d'abord, créons des données factices.

python


import numpy as np, pandas as pd
from pulp import *
menu = ['bol de boeuf', 'Oyakodon', 'Escalope de porc sur riz', 'Bol de thon', 'Bol Negitoro', 'sushi chirashi',
        'Aubergine Mao', 'Doria', 'Riz à l'omelette', 'Riz sauté', 'curry et riz']
n = len(menu)
np.random.seed(1)
a = pd.DataFrame({
        'Nom de la cuisine': menu,
        'calorie': np.random.randint(10,20,n),
        'Nutriment A': np.random.randint(10,20,n),
        'Nutriment B': np.random.randint(10,20,n),
        'Préférence': np.random.randint(10,20,n),
    })
print(a)
Nom de la cuisine Préférence calorie Nutriment A Nutriment B
0 bol de boeuf 18 15 14
1 Oyakodon 13 18 15
2 Escalope de porc sur riz 19 19 12
3 Bol de thon 18 15 14
4 Bol Negitoro 17 10 12
5 sushi chirashi 13 10 14
6 Aubergine Mao 16 11 17
7 Doria 15 17 17
8 Riz à l'omelette 11 16 19
9 Riz sauté 19 19 11
10 curry et riz 13 12 17

Résolvons-le.

python


m = LpProblem(sense=LpMaximize) #Problème de maximisation
a['x'] = [LpVariable('x%d'%i, cat=LpBinary) for i in range(n)] #sélectionner/ne pas faire
m += lpDot(a.Préférence, a.x) # Préférenceを最大化
m += lpSum(a.x) == 7 #Une semaine de menu
m += lpDot(a.calorie, a.x) <= 90
m += lpDot(a.Nutriment A, a.x) >= 95
m += lpDot(a.Nutriment B, a.x) >= 95
m.solve()
if m.status == 1: # Optimal
    a['val'] = a.x.apply(lambda v: value(v)) #résultat
    print(a[a.val == 1].Nom de la cuisine)
>>>
0 bol de boeuf
3 bol à feu en fer
4 bol Negitoro
5 sushis Chirashi
6 aubergines Mao
7 Doria
10 riz au curry

Docker Si vous voulez essayer avec Docker, exécutez ce qui suit pour ouvrir l'hôte dans votre navigateur et Jupyter démarrera. La bibliothèque est également Diverses installations.

docker run -d -p 80:8888 tsutomu7/jupyter

c'est tout

Recommended Posts