The Data Overview is as given:
cj = cost per unit of food
aij = amount of nutrient i per unit of the given food j
mi = minimum amount of nutrient i required by the soldier
Mi = maximum amount of nutrient i required by the soldier
Variables:
xj = amount of food consumed
Objective function: Minimize total cost
Constraints: a. can't eat negative amount of food (xj greater than 0)
b. take in at least minimum amount of each nutrient
c. take in no more than maximum amount of each nutrient
d. additional constraints added below
I will be using the pulp library in Python 3 for this diet optimization problem.
!pip install xlrd
!pip install pulp
!pip install pandoc
from pulp import *
import pandas as pd
import numpy as np
Requirement already satisfied: xlrd in c:\users\pgaut\anaconda3\lib\site-packages (2.0.1) Requirement already satisfied: pulp in c:\users\pgaut\anaconda3\lib\site-packages (2.7.0) Requirement already satisfied: pandoc in c:\users\pgaut\anaconda3\lib\site-packages (2.3) Requirement already satisfied: plumbum in c:\users\pgaut\anaconda3\lib\site-packages (from pandoc) (1.8.2) Requirement already satisfied: ply in c:\users\pgaut\anaconda3\lib\site-packages (from pandoc) (3.11) Requirement already satisfied: pywin32 in c:\users\pgaut\anaconda3\lib\site-packages (from plumbum->pandoc) (305.1)
data = pd.read_excel("diet.xls")
data
Foods | Price/ Serving | Serving Size | Calories | Cholesterol mg | Total_Fat g | Sodium mg | Carbohydrates g | Dietary_Fiber g | Protein g | Vit_A IU | Vit_C IU | Calcium mg | Iron mg | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Frozen Broccoli | 0.16 | 10 Oz Pkg | 73.8 | 0.0 | 0.8 | 68.2 | 13.6 | 8.5 | 8.0 | 5867.4 | 160.2 | 159.0 | 2.3 |
1 | Carrots,Raw | 0.07 | 1/2 Cup Shredded | 23.7 | 0.0 | 0.1 | 19.2 | 5.6 | 1.6 | 0.6 | 15471.0 | 5.1 | 14.9 | 0.3 |
2 | Celery, Raw | 0.04 | 1 Stalk | 6.4 | 0.0 | 0.1 | 34.8 | 1.5 | 0.7 | 0.3 | 53.6 | 2.8 | 16.0 | 0.2 |
3 | Frozen Corn | 0.18 | 1/2 Cup | 72.2 | 0.0 | 0.6 | 2.5 | 17.1 | 2.0 | 2.5 | 106.6 | 5.2 | 3.3 | 0.3 |
4 | Lettuce,Iceberg,Raw | 0.02 | 1 Leaf | 2.6 | 0.0 | 0.0 | 1.8 | 0.4 | 0.3 | 0.2 | 66.0 | 0.8 | 3.8 | 0.1 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
62 | Crm Mshrm Soup,W/Mlk | 0.65 | 1 C (8 Fl Oz) | 203.4 | 19.8 | 13.6 | 1076.3 | 15.0 | 0.5 | 6.1 | 153.8 | 2.2 | 178.6 | 0.6 |
63 | Beanbacn Soup,W/Watr | 0.67 | 1 C (8 Fl Oz) | 172.0 | 2.5 | 5.9 | 951.3 | 22.8 | 8.6 | 7.9 | 888.0 | 1.5 | 81.0 | 2.0 |
64 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
65 | NaN | NaN | Minimum daily intake | 1500.0 | 30.0 | 20.0 | 800.0 | 130.0 | 125.0 | 60.0 | 1000.0 | 400.0 | 700.0 | 10.0 |
66 | NaN | NaN | Maximum daily intake | 2500.0 | 240.0 | 70.0 | 2000.0 | 450.0 | 250.0 | 100.0 | 10000.0 | 5000.0 | 1500.0 | 40.0 |
67 rows × 14 columns
The relevant libraries are installed and the dataset has also been loaded to the Jupyter environment. Upon inspection of the MS Excel file, only the first 64 rows are useful for the data analysis so it would be helpful to create a list of it.
dataTable = data[0:64] #this is the food data table
dataTable = dataTable.values.tolist() #convert the dataframe to a list
Create a list with names of nutrients.
nutrientNames = list(data.columns.values)
The minimum and maximum daily intake values are in bottom two rows in the MS Excel file. Get them.
minVal = data[65:66].values.tolist()
maxVal = data[66:67].values.tolist()
We will now take the nutrition components and create separate dictionaries for them. First, begin with a list of food names. Then, create a dictionary with cost of each food item and eventually a for loop to run through each nutrient/and its amount.
foods = [j[0] for j in dataTable]
cost = dict([(j[0], float(j[1])) for j in dataTable])
nutrients = []
for i in range(0,11):
nutrients.append(dict([(j[0], float(j[i+3])) for j in dataTable]))
Now, onto using our Pulp library to model the Linear Programming. First, create a LP Problem and then Python dictionary objects with the information provided to us in the data table. LpMinimize as we seek to minimize total cost. Then, define the continuos and binary variables needed for the solution.
prob = LpProblem('FoodOptimization', LpMinimize)
foodVars = LpVariable.dicts("Foods", foods, 0)
foodVars_selected = LpVariable.dicts("food_select", foods, 0, 1, LpBinary)
Objective Function
prob += lpSum([cost[f] * foodVars[f] for f in foods]), 'Total Cost'
Add Constraints as provided in the question
for i in range(0, 11):
prob += lpSum([nutrients[i][j] * foodVars[j] for j in foods]) >= minVal[0][i+3], 'min nutrient' + nutrientNames[i+3]
prob += lpSum([nutrients[i][j] * foodVars[j] for j in foods]) <= maxVal[0][i+3], 'max nutrient' + nutrientNames[i+3]
for food in foods:
prob += foodVars[food] >= 0.1 * foodVars_selected[food]
for food in foods:
prob += foodVars_selected[food] >= foodVars[food] * 0.000001
prob += foodVars_selected['Frozen Broccoli'] + foodVars_selected['Celery, Raw'] <= 1
prob += foodVars_selected['Roasted Chicken'] + foodVars_selected['Poached Eggs'] + foodVars_selected['Scrambled Eggs'] \
+ foodVars_selected['Bologna,Turkey'] + foodVars_selected['Frankfurter, Beef'] + foodVars_selected['Ham,Sliced,Extralean'] \
+ foodVars_selected['Kielbasa,Prk'] + foodVars_selected['Pizza W/Pepperoni'] + foodVars_selected['Hamburger W/Toppings'] \
+ foodVars_selected['Hotdog, Plain'] + foodVars_selected['Pork'] + foodVars_selected['Sardines in Oil'] \
+ foodVars_selected['White Tuna in Water'] + foodVars_selected['Chicknoodl Soup'] + foodVars_selected['Splt Pea&Hamsoup'] \
+ foodVars_selected['Vegetbeef Soup'] + foodVars_selected['Neweng Clamchwd'] + foodVars_selected['New E Clamchwd,W/Mlk'] \
+ foodVars_selected['Beanbacn Soup,W/Watr'] >=3, 'at least three proteins'
Solve the optimization problem!
prob.solve()
1
Print the optimized solution.
print()
print("The optimized solution is: \n")
for var in prob.variables():
if var.varValue > 0 and "food_select" not in var.name:
print(str(var.varValue) + " units of " + str(var).replace('Foods_',''))
The optimized solution is: 0.1 units of Bologna,Turkey 51.695579 units of Celery,_Raw 72.437846 units of Lettuce,Iceberg,Raw 2.8305897 units of Oranges 0.1 units of Poached_Eggs 13.559747 units of Popcorn,Air_Popped 0.1 units of Scrambled_Eggs
print("The total cost of optimal food is: $")
value(prob.objective)
The total cost of optimal food is: $
4.517558415