Reputation: 443
I have written the following code for meal generation for different days, but I get the same meal everyday. I want to have "meat" and "Vegetarian" food_groups on alternate days.
my dataframe is as follows:
id name energy sugar Food_Groups
1 4-Grain Flakes 140 58.8 Breakfast
2 Beef Mince, Fried 1443 8.0 Meat
3 Pork 1000 3.0 Meat
4 cake 1200 150 Sweet
5 cheese 1100 140 Sweet
6 Juice 700 85 Drink
7 cabbage 60 13 vegetarian
8 cucumber 10 10 vegetarian
9 eggs 45 30 Breakfast
I am using PuLP to minimize sugar with a constraint on calories intake.
# Create the 'prob' variable to contain the problem data
prob = LpProblem("Simple Diet Problem",LpMinimize)
#create data variables and dictionary
food_items = list(df['name'])
calories = dict(zip(food_items,df['energy']))
sugars = dict(zip(food_items,df['sugar']))
food_vars =LpVariable.dicts("Food",food_items,lowBound=0,cat='Integer')
#Building the LP problem by adding the main objective function.
prob += lpSum([sugars[i]*food_vars[i] for i in food_items])
#adding calorie constraint
prob += lpSum([calories[f] * food_vars[f] for f in food_items]) >=
1800.0, "CalorieMinimum"
prob += lpSum([calories[f] * food_vars[f] for f in food_items]) <=
2200.0, "CalorieMaximum"
I loop over prob.solve() to generate menu for different days
prob.writeLP("SimpleDietProblem.lp")
days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
for i in days:
print(i)
prob.solve(PULP_CBC_CMD())
# print("Status:", LpStatus[prob.status])
print("Therefore, the optimal balanced diet consists of\n"+"-")
for v in prob.variables():
if v.varValue:
print(v.name , "=", v.varValue)
print("The total sugar of this balanced diet is: {}\n\n".format(round(value(prob.objective),2)))
My problem is that the output is repeated for all the days. How do I get "meat" and "vegetarian" on alternate days??
Upvotes: 1
Views: 887
Reputation: 306
@Khaned, the simplest way to do what you want is to setup two Problem instances. One will have Meat options and the other will have vegetarian options. Use each one on different days. You can alternate the starting problem for each week you want to run the plan to get a two-week meal plan.
You can setup the solvers like this:
prob1 = LpProblem("Simple Diet Problem Meat Day",LpMinimize)
prob2 = LpProblem("Simple Diet Problem Vegetarian Day",LpMinimize)
#create data variables and dictionary
day1_df = df[df['Food_Groups'] != 'vegetarian']
day1_items = list(day1_df['name'])
day1_calories = dict(zip(day1_items,day1_df['energy']))
day1_sugars = dict(zip(day1_items,day1_df['sugar']))
day2_df = df[df['Food_Groups'] != 'Meat']
day2_items = list(day2_df['name'])
day2_calories = dict(zip(day2_items,day2_df['energy']))
day2_sugars = dict(zip(day2_items,day2_df['sugar']))
# variables
day1_vars =LpVariable.dicts("Food",day1_items,lowBound=0,cat='Integer')
day2_vars =LpVariable.dicts("Food",day2_items,lowBound=0,cat='Integer')
#Building the LP problem by adding the main objective function.
prob1 += lpSum([day1_sugars[i]*day1_vars[i] for i in day1_items])
prob2 += lpSum([day2_sugars[i]*day2_vars[i] for i in day2_items])
If you still want to display options you don't choose between meat and vegetarian on all days, you need to create a more complex model with constraints specifying the food_vars for those items equal to zero.
Solve both problems once each.
Next, assign each day of the week one of the problems in a list like:
days = [('Monday', prob1), ('Tuesday', prob2), ...]
Then loop over the days and print the variables as you did already.
for day, prob in days:
print(day)
print("Therefore, the optimal balanced diet consists of\n"+"-")
for v in prob.variables():
if v.varValue:
print(v.name , "=", v.varValue)
print("The total sugar of this balanced diet is: {}\n\n".format(round(value(prob.objective),2)))
Upvotes: 2