1

Can lp_solve return a unifrom solution? (Is there a flag or something that will force this kinf of behavior?)
Say that I have this:

max: x + y + z + w;
x + y + z + w <= 100;

Results in:

Actual values of the variables:
x                             100
y                               0
z                               0
w                               0

However, I would like to have something like:

Actual values of the variables:
x                              25
y                              25
z                              25
w                              25

This is an oversimplyfied example, but the idea is that if the variables have the same factor in the objective function, then the result should idealy be more uniform and not everything for one, and the other what is left.
Is this possible to do? (I've tested other libs and some of them seem to do this by default like the solver on Excel or Gekko for Python).

EDIT: For instance, Gekko has already this behavior without me especifing anything...

from gekko import GEKKO
m = GEKKO()            
x1,x2,x3,x4 = [m.Var() for i in range(4)]

#upper bounds
x1.upper = 100
x2.upper = 100
x3.upper = 100
x4.upper = 100

# Constrain
m.Equation(x1 + x2 + x3 + x4 <= 100)  

# Objective
m.Maximize(x1 + x2 + x3 + x4)
m.solve(disp=False)   
print(x1.value, x2.value, x3.value, x4.value)

>> [24.999999909] [24.999999909] [24.999999909] [24.999999909]

John Hedengren
  • 12,068
  • 1
  • 21
  • 25

2 Answers2

1

You would need to explicitly model this (as another objective). A solver does nothing automatically: it just finds a solution that obeys the constraints and optimizes the objective function.

Also, note that many linear solvers will produce so-called basic solutions (corner points). So "all variables in the middle" does not come naturally at all.

Erwin Kalvelagen
  • 15,677
  • 2
  • 14
  • 39
  • I don't fully agree, I understand that a solver finds a feasable solution that maximizes and return it, yet there are still some solvers that will always return the soltuion with less deviation between variables with the same weitght in the objective function. I have edited the question and added and example so you can test it. Gekko does such thing... –  Feb 24 '22 at 08:57
  • 2
    IPOPT (a nonlinear interior point code) like other interior point algorithms may choose to stay in the middle. This is not a basic solution. Most LP algorithms are Simplex-based (or do a crossover after the interior point algorithm). These solvers will deliver a basic solution. The only way to consistently get an even distribution is to actually model this behavior. – Erwin Kalvelagen Feb 24 '22 at 22:20
0

The example in Gekko ended on [25,25,25,25] because of how the solver took a step towards the solution from an initial guess of [0,0,0,0] (default in Gekko). The problem is under-specified so there are an infinite number of feasible solutions. Changing the guess values gives a different solution.

from gekko import GEKKO
m = GEKKO()            
x1,x2,x3,x4 = m.Array(m.Var,4,lb=0,ub=100)
x1.value=50 # change initial guess
m.Equation(x1 + x2 + x3 + x4 <= 100)  
m.Maximize(x1 + x2 + x3 + x4)
m.solve(disp=False)   
print(x1.value, x2.value, x3.value, x4.value)

Solution with guess values [50,0,0,0]

[3.1593723566] [32.280209196] [32.280209196] [32.280209196]

Here is one method with equality constraints m.Equations([x1==x2,x1==x3,x1==x4]) to modify the problem to guarantee a unique solution that can be used by any linear programming solver.

from gekko import GEKKO
m = GEKKO()            
x1,x2,x3,x4 = m.Array(m.Var,4,lb=0,ub=100)
x1.value=50 # change initial guess
m.Equation(x1 + x2 + x3 + x4 <= 100)  
m.Maximize(x1 + x2 + x3 + x4)
m.Equations([x1==x2,x1==x3,x1==x4])
m.solve(disp=False)   
print(x1.value, x2.value, x3.value, x4.value)

This gives a solution:

[25.000000002] [25.000000002] [25.000000002] [25.000000002]

QP Solution

Switching to a QP solver allows a slight penalty for deviations but doesn't consume a degree of freedom.

from gekko import GEKKO
m = GEKKO()            
x1,x2,x3,x4 = m.Array(m.Var,4,lb=0,ub=100)
x1.value=50 # change initial guess
m.Equation(x1 + x2 + x3 + x4 <= 100)  
m.Maximize(x1 + x2 + x3 + x4)
penalty = 1e-5
m.Minimize(penalty*(x1-x2)**2)
m.Minimize(penalty*(x1-x3)**2)
m.Minimize(penalty*(x1-x4)**2)
m.solve(disp=False)   
print(x1.value, x2.value, x3.value, x4.value)

Solution with QP penalty

[24.999998377] [25.000000544] [25.000000544] [25.000000544]
John Hedengren
  • 12,068
  • 1
  • 21
  • 25