Gekko - if3() statement for choosing between two expressions in ODE

Viewed 173

I tried solving a differential equation having a logical condition in Gekko. I know that Gekko does not like these things but I supposed that simple if3() function in order to switch between the two given expressions (R1,R2) will get some solution. Here is a simple example code that failed - Solution not found.

import numpy as np
from gekko import GEKKO
import matplotlib.pyplot as plt

A=1
B=1e-5
C=2
D=0.01 
G=1
y0=120

m = GEKKO()    # create GEKKO model
nt = 101
m.time = np.linspace(0,100,nt) # time points

y = m.Var(y0) # create GEKKO variable

R1 = m.Intermediate(-(y+A-A/(y/C+1)**(B/D))/G*(D*y+D*C))
R2 = m.Intermediate(-0.1*y)

z = m.Var()              # This way - Solution not found
z = m.if3(y-60,R1,R2)    #
m.Equation(y.dt()== z)   # 

#m.Equation(y.dt()== R1)
#m.Equation(y.dt()== R2)

# solve ODE
m.options.IMODE = 4
m.options.NODES = 5
m.solve(disp=False)

# plot results
plt.plot(m.time,y)
plt.xlabel('time')
plt.ylabel('y(t)')

Unfortunately, it seems I did not figure out yet how to overcome these problems by reading the article about Logical conditions in Optimization.

Best Regards,

Radovan

1 Answers

The posted script gives the error:

Exception:  @error: Solution Not Found

To see additional details about the error, turn on the display with disp=True. This gives additional detail that indicates that the problem is infeasible.

 Number of state variables:    2800
 Number of total equations: -  2000
 Number of slack variables: -  800
 ---------------------------------------
 Degrees of freedom       :    0
 
 ----------------------------------------------
 Dynamic Simulation with APOPT Solver
 ----------------------------------------------
Iter:     1 I: -1 Tm:     13.07 NLPi:    9 Dpth:    0 Lvs:    0 Obj:  0.00E+00 Gap:       NaN
 Warning: no more possible trial points and no integer solution
 Maximum iterations
 
 ---------------------------------------------------
 Solver         :  APOPT (v1.0)
 Solution time  :  13.116200000000001 sec
 Objective      :  0.
 Unsuccessful with error code  0
 ---------------------------------------------------
 
 Creating file: infeasibilities.txt
 Use command apm_get(server,app,'infeasibilities.txt') to retrieve file
 @error: Solution Not Found

A couple issues with the model:

  • z = m.Var() is not needed because the z = if3() function defines the variable.
  • IMODE=6 is needed because there are slack variables in the problem and an optimization mode is needed to solve the problem.
  • Try if2() instead of if3(). It seems to work better with the MPCC form than the Mixed Integer form.
  • Solver APOPT performs better for this problem. Try m.options.SOLVER=1.

Solution with switching statement

import numpy as np
from gekko import GEKKO
import matplotlib.pyplot as plt

A=1; B=1e-5; C=2; D=0.01; G=1
y0=120

m = GEKKO(remote=False)    # create GEKKO model
nt = 101
m.time = np.linspace(0,50,nt) # time points

y = m.Var(y0) # create GEKKO variable

R1 = m.Intermediate(-(y+A-A/(y/C+1)**(B/D))/G*(D*y+D*C))
R2 = m.Intermediate(-0.1*y)

z = m.if2(y-60,0,1) 
m.Equation(y.dt()== (1-z)*R1+z*R2)

# solve ODE
m.options.IMODE  = 6
m.options.SOLVER = 1
m.options.NODES  = 5
m.solve(disp=True)

# plot results
plt.subplot(2,1,1)
plt.plot(m.time,y)
plt.plot([0,50],[60,60],'r--')
plt.ylabel('y(t)'); plt.grid()
plt.subplot(2,1,2)
plt.plot(m.time,z)
plt.ylabel('z(t)'); plt.grid()
plt.xlabel('time')
plt.show()

The alternative to using an if statement in the model is to integrate in a loop and check the condition y>60 to switch to the other model.

Related