Here is a short answer in the form of a sketch of a working example:
Create a problem and add hard limits and a goal.
prob = LpProblem("My Problem", LpMinimize) ....
After you have done this, define a soft (elastic) constraint and add it to the problem using pulp.prob.extend() , for example:
c_e_LHS = LpAffineExpression([(var1,coeff1), (var2,coeff2)])
At this point, the problem has been modified to include a soft (elastic) constraint, and you can solve it. $ \ Rct $.
Here is a longer answer: this question will be answered in the group of the "pulp or discuss" group in the section adding elastic restrictions . I created the following example for my own purposes based on this discussion and a longer formulation of the mixing problem on the PuLP documentation website.
First you create a problem:
from pulp import * prob = LpProblem("The Whiskas Problem", LpMinimize)
Create a list of ingredients:
Ingredients = ['CHICKEN', 'BEEF', 'MUTTON', 'RICE', 'WHEAT', 'GEL']
A dictionary of the cost of each of the ingredients is created:
costs = {'CHICKEN': 0.013, 'BEEF': 0.008, 'MUTTON': 0.010, 'RICE': 0.002, 'WHEAT': 0.005, 'GEL': 0.001}
A dictionary of the percentage of protein in each of the ingredients is created:
proteinPercent = {'CHICKEN': 0.100, 'BEEF': 0.200, 'MUTTON': 0.150, 'RICE': 0.000, 'WHEAT': 0.040, 'GEL': 0.000}
A dictionary of fat percentage in each of the ingredients is created:
fatPercent = {'CHICKEN': 0.080, 'BEEF': 0.100, 'MUTTON': 0.110, 'RICE': 0.010, 'WHEAT': 0.010, 'GEL': 0.000}
A dictionary of fiber percentages is created in each of the ingredients:
fibrePercent = {'CHICKEN': 0.001, 'BEEF': 0.005, 'MUTTON': 0.003, 'RICE': 0.100, 'WHEAT': 0.150, 'GEL': 0.000}
Created a dictionary of salt percent in each of the ingredients:
saltPercent = {'CHICKEN': 0.002, 'BEEF': 0.005, 'MUTTON': 0.007, 'RICE': 0.002, 'WHEAT': 0.008, 'GEL': 0.000}
Create the variable "prob" to contain these problems:
prob = LpProblem("The Whiskas Problem", LpMinimize)
A dictionary called "component_stars_vars" has been created that contains reference variables:
ingredient_vars = LpVariable.dicts("Ingr",Ingredients,0)
Add target:
prob += lpSum([costs[i]*ingredient_vars[i] for i in Ingredients]), "Total Cost of Ingredients per can"
Create hard limits ( where my example starts to deviate from the text in the documentation ):
c1 = lpSum([ingredient_vars[i] for i in Ingredients]) == 100, "PercentagesSum" c2 = lpSum([proteinPercent[i] * ingredient_vars[i] for i in Ingredients]) >= 8.0, "ProteinRequirement" c3 = lpSum([fatPercent[i] * ingredient_vars[i] for i in Ingredients]) >= 6.0, "FatRequirement" c4 = lpSum([fibrePercent[i] * ingredient_vars[i] for i in Ingredients]) <= 2.0, "FibreRequirement" c5 = lpSum([saltPercent[i] * ingredient_vars[i] for i in Ingredients]) <= 0.4, "SaltRequirement"
Add hard limits:
for con in [c1,c2,c3,c4,c5]: prob += con
Define a left constraint expression that should be elastic:
c6_LHS = LpAffineExpression([(ingredient_vars['GEL'],1), (ingredient_vars['BEEF'],1)])
Define an elastic limit: the total amount of gel and beef is less than 30%:
c6= LpConstraint(e=c6_LHS, sense=-1, name='GelBeefTotal', rhs=30)
Define the elastic constraint:
c6_elastic = c6.makeElasticSubProblem(penalty = 100, proportionFreeBoundList = [.02,.02])
And this way to add an elastic (i.e. soft) constraint to the problem:
prob.extend(c6_elastic)
Solve the problem:
prob.writeLP("WhiskasModel.lp") prob.solve()
Print the optimal solution:
for v in prob.variables(): print v.name, "=", v.varValue
If you play with fines and restrictions, you can check that it works as advertised.
PS, I understand that the name of the question can be misleading. Adding an elastic subtask reduces to adding some conditions to the object, which corresponds to a “soft constraint”. A soft restriction is not a restriction - it is a reduction from a set of cost conditions in the lens.