IndexError when solving an optimal time control problem with code using GEKKO

Viewed 26

I am starting to learn Gekko and I am working time-optimal control problem. I am trying to solve the following problem with Gekko: Time optimal car problem

While investigating how to implement this problem with GEKKO I found the following code:

from gekko import GEKKO
import matplotlib.pyplot as plt
import numpy as np
 
# set up the gekko model
m = GEKKO()
 
# set up the time (minimize the time with time scaling)
m.time = np.linspace(0, 1, 100)
 
# set up the variables
Z1 = m.Var(value=0, ub=330, lb=0)
Z2 = m.Var(value=0, ub=33, lb=0)
m.fix(Z2, len(m.time)-1, 0)
m.fix(Z1, len(m.time)-1, 300)
 
# set up the value we modify over the horizon
tf = m.FV(value=500, lb=0.1)
tf.STATUS = 1
 
# set up the MV
u = m.MV(integer=True, lb=-2, ub=1)
u.STATUS = 1
 
# set up the equations
m.Equation(Z1.dt() / tf == Z2)
m.Equation(Z2.dt() / tf == u)
 
# set the objective
m.Obj(tf)
 
# set up the options
m.options.IMODE = 6
m.options.SOLVER = 1
 
# solve
m.solve(disp=False)
 
# print the time
print("Total time taken: " + str(tf.NEWVAL))
 
# plot the results
plt.figure()
plt.subplot(211)
plt.plot(np.linspace(0,1,100)*tf.NEWVAL, Z1, label=r'$Z_1$')
plt.plot(np.linspace(0,1,100)*tf.NEWVAL, Z2, label=r'$Z_2$')
plt.ylabel('Z')
plt.legend()
plt.subplot(212)
plt.plot(np.linspace(0,1,100)*tf.NEWVAL, u, label=r'$u$')
plt.ylabel('u')
plt.xlabel('Time')
plt.legend()
plt.show()

But when executing this code, it throws me the following error:

Traceback (most recent call last):

  File ~\OneDrive\Sin título2.py:43 in <module>
    m.solve(disp=False)

  File ~\anaconda3\lib\site-packages\gekko\gekko.py:2044 in solve
    self._write_csv()

  File ~\anaconda3\lib\site-packages\gekko\gk_write_files.py:224 in _write_csv
    t[i[0]+1] = i[1] #index is +1 because of prepended header

IndexError: index 301 is out of bounds for axis 0 with size 101

I realized that the error comes from that the size of the m.time should be 300 and not 100. Even though I make the change, I still get the same error, even if I change to higher values, the program stays running. Also, the configuration variables Z1, Z2 should be:

Z1 = m.Var(value=0, ub=33, lb=0)
Z2 = m.Var(value=0, ub=330, lb=0)
1 Answers

The order of the arguments to m.fix() changed with a prior release of Gekko. The correct order is m.fix(variable, value, time point) as shown in the documentation.

m.fix(Z2, 0, len(m.time)-1)
m.fix(Z1, 300, len(m.time)-1)

optimal solution

A newer function m.fix_final() also removes the need to specify the ending time index.

from gekko import GEKKO
import matplotlib.pyplot as plt
import numpy as np
 
# set up the gekko model
m = GEKKO()
 
# set up the time (minimize the time with time scaling)
m.time = np.linspace(0, 1, 100)
 
# set up the variables
Z1 = m.Var(value=0, ub=330, lb=0)
Z2 = m.Var(value=0, ub=33, lb=0)
m.fix_final(Z2, 0)
m.fix_final(Z1, 300)
 
# set up the value we modify over the horizon
tf = m.FV(value=500, lb=0.1)
tf.STATUS = 1
 
# set up the MV
u = m.MV(integer=True, lb=-2, ub=1)
u.STATUS = 1
 
# set up the equations
m.Equation(Z1.dt() / tf == Z2)
m.Equation(Z2.dt() / tf == u)
 
# set the objective
m.Obj(tf)
 
# set up the options
m.options.IMODE = 6
m.options.SOLVER = 1
 
# solve
m.solve(disp=False)
 
# print the time
print("Total time taken: " + str(tf.NEWVAL))
 
# plot the results
plt.figure()
plt.subplot(211)
plt.plot(np.linspace(0,1,100)*tf.NEWVAL, Z1, label=r'$Z_1$')
plt.plot(np.linspace(0,1,100)*tf.NEWVAL, Z2, label=r'$Z_2$')
plt.ylabel('Z')
plt.legend()
plt.subplot(212)
plt.plot(np.linspace(0,1,100)*tf.NEWVAL, u, label=r'$u$')
plt.ylabel('u')
plt.xlabel('Time')
plt.legend()
plt.show()
Related