I've set up the following LP problem and everything appears to be working except for my percent of mass constraint for salad greens. I want the mass of salad greens to be at least 40%, but I'm getting a syntax error with PuLP's lpSum, and I'm not sure how to reconcile it.
I'm have the following constraints for each salad:
At least 15 grams of protein
At least 2 and at most 8 grams of fat
At least 4 grams of carbohydrates
At most 200 milligrams of sodium
At least 40% leafy greens by mass.
from pulp import *
# Creates a list of the Ingredients
Ingredients = ['TOMATO', 'LETTUCE', 'SPINACH', 'CARROT', 'SUNFLOWER', 'TOFU', 'CHICKPEAS', 'OIL']
kcal = {'TOMATO': 21,
'LETTUCE': 16,
'SPINACH': 40,
'CARROT': 41,
'SUNFLOWER': 585,
'TOFU': 120,
'CHICKPEAS': 164,
'OIL': 884}
protein = {'TOMATO': 0.85,
'LETTUCE': 1.62,
'SPINACH': 2.86,
'CARROT': 0.93,
'SUNFLOWER': 23.4,
'TOFU': 16,
'CHICKPEAS': 9,
'OIL': 0}
fat = {'TOMATO': 0.33,
'LETTUCE': 0.20,
'SPINACH': 0.39,
'CARROT': 0.24,
'SUNFLOWER': 48.7,
'TOFU': 5.0,
'CHICKPEAS': 2.6,
'OIL': 100.0}
carbs = {'TOMATO': 4.64,
'LETTUCE': 2.37,
'SPINACH': 3.63,
'CARROT': 9.58,
'SUNFLOWER': 15.0,
'TOFU': 3.0,
'CHICKPEAS': 27.0,
'OIL': 0.0}
sodium = {'TOMATO': 9.0,
'LETTUCE': 28.0,
'SPINACH': 65.0,
'CARROT': 69.0,
'SUNFLOWER': 3.80,
'TOFU': 120.0,
'CHICKPEAS': 78.0,
'OIL': 0.0}
cost = {'TOMATO': 1.0,
'LETTUCE': 0.75,
'SPINACH': 0.50,
'CARROT': 0.50,
'SUNFLOWER': 0.45,
'TOFU': 2.15,
'CHICKPEAS': 0.95,
'OIL': 2.00}
# Create the 'prob' variable to contain the problem data
prob = LpProblem("The Salad Problem", LpMinimize)
# A dictionary called 'ingredient_vars' is created to contain the referenced Variables
ingredient_vars = LpVariable.dicts("Ingr",Ingredients,0)
# The objective function is added to 'prob' first
prob += lpSum([kcal[i]*ingredient_vars[i] for i in Ingredients]), "Total kCal of Ingredients per salad"
# The constraints are added to 'prob'
prob += lpSum([protein[i] * ingredient_vars[i] for i in Ingredients]) >= 15.0, "ProteinRequirement"
prob += 8.0 >= lpSum([fat[i] * ingredient_vars[i] for i in Ingredients]) >= 2.0, "FatRequirement"
prob += lpSum([carbs[i] * ingredient_vars[i] for i in Ingredients]) >= 4.0, "CarbRequirement"
prob += lpSum([sodium[i] * ingredient_vars[i] for i in Ingredients]) <= 200.0, "SodiumRequirement"
prob += lpSum(prob.variables()[2].varValue + prob.variables()[4].varValue) / lpSum([prob.variables()[i].varValue for i in range(8)]) >= 0.40, "GreensRequirement"
prob.solve()
# The status of the solution is printed to the screen
print("Status:", LpStatus[prob.status])
# Each of the variables is printed with it's resolved optimum value
for v in prob.variables():
print(v.name, "=", v.varValue)
# The optimised objective function value is printed to the screen
print("Total kCal of Ingredients per salad = ", value(prob.objective))
This is the constraint that's giving me the issue:
prob += lpSum(prob.variables()[2].varValue + prob.variables()[4].varValue) / lpSum([prob.variables()[i].varValue for i in range(8)]) >= 0.40, "GreensRequirement"
This gives an error for using the + operator on NoneType, since the variables don't have values yet. I'm just not sure exactly how to set up a constraint of this kind. I've looked through the PuLP docs on this, but I haven't had any luck figuring out the issue.

ingredient_vars[i]before and then access later vars byprob.variables()[2]? That looks a bit scary (probably some assumptions needed about ordering and co) (2) Yeah, as you have written, building a constraint while accessing a non-optimized variable-value can't work (3) This constraint of yours is probably non-convex formulated like this! Even if you would make pulp to accept it, the solver will break. You will need a different formulation. - sascha