Figuring out a Balanced Diet at Wendy's with Python & PuLP
Mathew Chan
Posted on November 13, 2020
Overview
We'll use Python to solve a linear programming problem of finding what items to eat at Wendy's for a nutritional and balanced diet. You can expand this project to a food and diet app, or apply it to solve other LP problems.
Linear Programming
Linear Programming (LP) is used to generate optimal solutions that satisfy several constraints at once. One of the problems it can solve is the diet problem.
The goal of the diet problem is to select a set of foods that will satisfy a set of daily nutritional requirement at minimum cost. - NEOS Guide
Prequisites
- Python 3
- PuLP
pip install pulp
PuLP is a LP modeler written in Python. For this project, we don't need to write any LP algorithms. We simply define our problem, send the data, and PuLP's API will do the rest.
Breaking It Down
Let's break down the LP problem to three parts: the objective function, the constraints, and our working data.
- Objective Function: Minimize calorie intake
- Constraints: Satisfy nutritional requirements
- Data: Nutritional information of Wendy's menu
Declaring Problem and Objective
# Declare problem and whether the objective function is to maximize or minimize
problem = pulp.LpProblem(name="Calories",sense=pulp.LpMinimize)
# Declare menu list and nutritional information of each item
menu_list = ["single_cheeseburger", "double_cheeseburger", "small_fries", "small_cola"]
calories = [580, 820, 310, 160]
protein = [30, 48, 4, 0]
carbohydrates = [42, 42, 40, 55]
sodium = [1220, 1510, 330, 0]
# Declare nutritional requirements
nutrition_requirement_dict ={
"Calories": 2700.0,
"Protein" : 65.0, # g
"Carbohydrates" : 330.6, # g
"Sodium" : 7500, # mg
}
# Declare LpVariables for each menu item
LpVariableList = [pulp.LpVariable('{}'.format(x), cat='Integer', lowBound=0) for item in menu_list]
# Declare objective: to minimize calories
problem += pulp.lpDot(calories, LpVariableList)
We first declare our LpProblem problem and LpVariables for each menu item. In the LpProblem declaration we use LpMinimize for a minimization objective. To declare the objective, we pass calories as the first argument for the value to minimize, and the LpVariable list as the second argument.
Declaring Constraints
# Declare constraints
# Assume the daily energy requirements of a man aged 30-49 with low activity
problem += pulp.lpDot(protein, LpVariableList) >= nutrition_requirement_dict["Protein"]
problem += pulp.lpDot(carbohydrates, LpVariableList) >= nutrition_requirement_dict["Carbohydrates"]
problem += pulp.lpDot(sodium, LpVariableList) <= nutrition_requirement_dict["Sodium"]
We call lpDot() with each of the nutrient that we would like to set a constraint on and evaluate it to our nutrient requirement to create a boolean expression. Whenever we add a boolean expression to our problem it becomes an additional constraint. In this example, we want to satisfy the requirements of protein and carbohydrates but limit sodium intake.
Solving
When we are done defining our problem and constraints, we can simply call problem.solve()
# Solve
status = problem.solve()
print(pulp.LpStatus[status])
# Output Result
print("Result")
for menu_item in LpVariableList:
print(str(menu_item) + " × "+ str(int(menu_item.value())) )
for nutrient_name, nutrient_value in {"Calories": calories, "Protein": protein, "Carbohydrates": carbohydrates, "Sodium": sodium}.items():
print("*{}: {} Reference: {}".format(nutrient_name, str(round(pulp.lpDot(nutrient_value, LpVariableList).value())), nutrition_requirement_dict[nutrient_name]))
For the output, we first iterate through LpVariableList and show the value of each menu_item, which is the number of times they are chosen for the solution. Then we iterate through our nutrients and show their quantity by picking the above menu items.
Result
single_cheeseburger × 1
double_cheeseburger × 1
small_fries × 0
small_cola × 5
*Calories: 2200 Reference: 2700.0
*Protein: 78 Reference: 65.0
*Carbohydrates: 359 Reference: 330.6
*Sodium: 2730 Reference: 7500
Let's look at how well it did. One of each burger is selected with 5 cups of small cola. The final calorie count is 2200 which is way below 2700. Protein and carbohydrates also look good with a healthy amount of sodium.
Could this be the perfect meal?
Not yet. 5 cups of cola screams excess sugar and we haven't added vitamins and other nutrients to the equation. We will expand on this project in our next post.
Note: I'm still working on the second part of this post. You can follow me if you want to stay posted.
Summary
- What Linear Programming (LP) is and what problems it solves
- Defining a LP problem, an objective, and constraints
- Implementing LP with PuLP
Let me know if you found this helpful. :)
Part of the reason I chose Wendy's for this post is because of these funny tweets.
References
Posted on November 13, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.