簡體   English   中英

自由終端時間、積分目標和微分方程作為約束

[英]Free terminal time, integral objective and differential equations as constraints

我正在嘗試解決一個最優控制問題,該問題涉及最小化具有固定狀態但自由終端時間的積分目標。 這是一個相對簡單的問題,可以解析解決。 Gekko 的解決方案與分析不符。

方程式

解決方案

我不確定我做錯了什么。 我按照幾個 Gekko 示例來解決這個問題。 任何幫助深表感謝。

我遇到的另一個問題是如何讓 Gekko 自動計算控件的初始值。 最優控制總是從指定的初始控制猜測開始。

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

# create GEKKO model
m = GEKKO()
# time points
n = 501
tm = np.linspace(0, 1, n)
m.time = tm

# Variables
x1 = m.Var(value=1)  # x1
x2 = m.Var(value=2)  # x2
# u = m.Var(value=-1)  # control variable used as normal var
u = m.MV(value=-1) # manipulative variable
u.STATUS = 1
u.DCOST = 1e-5

p = np.zeros(n)
p[-1] = 1.0
final = m.Param(value=p)

# FV
tf = m.FV(value=10.0, lb=0.0, ub=100.0)
tf.STATUS = 1

# equations
m.Equation(x1.dt()/tf == x2)
m.Equation(x2.dt()/tf == u)


# Final conditions
soft = True
if soft:
    # soft terminal constraint
    m.Minimize(final*1e5*(x1-3)**2)
    # m.Minimize(final*1e5*(x2-2)**2)
else:
    # hard terminal constraint
    x1f = m.Param()
    m.free(x1f)
    m.fix_final(x1f, 3)
    # connect endpoint parameters to x1 and x2
    m.Equations([x1f == x1])

# Objective Function
obj = m.Intermediate(tf*final*m.integral(0.5*u**2))

m.Minimize(final*obj)

m.options.IMODE = 6
m.options.NODES = 2
m.options.SOLVER = 3
m.options.MAX_ITER = 500
# m.options.MV_TYPE = 0
m.options.DIAGLEVEL = 0
m.solve(disp=False)


# Create a figure
plt.figure(figsize=(10, 4))
plt.subplot(2, 2, 1)
# plt.plot([0,1],[1/9,1/9],'r:',label=r'$x<\frac{1}{9}$')
plt.plot(tm, x1.value, 'k-', lw=2, label=r'$x1$')
plt.ylabel('x1')
plt.legend(loc='best')
plt.subplot(2, 2, 2)
plt.plot(tm, x2.value, 'b--', lw=2, label=r'$x2$')
plt.ylabel('x2')
plt.legend(loc='best')
plt.subplot(2, 2, 3)
plt.plot(tm, u.value, 'r--', lw=2, label=r'$u$')
plt.ylabel('control')
plt.legend(loc='best')
plt.xlabel('Time')
plt.subplot(2, 2, 4)
plt.plot(tm, obj.value, 'g-', lw=2, label=r'$\frac{1}{2} \int u^2$')
plt.text(0.5, 3.0, 'Final Value = '+str(np.round(obj.value[-1], 2)))
plt.ylabel('Objective')
plt.legend(loc='best')
plt.xlabel('Time')
plt.show()

這里有一些修改:

# u = m.MV(value=-1)
u = m.MV(value=-1,fixed_initial=False)

#obj = m.Intermediate(tf*final*m.integral(0.5*u**2))
obj = m.Intermediate(m.integral(0.5*u**2))

m.options.NODES = 3 # increase accuracy

如果您添加tf<=3的約束,那么它會給出與上述相同的解決方案。

原液

但是,如果將tf約束放寬到<=100 ,則有更好的解決方案。

更好的解決方案

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

# create GEKKO model
m = GEKKO()
# time points
n = 501
tm = np.linspace(0, 1, n)
m.time = tm

# Variables
x1 = m.Var(value=1)  # x1
x2 = m.Var(value=2)  # x2
u = m.MV(value=-1,fixed_initial=False) # manipulated variable
u.STATUS = 1
u.DCOST = 1e-5

p = np.zeros(n)
p[-1] = 1.0
final = m.Param(value=p)

# FV
tf = m.FV(value=10.0, lb=0.0, ub=100.0)
tf.STATUS = 1

# equations
m.Equation(x1.dt()/tf == x2)
m.Equation(x2.dt()/tf == u)


# Final conditions
soft = True
if soft:
    # soft terminal constraint
    m.Minimize(final*1e5*(x1-3)**2)
    # m.Minimize(final*1e5*(x2-2)**2)
else:
    # hard terminal constraint
    x1f = m.Param()
    m.free(x1f)
    m.fix_final(x1f, 3)
    # connect endpoint parameters to x1 and x2
    m.Equations([x1f == x1])

# Objective Function
obj = m.Intermediate(m.integral(0.5*u**2))

m.Minimize(final*obj)

m.options.IMODE = 6
m.options.NODES = 3
m.options.SOLVER = 3
m.options.MAX_ITER = 500
# m.options.MV_TYPE = 0
m.options.DIAGLEVEL = 0
m.solve(disp=True)

# Create a figure
tm = tm*tf.value[0]
plt.figure(figsize=(10, 4))
plt.subplot(2, 2, 1)
# plt.plot([0,1],[1/9,1/9],'r:',label=r'$x<\frac{1}{9}$')
plt.plot(tm, x1.value, 'k-', lw=2, label=r'$x1$')
plt.ylabel('x1')
plt.legend(loc='best')
plt.subplot(2, 2, 2)
plt.plot(tm, x2.value, 'b--', lw=2, label=r'$x2$')
plt.ylabel('x2')
plt.legend(loc='best')
plt.subplot(2, 2, 3)
plt.plot(tm, u.value, 'r--', lw=2, label=r'$u$')
plt.ylabel('control')
plt.legend(loc='best')
plt.xlabel('Time')
plt.subplot(2, 2, 4)
plt.plot(tm, obj.value, 'g-', lw=2, label=r'$\frac{1}{2} \int u^2$')
plt.text(0.5, 3.0, 'Final Value = '+str(np.round(obj.value[-1], 2)))
plt.ylabel('Objective')
plt.legend(loc='best')
plt.xlabel('Time')
plt.show()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM