Khaned
Khaned

Reputation: 443

pulp solve function gives same output

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

Answers (1)

Wesley Dyk
Wesley Dyk

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

Related Questions