How can I use the elastic subproblem in PuLP as a limitation?

In Python PuLP, a linear programming constraint can be turned into an elastic subtask.

http://www.coin-or.org/PuLP/pulp.html?highlight=lpsum#elastic-constraints

The subtask solution optimizes the distance from the target value.

Of course, the target value is the optimal solution to this subproblem, but the whole point of elastization is that we believe that this solution may not be feasible.

How can I include a subtask in a common problem? I tried to add it to the problem the way you added the restriction, and this led to a type error. I tried to include it in the objective function, and that didn't work either.

I can not find anything in the above documentation or examples posted here:

https://code.google.com/p/pulp-or/wiki/OptimisationWithPuLP?tm=6

Here is the subtask I formulated:

capacity = LpConstraint(e=lpSum([ x[m][n] * len(n.items) for n in N ]), sense=-1, rhs=30, name=str(random.random())) stretch_proportion = 30/50 elasticCapacity = capacity.makeElasticSubProblem(penalty=50, proportionFreeBoundList=[1,stretch_proportion]) 

Here is the closest thing, I think I need to include it in LP Objective:

 def sub(m): capacity = LpConstraint(e=lpSum([ x[m][n] * len(n.items) for n in N ]), sense=-1, rhs=30, name=str(random.random())) stretch_proportion = 30/50 elasticCapacity = capacity.makeElasticSubProblem(penalty=50, proportionFreeBoundList=[1,stretch_proportion]) elasticCapacity.solve() return elasticCapacity.isViolated() 

...

 prob += lpSum( [ x[m][n] * reduce(op.add, map(D2, [il for i in n.items], [jl for j in n.items]))\ for n in N for m in M ] ) + 50 * sub(m) 
+5
source share
1 answer

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)]) # example left-hand-side expression c_e_RHS = 30 # example right-hand-side value c_e_pre = LpConstraint(e=el_constr_LHS, sense=-1, name='pre-elastic', rhs=c_e_RHS) # The constraint LHS = RHS c_e = c_e_pre.makeElasticSubProblem(penalty=100, proportionFreeBoundList=[.02,.02]) # The definition of the elasticized constraint prob.extend(c_e) # Adding the constraint to the problem 

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.

+3
source

Source: https://habr.com/ru/post/1208275/


All Articles