How should I model log or sqrt with GEKKO? Constraints

Question:

I’m trying to develop my constraints with GEKKO, and I need to include some mathematical operations as log, coth or sqrt.

I tried initially with my habitual procedures, using numpy or mpmath, but I figure out that using GEKKO I need to use their operator definitions, as m.wathever (log,…), once the m = GEKKO() is done

How is the best way to develop that?
Should I take some considerations while I’m changing it?

K_t = (1 + m + np.sqrt(1 + m**3)) - mpmath.coth(s/2)  # Ref 2. Same results
Asked By: srgam

||

Answers:

Use the Gekko versions of those functions instead of the NumPy or Math versions:

gk = GEKKO()
K_t = (1 + m + gk.sqrt(1 + m**3)) - gk.cosh(s/2)/gk.sinh(s/2)

The Gekko versions are needed because of operator overloading to calculate first and second derivatives for the solvers with automatic differentiation. There is no coth so you’ll need to substitute with coth(x) = cosh(x)/sinh(x). I typically define my Gekko model as m=GEKKO() but you have another variable named m so I used gk instead. Here is a section from the documentation on Model Building Functions.

Equation Functions

Special function besides algebraic operators are available through GEKKO functions. These must be used (not numpy or other equivalent functions):

  • gk.sin(other)
  • gk.cos(other)
  • gk.tan(other)
  • gk.asin(other)
  • gk.acos(other)
  • gk.atan(other)
  • gk.sinh(other)
  • gk.cosh(other)
  • gk.tanh(other)
  • gk.exp(other)
  • gk.log(other)
  • gk.log10(other)
  • gk.sqrt(other)
Answered By: John Hedengren

One related observation about sqrt is that solution robustness improves by protecting against the case where the argument is negative. Here is a simple system using gekko:

from gekko import GEKKO
import numpy as np
m = GEKKO()
m.time = np.linspace(0,20,100)
k = 5
y = m.Var(value=5.0)
t = m.Param(value=m.time)

m.Equation(k*y.dt()==-m.sqrt(y))
m.options.IMODE = 4
m.solve(disp=True)

It seems to get stuck at sqrt probably because it can become less than zero and gekko solvers need additional equations to handle complex numbers. Changing the equation to remove sqrt with m.Equation((-k*y.dt())**2==y) is a potential solution to this problem:

solution

from gekko import GEKKO
import numpy as np
m = GEKKO()
m.time = np.linspace(0,20,100)
k = 5
y = m.Var(value=5.0)
t = m.Param(value=m.time)

m.Equation((-k*y.dt())**2==y)
m.options.IMODE = 4
m.solve(disp=True)

import matplotlib.pyplot as plt
plt.plot(m.time,y)
plt.show()

Another strategy is to constrain the argument of sqrt to be greater than zero such as with y = m.Var(value=5.0,lb=0) or y.LOWER=0. This also works to find a successful solution with the original equation.

from gekko import GEKKO
import numpy as np
m = GEKKO()
m.time = np.linspace(0,20,100)
k = 5
y = m.Var(value=5.0,lb=0)
t = m.Param(value=m.time)

m.Equation(k*y.dt()==-m.sqrt(y))
m.options.IMODE = 4
m.solve(disp=True)
Answered By: Michael Kwapisz