BYU-PRISM / GEKKO

GEKKO Python for Machine Learning and Dynamic Optimization
https://machinelearning.byu.edu
Other
573 stars 102 forks source link

inquiry about operators that GEKKO supports #111

Closed frankligy closed 3 years ago

frankligy commented 3 years ago

Hi,

Thanks for this awesome library!

As an end-user that knows very little about the implementation and mathematical detail, I encountered an issue that I was hoping to get some bits of help with.

When defining equation, sometimes I need to involve customized defined functions that include operators like math.sqrt or piecewise function, like in the following example:

def heavisible(x):
    if x > 0:
        return 1
    else:
        return 0

# here the k_repair is a python variable (constant value), X_var is a GEKKO variable
m.Equation(X_var.dt()==-k_repair*heavisible(X_var))

I will get this error:

Traceback (most recent call last):
  File "/Users/ligk2e/opt/anaconda3/envs/scanpy/lib/python3.6/site-packages/IPython/core/interactiveshell.py", line 3343, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-15-0755d52d8636>", line 1, in <module>
    m.Equation(X_var.dt()==-k_repair*heavisible(X_var))
  File "<ipython-input-5-702c6cbc02ae>", line 10, in heavisible
    if x > 0:
  File "/Users/ligk2e/opt/anaconda3/envs/scanpy/lib/python3.6/site-packages/gekko/gk_operators.py", line 25, in __len__
    return len(self.value)
  File "/Users/ligk2e/opt/anaconda3/envs/scanpy/lib/python3.6/site-packages/gekko/gk_operators.py", line 144, in __len__
    return len(self.value)
TypeError: object of type 'int' has no len()

Another example:

def Goldbeter_koshland(u,v,q,r):
    a = 2*u*r
    b = (v-u+v*q+u*r)**2
    c = 4*u*r*(v-u)
    d = math.sqrt(b-c)
    e = v-u+v*q+u*r+d
    return a/e

# again, here P_var is GEKKO variable and others are just constant
m.Equation(k_d53=k_prime_d53+k_prime2_d53*Goldbeter_koshland(Z_var,theta,J1/P_var,J2/P_var))

I got this error:

Traceback (most recent call last):
  File "/Users/ligk2e/opt/anaconda3/envs/scanpy/lib/python3.6/site-packages/IPython/core/interactiveshell.py", line 3343, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-17-b9b22ad85e3d>", line 1, in <module>
    m.Equation(k_d53=k_prime_d53+k_prime2_d53*Goldbeter_koshland(Z_var,theta,J1/P_var,J2/P_var))
  File "<ipython-input-5-702c6cbc02ae>", line 5, in Goldbeter_koshland
    d = math.sqrt(b-c)
TypeError: must be real number, not GK_Operators

As I said, I am not familiar with the math behind, but by looking at these errors, it seems like the culprit is the math.sqrt and <,>,= operators that are not allowed in GEKKO, I am trying to understand is that true? If so, any workaround here because the ODE I am trying to simulate just has all these operators in the equation.

Thanks a lot, Frank

APMonitor commented 3 years ago

For the first function, you can use either the m.if2() or m.if3() (preferred) functions in Gekko to introduce the switching terms.

# here the k_repair is a python variable (constant value), X_var is a GEKKO variable
m.Equation(X_var.dt()==-k_repair*m.if3(X_var,0,1))

This implements binary switching conditions that are solvable with gradient based optimizers. You will also need to switch to m.options.IMODE=6 to solve the model as an optimization problem.

For the second function, please use the gekko m.sqrt() function instead of the math.sqrt() function. This is needed for the automatic differentiation in Gekko to efficiently solve the model.