gekkompc

How to deploy a deep learning model into MPC as a constraint/equation?


I 'm working on solving MPC problem with GEKKO. My task is to develop a MPC controller generating indoor setpoint to saving power cost. At the same time, the indoor comfort level should be ensured. Currently, I have 2 svr models, one for house power forecasting, one for indoor temperature forecasting. Both svr model need current information (like setpoint(t), solar(t), room temp(t)...) and last time information(like setpoint(t-1), room temp(t-1)). So I'm confused how to implement these two model into MPC constraints.

Here is part of my code:

# ******************* MPC OPTIMIZER *******************
def Core2_0(time,S_p,R_p,Occup,GridRate,Spt0):
    
    m = GEKKO(remote = False)
    Np = 7
    
    # weather and occupancy forecast data for optimization
    df_data = pd.read_csv('RawData.csv')
    Solar_forecast = df_data.loc[:,['Irradiance']].values.flatten()
    # Solar_forecast = 100*Solar_forecast
    Tamb_forecast = df_data.loc[:,['Temperature_C']].values.flatten()
    
    df = pd.DataFrame({'Solar':[Solar_forecast[time]],
                        'OutTemp':[Tamb_forecast[time]],
                        'Setpoint_previous':[S_p],
                        'RoomTemp_previous':[R_p],
                        'Setpoint':[Spt0]})
    
    m.time = np.linspace(0,Np-1,Np) # prediction horizon
    
    
    Irr = m.Param(value = Solar_forecast[time:time+Np])
    TempAmb = m.Param(value = Tamb_forecast[time:time+Np])
    Occupancy = m.Param(value = Occup[time:time+Np])
    Price = m.Param(value = GridRate[time:time+Np])
    # previous ->datatype: variable
    # objfunc parameter
    weight = np.zeros(Np)
    for j in range (Np):
        if Occup[time+j] == 1:
            weight[j] = 10
    
    ## M for cost saving, W for comfort level
    M = m.Param(value = 100)
    Ttar = m.Param(value = 21)
    W = m.Param(value = weight)

    RoomTemp_previous = m.Var(value = R_p)
    # Pwr_previous = m.Var(value = P_p)
    Spt_previous = m.Var(value = S_p)
    
    # manipulated variable
    Spt = m.MV(value = Spt0, lb = 17,ub = 27)
    Spt.STATUS = 1 # allow optimizer to change
    Spt.DCOST = 0.01 # penalty to change the variable
    Spt.DMAX = 1 # maximum change for every time step
    
    # controlled variable
    Pwr = m.CV(value = svr_power.predict(df[features_power]), lb = 0)
    Trm = m.CV(value = svr_troom.predict(df[features_troom]))
    Pwr.STATUS = 0 # disable SP options; add SP to CV objective when equals 1
    Trm.STATUS = 0 # disable SP options
    m.options.CV_TYPE = 2 # squared error mode
#     Pwr.SP = 0 # reference
#     Trm.SP = 75
    Pwr.TR_INIT = 1 # trajectory
    Trm.TR_INIT = 1
    Pwr.TAU = 10 # time constant of trajectory
    Trm.TAU = 10
    
    
    # POWER input reshape->Setpoint_previous Setpoint RoomTemp_previous
    # TROOM input reshape->RoomTemp_previous Solar Setpoint_previous OutTemp Occupancy RoomTemp
    pwr_in = np.array([Spt_previous,Spt,RoomTemp_previous],dtype = object)
    trm_in = np.array([RoomTemp_previous,Irr,Spt_previous,TempAmb,Spt],dtype = object)
    
    # Equation
    m.Equation(Trm == Gekko_SVR(svr_troom,m).predict(trm_in))
    m.Equation(Pwr == Gekko_SVR(svr_power,m).predict(pwr_in))
    
    # if Pwr.value < 0:
    #     Pwr.value = 0
    
    # time delay, receding horizon, put predicted output into input of next receding prediction time window
    # m.delay(Pwr,Pwr_previous,1)
    m.delay(Trm,RoomTemp_previous,1)
    m.delay(Spt,Spt_previous,1)
    
    # Objective function

    m.Obj(m.abs((Trm-Ttar))**2*W + (Pwr*Price)**2*M)
    
    # mode and solve
    m.options.IMODE = 6 # MPC mode
    m.solve(disp = False)
    
    return Spt.NEWVAL,Pwr.value,Trm.value,Spt.value,pwr_in

action,_,_,_,_ = Core2_0()

I put these 2 models into the equation. And use m.delay() to generate the previous information.

The running result seems good but I'm not sure if the variable definition is reasonable. Also I'm not vary clear about the rolling logic in GEKKO MPC. Is there anyone can help me to check this code?


Solution

  • From what I can see and what you've described the code looks good, assuming the svr models were trained with the proper input format. That is the correct use of the delay function, and the best method of accessing the previous timesteps results. The delay object creates values from the previous timestep, so ensure that previous time is the desired input for the models that you created. If you plan on changing the Np parameter, make sure to account for this by either altering how many timesteps you delay or retraining a model on the new timestep. Here is a previous thread about the delay function and how to use it: Gekko: Calculate a variable that is a function of the previous and current time step's value