How to solve for multiple solutions to linear program in Python?

笑着哭i 提交于 2021-02-10 14:25:52

问题


I have some Pyomo code (see below) which produces one possible solution to the linear equation:

3a + 2b + 2c = 15

Where:

-20 <= a <= 0

0 <= b <= 20

20 <= c <= 50

a, b, c are real numbers

How could I rewrite the program to produce a random solution every time it is run? I am open to using Pulp as well.

My Code:

# Coefficients
coeffs = [3,2,2]
y_target = 15

# Define model and variables
model = ConcreteModel()
model.a = Var(bounds=(-20,0))
model.b = Var(bounds=(0,20))
model.c = Var(bounds=(20,50))
model_x = [model.a, model.b, model.c]
    
# Model Constraint
def weight_rule(model):
    return sum(coeffs[i] * model_x[i] for i in range(len(coeffs))) == y_target 
model.weight = Constraint( rule=weight_rule )

# Model Objective
obj = sum(coeffs[i] * model_x[i] for i in range(len(coeffs))) - y_target 
model.objective = Objective(expr=obj, sense=minimize)

# Solve the model
solver = SolverFactory('glpk')
solver.solve(model)

# Print results
print([value(model_x[i]) for i in range(len(coeffs))])
# Current Output:
[-8.33333, 0, 20]

EDIT - New approach (still not working): Below I adapted some helpful code supplied here by @kabdulla using the approach described by @Erwin Kalvelagen, but can't quite get it working for my case. Any advice would be appreciated.

import pulp as pulp

# Accounting:
# n structural varuables (n = 3)
# m constraints (m = 2)
# => No. of basics = 2 (no. of constraints)
# => No. of non-basics = 2 (no. of variables)

A = []    # Empty list for solutions to exclude
nb = 3
M = 100   # large M value - upper bound for x1, x2, x3 * the slacks
numSolutions = 5 # How many solutions we seek by iterating

# Set lower and upper bound ranges for respective variables
lowers = [-20,0,20]
uppers = [0,20,50]

for _ in range(numSolutions):

    model = pulp.LpProblem('get all basis', pulp.LpMaximize)

    # Variables
    x = pulp.LpVariable.dicts('x', range(3), cat='Continuous')
    for i in x.keys():
         x[i].lowBound = lowers[i]
         x[i].upBound = uppers[i]

    # Non-negative Slack Variables - one for each constraint
    s = pulp.LpVariable.dicts('s', range(1), 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 += 3*x[0] + 2*x[1] + 2*x[2]

    # Constraints - with explicit slacks
    model += 3*x[0] + 2*x[1] + 2*x[2] + s[0] == 15

    # 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(s)):
        model += s[i] <= M*B_s[i]
 
    for a in A:
        model += (B_x[0]*a[0] + B_x[1]*a[1] + B_x[2]*a[2] + B_s[0]*a[3]) <= nb - 1 

    model.solve()
    
    # Cuts - already discovered solutions
    exc = [v.varValue for v in model.variables()][:4]
    exc = exc[1:4] + exc[0:1]
    
    A.append(exc)

    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/65677194/how-to-solve-for-multiple-solutions-to-linear-program-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!