I tried using the python library of Gekko to simulate a solver. I need to use a large number of if conditions, for which I have used the if2 and if3 provided by Gekko. I understand that m.if2 or m.if3 are solved returning the output as a variable. The problem occurs especially when I use these if conditions within a for loop. Each if condition yields a variable and especially when I run it through a for loop, the number of these variables increases significantly. This sometimes messes up the solution.
I need a better understanding of exactly how these if conditions work.
For example:
xlr = self.m.Const(18)
xor = self.m.Intermediate("_some intermediate equation_")
for i in range(2, 6):
x = self.m.Intermediate("_some intermediate equation_")
y = self.m.if3(
self.m.abs(xlr - xor) - 1e-6,
self.m.Intermediate(t11 - dan * i / 6),
self.m.Intermediate(
t11
- dan
* (1 - self.m.exp(-i / (6 * x0)))
/ (1 - self.m.exp(-1 / x0))
)
)
Here, 'y' is returned as a variable by the m.if3 condition and as it is run within a for loop, the variables seem to be created every time. I suppose this sometimes causes the Gekko model to fail. It would really help me if someone can help me with the explanation of the if2/if3 conditions in Gekko.
1 Answer 1
In Gekko, the if2 and if3 functions implement logic in mathematical expressions. They are used to handle discontinuities and non-smooth conditions. Here's how these functions works:
if2 Function:
- Syntax:
m.if2(condition, value_if_false, value_if_true) - Returns
value_if_trueifcondition > 0; otherwise, returnsvalue_if_false. - Uses Mathematical Program with Complementarity Constraint (MPCC) form.
- Solver may give incorrect result because of poor numerics at switching point (saddle point).
if3 Function:
- Syntax:
m.if3(condition, value_if_false, value_if_true) - Similar to
if2but uses binary variables instead of MPEC equations. - Requires a Mixed Integer solver such as
m.options.SOLVER='APOPT' - More reliable, but often takes longer to solve.
Here is an example use of m.if3():
import numpy as np
import matplotlib.pyplot as plt
from gekko import GEKKO
m = GEKKO(remote=False)
p = m.Param(value=np.linspace(0,10,41))
# conditional statement
y = m.if3(p-4,p**2,-0.2*(p-4)+7)
m.options.IMODE = 2
m.solve()
lbl = r'$y=\mathrm{if3}(p-4,p^2,-0.2(p-4)+7)$'
plt.plot(p,y,'bo',label=lbl)
plt.text(1,5,r'$p^2$')
plt.text(5,10,r'$-0.2 (p-4)+7$')
plt.legend(loc=4)
plt.ylabel('y')
plt.show()
Here is additional information on using logical conditions in optimization problems.
If creating the model in a loop, each variable needs a separate index. If x and y are redefined without a new index, the previously defined variables are still included in the model.
x = [None]*4
y = [None]*4
for i in range(2, 6):
x[i] = self.m.Intermediate("_some intermediate equation_")
y[i] = self.m.if3(
self.m.abs(xlr - xor) - 1e-6,
self.m.Intermediate(t11 - dan * i / 6),
self.m.Intermediate(
t11
- dan
* (1 - self.m.exp(-i / (6 * x0)))
/ (1 - self.m.exp(-1 / x0))
)
)
One additional note is that m.abs() has a non-continuous derivative at 0. It is better to use m.abs3() if also using m.if3() or m.abs2() if also using m.if2(). It is challenging to help more specifically without a complete code, but one other recommendation is to use native Python or numpy instead of gekko if attempting to create a solver that iterates through a solution. Gekko has built-in solvers that iterate internally once the problem is compiled into byte-code.