Optimal Control Problem
agobL opened this issue · comments
Hi,
I would like to optimize an optimal control problem with Gekko, but I don't know how to write it correctly.
On the code below, the input to optimize is the 23-elements-vector Pheat, so that the objective function Cost is minimized, and the 23-elements-vector Tint kept above a threshold value given by the setpoint list.
The computation of Tint is done by the simulateTint function. It's not an explicit mathematic formula, and I would like to know how to formulate it so that the algorithm takes it into account.
from gekko import GEKKO
import numpy as np
import pandas as pd
size = 1
optimizedParams = [9.99999946e+00, 3.56802228e+02, 2.19999993e+01, 8.38949750e+02
, 1.42500002e+02, 4.90000020e+01, 7.00000031e+00, 1.50000006e+00
, 1.82238388e+02, 6.63460266e+06, 8.66627245e+06, 8.35000109e+06
, 1.46599414e+08, 1.22564853e+06]
conductances = optimizedParams[0:9]
capacitances = optimizedParams[9:len(optimizedParams)]
df_1H = pd.read_csv('data1_1H.csv', index_col='date', parse_dates=['date'])
df_1H = df_1H[1:size * 24]
i = np.arange(len(df_1H))
setpoint = np.where(np.logical_or(np.logical_and(((i % 24) >= 6), ((i % 24) < 8)),
np.logical_and(((i % 24) >= 18), ((i % 24) < 23))), 20., 0.)
TempCtr = [setpoint[i] for i in range(len(setpoint))]
def cgrid(Pgrid):
off_peak_price = 0.1252 # €/kWh
on_peak_price = 0.1593 # €/kWh
N = len(Pgrid)
i = np.arange(N)
mask_price = np.where(
np.logical_or((i % 24) < 7,
np.logical_and(((i % 24) >= 14), ((i % 24) < 17))
), off_peak_price, on_peak_price)
return Pgrid * mask_price
def Cost(Pheat):
if len(Pheat) == 0:
Pheat = df_1H['Pheat']
cost = m.sum(cgrid(np.array(Pheat))) # in €/kWh
return cost
def simulateTint(Pheat):
if len(Pheat) != 0:
df_1H['Pheat'] = 1000 * np.array(Pheat)
U = df_1H.values # boundary conditions(External and adjacent zones temperatures,Solar and Internal gains)
for i in range(len(U)):
U[i][4]=U[i][4].value.value
X0 = np.ones(5) * 14.9 # initialization with value from simulation
[Uext1, Uext2, Ugar1, Ugar2, UBSoffice1, UBSoffice2, UBSroom1, UBSroom2, Uv] = [np.array(cond) for cond in
conductances]
[Cext, Cgar, CBSoffice, CBSroom, Cair] = [np.array(capa) for capa in capacitances]
# State matrix A of size 5 x 5
C = np.array([Cext, Cgar, CBSoffice, CBSroom, Cair])
A = np.array([[-(Uext1 + Uext2), 0, 0, 0, Uext2],
[0, -(Ugar1 + Ugar2), 0, 0, Ugar2],
[0, 0, -(UBSoffice1 + UBSoffice2), 0, UBSoffice2],
[0, 0, 0, -(UBSroom1 + UBSroom2), UBSroom2],
[Uext2, Ugar2, UBSoffice2, UBSroom2, -(Uv + Uext2 + Ugar2 + UBSoffice2 + UBSroom2)]])
A = (A.T / C).T # each lines of A is divided by each elements of C. ".T" means transpose
# Matrix B of size 5 x 8
B = np.array([[Uext1, 0, 0, 0, 0, 0, 0, 0],
[0, Ugar1, 0, 0, 0, 0, 0, 0],
[0, 0, UBSoffice1, 0, 0, 0, 0, 0],
[0, 0, 0, UBSroom1, 0, 0, 0, 0],
[Uv, 0, 0, 0, 1, 1, 1, 1]])
B = (B.T / C).T # each lines of B is divided by each elements of C. ".T" means transpose
dt = 600 # 600s = 10 minutes
# temporary matrices
M1 = 2 * A + dt * np.dot(A, A)
M2 = B + dt * np.dot(A, B)
# initial states
N = len(U)
# Solve the numerical integration with Modified Euler's method
Tint = np.array(X0[4])
Xsave = X0
for k in range(1, N):
Xsave = Xsave + dt / 2.0 * (np.dot(M1, Xsave) + np.dot(M2, U[k - 1, :]) + np.dot(B, U[k, :]))
Tint = np.append(Tint, Xsave[4])
return Tint
m = GEKKO()
m.time = np.linspace(1,1, size * 24-1)
time=m.time
Pheat = m.Array(m.MV,(len(df_1H)))
j=0
for xi in Pheat:
xi.value = 1.
xi.lower = 0.
xi.upper = 10.
j += 1
m.Obj(Cost(Pheat))
Tint= m.Array(m.CV,(len(df_1H)))
j=0
for xi in Tint:
xi.SPLO = setpoint[j]
j += 1
m.Equations(Tint>TempCtr)
m.solve()
Thanks in advance.
Some functions such as np.dot()
are allowed with Gekko arrays but others such as np.logical_or()
do not return the correct form for Gekko automatic differentiation. Gekko uses gradient-based solvers so discontinuous functions are not allowed. Perhaps try scipy.optimize.minimize()
instead?