问题
I want to solve an LPP which has more than one optimal solution. How can I do that? For Example: Maximize 2000x1 + 3000x2
subject to
6x1 + 9x2 ≤ 100 2x1 + x2 ≤ 20
x1, x2 ≥ 0
In this LPP problem, there is more than one optimal solution i.e (0,100/9) and (20/3,20/3). When I solve this problem using the pulp library, it gives me only a (0,100/9) solution. I want all the possible solutions.
回答1:
There is a good discusion on this here.
There are two questions here: (i) How to find multiple optimal solutions to an LP, and (ii) Why you would want to.
Answering (ii) first - typically you might want to ask for all optimal solutions because there is some secondary or lower imporatance objective to pick between them (for example wanting to minimize the change from a current setting, or minimise risk in some way). If this is the case my personal recommendation would be to find a way of incorporating that lower order preference into your objective function (for example by adding in a term with a low weighting).
Answering (i) I find it helps to look at an LP graphically - and the example you have given works nicely for this (two variables means you can plot it - see plot on wolfram). Each of your constraints puts a lines on this inequality plot, and solutions can only be chosen on one side of that line.
Your objective function is like having a constant gradient across this feasible area and you are trying to find the highest spot. You can draw contours of your objective function by setting it to a specific value and drawing that line. What you'll find if you do this is that your objective function contours are parrallel to the top constraint line (your first constratin).
You can see this directly from the equation: 6x1 + 9x2 <= 100 divides down to 2x1 + 3x2 <= 100/3, and your objective divides down to have the same gradient. What this means is you can move along that top constraint from one corner to the other without changing the value of your objective function.
There are infinitely many optimal solutions which solve the equation:
2x1 + 3x2 == 100/3, between x1==0, and x1==20/3. You have already identified the solutions at the two corners.
If you want to find all the nodes which are equally optimal - for large problems there could be a large number of these - then the code below gives a basic implementation the method discussed here. When you run it the first time it will give you one of the corner solutions - you then need to add this node (set of variables and slacks which are zero) to A, and iterate until the objective degrades. You could put this within a loop. Note that as currently implemented this only works for problems with variables which have 0 lower bound, and are unbounded above.
import pulp as pulp
# Accounting:
# n structural varuables (n = 2)
# m constraints (m = 2)
# => No. of basics = 2 (no. of constraints)
# => No. of non-basics = 2 (no. of variables)
nb = 2
M = 100 # large M value - upper bound for x1, x2 * the slacks
model = pulp.LpProblem('get all basis', pulp.LpMaximize)
# Variables
x = pulp.LpVariable.dicts('x', range(2), lowBound=0, upBound=None, cat='Continuous')
# Non-negative Slack Variables - one for each constraint
s = pulp.LpVariable.dicts('s', range(2), lowBound=0, upBound=None, cat='Continuous')
# Basis variables (binary)
# one for each variable & one for each constraint (& so slack)
B_x = pulp.LpVariable.dicts('b_x', range(len(x)), cat='Binary')
B_s = pulp.LpVariable.dicts('b_s', range(len(s)), cat='Binary')
# Objective
model += 2000*x[0] + 3000*x[1]
# Constraints - with explicit slacks
model += 6*x[0] + 9*x[1] + s[0] == 100
model += 2*x[0] + x[1] + s[1] == 20
# No. of basics is correct:
model += pulp.lpSum(B_x) + pulp.lpSum(B_s) == nb
# Enforce basic and non-basic behaviour
for i in range(len(x)):
model += x[i] <= M*B_x[i]
for i in range(len(x)):
model += s[i] <= M*B_s[i]
# Cuts - already discovered solutions
A = []
# A = [[1, 1, 0, 0]]
# A = [[1, 1, 0, 0], [0, 1, 0, 1]]
for a in A:
model += (B_x[0]*a[0] + B_x[1]*a[1] +
B_s[0]*a[2] + B_s[1]*a[3]) <= nb - 1
model.solve()
print('Status:', pulp.LpStatus[model.status])
print('Objective:', pulp.value(model.objective))
for v in model.variables():
print (v.name, "=", v.varValue)
来源:https://stackoverflow.com/questions/61623548/how-to-solve-linear-programming-problem-with-more-than-one-optimal-solution-usin