The control horizon and prediction horizon

4.9k views Asked by At

I have reviewed the bibliography and the Gekko programming structure for model predictive control.  Although I understood the way it is programmed and their purpose. I would like to understand how Gekko manages the differences between the control horizon and prediction horizon according to related in Seborg, for example.  I can´t see a differentiation on the code. Below is an example MPC application for illustration.

Model Predictive Control

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

m = GEKKO()

# Time Horizon [0,1,2,...,39,40]
m.time = np.linspace(0,40,41)

# MV = Manipulated Variable
u = m.MV(value=0, lb=0, ub=100)
u.STATUS=1; u.DCOST=0.1; u.DMAX=20

# CV = Controlled Variable
x = m.CV(value=0,name='x')
x.STATUS=1; x.SP=45

# Define model
K = m.Param(value=0.8); tau = 15.0
m.Equation(tau*x.dt() == -x + K*u)

# Options and solve
m.options.CV_TYPE = 2
m.options.MV_TYPE = 0
m.options.NODES   = 3
m.options.IMODE   = 6

# Define Control and Prediction Horizon
m.options.CTRL_HOR = 10
m.options.CTRL_TIME = 1
m.options.PRED_HOR = 40
m.options.PRED_TIME = 2

m.solve(disp=False)

# Plot results
plt.figure()
plt.subplot(2,1,1)
plt.step(m.time,u.value,'b-',label='MV Move Plan')
plt.legend()
plt.ylabel('MV')
plt.subplot(2,1,2)
plt.plot([0,40],[45,45],'k-',label='Target Setpoint')
plt.plot(m.time,x.value,'r--',label='CV Response')
plt.ylabel('CV')
plt.xlabel('Time')
plt.legend(loc='best')
plt.show()

I would appreciate your feedback about how I should consider the np.linspace() instruction used in the code.

Thank you.

Sandra Rodríguez

1

There are 1 answers

0
John Hedengren On

The control horizon is the section of the time horizon where MV moves are allowed. The prediction horizon extends past the control horizon to predict the final CV outcomes but without MV movement. It is a legacy concept from industrial model predictive controllers that need to calculate a short-term move plan but also need to predict where the controller MVs and CVs will eventually settle out.

Option 1: Use Gekko Options to Define Time Horizon (not recommended)

The parameters CTRL_HOR, CTRL_TIME, PRED_HOR, and PRED_TIME are options from APMonitor but don't change the Gekko solution unless you set m.options.CSV_READ=0. Turning off the CSV file reading is not recommended because Gekko uses the CSV data file to communicate changes.

m.options.CSV_READ = 0

# Define Control and Prediction Horizon
m.options.CTRL_HOR = 10
m.options.CTRL_TIME = 1
m.options.PRED_HOR = 40
m.options.PRED_TIME = 1

Control horizon

Option 2: Use m.time() to Define Time Horizon

Using m.time is the preferred method for defining your MPC time horizon. It can be non-uniform with more than just a control and prediction interval.

m.time = [0,1,2,3,4,6,8,10,15,25,35,50,80]

Non-uniform time horizon

Reduce Prediction Horizon Degrees of Freedom

The purpose of the prediction horizon is to calculate to steady state, holding the last allowable MV move from the control horizon constant. If you need to disallow MV movement after a certain point then m.Connection() can link MV values together to disallow movement after a certain time horizon location.

# Create prediction horizon
for i in range(9,len(m.time)):
    m.Connection(u,u,8,i)     # connect end point node
    m.Connection(u,u,8,i,1,2) # connect internal node

Prediction Horizon

Here is the full code for this example problem.

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

m = GEKKO()

# Time Horizon
m.time = [0,1,2,3,4,6,8,10,15,25,35,50,80]

# MV = Manipulated Variable
u = m.MV(value=0, lb=0, ub=100)
u.STATUS=1; u.DCOST=0.1; u.DMAX=20

# CV = Controlled Variable
x = m.CV(value=0,name='x')
x.STATUS=1; x.SP=45

# Define model
K = m.Param(value=0.8); tau = 15.0
m.Equation(tau*x.dt() == -x + K*u)

# Options and solve
m.options.CV_TYPE = 2
m.options.MV_TYPE = 0
m.options.NODES   = 3
m.options.IMODE   = 6

# Create prediction horizon
for i in range(9,len(m.time)):
    m.Connection(u,u,8,i)     # connect end point node
    m.Connection(u,u,8,i,1,2) # connect internal node

m.solve(disp=True)

# Plot results
plt.figure()
plt.subplot(2,1,1)
plt.step(m.time,u.value,'b-',label='MV Move Plan')
plt.plot(m.time[0:8],u.value[0:8],'o',color='orange',label='Control Horizon')
plt.plot(m.time[8:],u.value[8:],'x',color='purple',label='Prediction Horizon')
plt.legend()
plt.ylabel('MV')
plt.subplot(2,1,2)
plt.plot([0,80],[45,45],'k-',label='Target Setpoint')
plt.plot(m.time,x.value,'r.-',label='CV Response')
plt.ylabel('CV')
plt.xlabel('Time')
plt.legend(loc='best')
plt.show()