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
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)
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:
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)
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
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)
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:
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)