3

I've run into an issue where I can't get APOPT to optimize an unconstrained single piecewise linear, and it's really throwing me for a loop. I feel like there's something I'm not understanding about model.pwl, but it's hard (for me) to find documentation outside of the GEKKO docs. Here's my minimal example:

model = GEKKO(remote=False)
model.options.SOLVER = 1
model.solver_options = ["minlp_as_nlp 0"]
x = model.sos1([0, 1, 2, 3, 4]) # This can also be model.Var(lb=0, ub=4), same result.
pwl = model.Var()
model.pwl(x, pwl, [0, 1, 2, 3, 4], [30, 30.1, 30.2, 30.3, 30.4], bound_x=True)
model.Minimize(pwl)
model.solve(display=True)
print(x.value)
print(pwl.value)
print(model.options.objfcnval)

The output that I get is:

 ----------------------------------------------------------------
 APMonitor, Version 1.0.3
 APMonitor Optimization Suite
 ----------------------------------------------------------------
 --------- APM Model Size ------------
 Each time step contains
 Objects : 1
 Constants : 0
 Variables : 2
 Intermediates: 0
 Connections : 2
 Equations : 1
 Residuals : 1
 Piece-wise linear model pwl1points: 5
 Number of state variables: 12
 Number of total equations: - 5
 Number of slack variables: - 0
 ---------------------------------------
 Degrees of freedom : 7
 ----------------------------------------------
 Steady State Optimization with APOPT Solver
 ----------------------------------------------
 Iter Objective Convergence
 0 3.39503E+01 3.01000E+01
 1 3.22900E+01 1.00000E-10
 2 3.22000E+01 2.22045E-16
 4 3.22000E+01 0.00000E+00
 Successful solution
 ---------------------------------------------------
 Solver : APOPT (v1.0)
 Solution time : 3.819999999541324E-002 sec
 Objective : 32.2000000000000
 Successful solution
 ---------------------------------------------------
2.0
30.2
32.2

This is unexpected to me, as the obvious minimal value is 30 for the pwl.

asked Jan 3, 2025 at 17:53

1 Answer 1

2

A cubic spline is much more reliable in optimization than a piecewise linear function because it doesn't rely on slack variables and switching conditions.

from gekko import GEKKO
model = GEKKO(remote=False)
model.options.SOLVER = 1
x = model.Var(lb=0, ub=4, integer=True)
y = model.Var()
model.cspline(x, y, [0, 1, 2, 3, 4], [30, 30.1, 30.2, 30.3, 30.4], bound_x=True)
model.Minimize(y)
model.solve(display=True)
print(x.value)
print(y.value)
print(model.options.objfcnval)

Here is the output:

 ----------------------------------------------------------------
 APMonitor, Version 1.0.3
 APMonitor Optimization Suite
 ----------------------------------------------------------------
 
 
 --------- APM Model Size ------------
 Each time step contains
 Objects : 1
 Constants : 0
 Variables : 2
 Intermediates: 0
 Connections : 2
 Equations : 1
 Residuals : 1
 
 Number of state variables: 2
 Number of total equations: - 1
 Number of slack variables: - 0
 ---------------------------------------
 Degrees of freedom : 1
 
 ----------------------------------------------
 Steady State Optimization with APOPT Solver
 ----------------------------------------------
Iter: 1 I: 0 Tm: 0.00 NLPi: 2 Dpth: 0 Lvs: 0 Obj: 3.00E+01 Gap: 0.00E+00
 Successful solution
 
 ---------------------------------------------------
 Solver : APOPT (v1.0)
 Solution time : 1.970000000437722E-002 sec
 Objective : 30.0000000000000 
 Successful solution
 ---------------------------------------------------
 
[0.0]
[30.0]
30.0

A few other notes:

  • Use m.Var(integer=True) instead of m.sos1() when potential values are integers. The m.sos1() function is for discrete non-integer values.
  • There is more information on the PWL function in the APMonitor documentation. Gekko is an interface to the APMonitor Modeling Language and writes gk0_model.apm as a text file in the run directory m._path (or open tmp folder with m.open_folder()).
answered Jan 4, 2025 at 1:53
Sign up to request clarification or add additional context in comments.

3 Comments

The problem I am working on uses a discretized input that is not necessarily integral. It might have step sizes of 0.5, 0.25, etc. From what I've read, it's still better to have an integral index than to use sos1 though. Is there a good reason though why the APOPT algorithm wouldn't be able to find the minimum of the PWL?
Here is a discussion on Logical Conditions in optimization using MPCCs (Mathematical Programs with Complementarity Constraints) versus Binary Conditions. Binary conditions work better but take longer to solve. apmonitor.com/me575/index.php/Main/LogicalConditions If you can avoid logical conditions (such as with a cubic spline) then it is generally faster to solve and easier for the solver to find an optimum. The PWL form that is implemented in gekko is with continuous variables that often get stuck near the switching conditions, similar to MPCCs.
It's no problem if you need to use the m.sos1() function. It creates a binary variable for each option. If you do use an integer variable then only one integer variable is created instead of multiple binary variables.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.