首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GEKKO多相优化:无解,-1自由度

GEKKO多相优化:无解,-1自由度
EN

Stack Overflow用户
提问于 2022-05-15 17:18:01
回答 1查看 40关注 0票数 2

我现在正在学习GEKKO,并尝试编写一个简单的一维控制示例,其中有一个具有动态特性的块。

dx/dt =v

dv/dt =u

电话:-5 <= u <= 5

其中x是位置,v是速度,u是施加的驱动,在初始和最终速度为0的情况下,从位置0移动到1倍的时间单位。目标是:

分钟abs(u)

它工作在一个单一的阶段,结果是 Bang Bang控件.

现在,我想尝试将其作为一个多阶段的轨道来实现,其中包括三个相互关联的阶段:

  1. U=5
  2. U=0
  3. U= -5

每个阶段的时间是控制变量。

问题是求解者找不到解决办法。自由度为-1,理论上为-1(总最后一次)与给定目标对应;如果目标被平等约束所取代,则为0(结果导致求解者表示的自由度更少,约为-100)。

这是我的代码:

代码语言:javascript
复制
import numpy as np
import matplotlib.pyplot as plt
from gekko import GEKKO

m = GEKKO(remote=True)  # Model

n = 3  # Number of phases: Bang-Off-Bang
max_u = 5.0  # Control can either be max_u, 0 or -max_u

# Options
m.options.NODES = 4  # Two intermediate nodes between collocation points
m.options.SOLVER = 1  # APOPT
m.options.IMODE = 6  # MPC Direct Collocation
m.options.MAX_ITER = 500  # To prevent endless loops
m.options.MV_TYPE = 0  # MVs are constant between endpoints
m.options.DIAGLEVEL = 1  # Show some diagnostics

# Time from 0 to 1 in 31 collocation points for every phase each
m.time = np.linspace(0, 1, 31)

tf = [m.FV(value=0.3) for i in range(n)]
for i in range(n):
    tf[i].STATUS = 1  # make final time controllable

# Collocation variables x and v
x = [m.Var(value=0, fixed_initial=False) for i in range(n)]
v = [m.Var(value=0, fixed_initial=False) for i in range(n)]
u = [max_u, 0, -max_u]  # For the three phases

# Fix start- and endpoint (Inbetween points can be fixed with m.fix())
m.fix_initial(x[0], val=0)
m.fix_initial(v[0], val=0)
m.fix_final(x[n-1], val=1)
m.fix_final(v[n-1], val=0)

# Differential equations describing the system scaled by tf
for i in range(n):
    m.Equation(x[i].dt() == v[i]*tf[i])
    m.Equation(v[i].dt() == u[i]*tf[i])

# Connect phases at endpoints
for i in range(n-1):
    m.Connection(x[i+1], x[i], 1, 'end', 1, 'end')
    m.Connection(x[i+1],'calculated', pos1=1, node1=1)
    m.Connection(v[i+1], v[i], 1, 'end', 1, 'end')
    m.Connection(v[i+1],'calculated', pos1=1, node1=1)

# Make final time equal to 1
m.Minimize((m.sum(tf)-1)**2)
#m.Equation(m.sum(tf) == 1)  # Could be used instead of objective

m.open_folder()

# Run optimization with Diagnostics
m.solve(disp=True)

我希望有人能帮我,谢谢你提前!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-05-30 04:39:43

软终端约束通常用于收敛到解决方案。下面是对硬终端约束的替换:

代码语言:javascript
复制
f = np.zeros(31); f[-1]=1; final=m.Param(f)
m.Minimize(final*(x[n-1]-1)**2)
m.Minimize(final*v[n-1]**2)

#m.fix_final(x[n-1], val=1)
#m.fix_final(v[n-1], val=0)

这给出了三个连接相的最优解。

代码语言:javascript
复制
import numpy as np
import matplotlib.pyplot as plt
from gekko import GEKKO

m = GEKKO(remote=True)  # Model

n = 3  # Number of phases: Bang-Off-Bang
max_u = 5.0  # Control can either be max_u, 0 or -max_u

# Options
m.options.NODES = 4  # Two intermediate nodes between collocation points
m.options.SOLVER = 1  # APOPT
m.options.IMODE = 6  # MPC Direct Collocation
m.options.MAX_ITER = 500  # To prevent endless loops
m.options.MV_TYPE = 0  # MVs are constant between endpoints
m.options.DIAGLEVEL = 0  # Show some diagnostics

# Time from 0 to 1 in 31 collocation points for every phase each
m.time = np.linspace(0, 1, 31)

tf = [m.FV(value=0.3) for i in range(n)]
for i in range(n):
    tf[i].STATUS = 1  # make final time controllable

# Collocation variables x and v
x = [m.Var(value=0, fixed_initial=False) for i in range(n)]
v = [m.Var(value=0, fixed_initial=False) for i in range(n)]
u = [max_u, 0, -max_u]  # For the three phases

# Fix start- and endpoint (Inbetween points can be fixed with m.fix())
m.fix_initial(x[0], val=0)
m.fix_initial(v[0], val=0)

f = np.zeros(31); f[-1]=1; final=m.Param(f)
m.Minimize(final*(x[n-1]-1)**2)
m.Minimize(final*v[n-1]**2)

#m.fix_final(x[n-1], val=1)
#m.fix_final(v[n-1], val=0)

# Differential equations describing the system scaled by tf
for i in range(n):
    m.Equation(x[i].dt() == v[i]*tf[i])
    m.Equation(v[i].dt() == u[i]*tf[i])

# Connect phases at endpoints
for i in range(n-1):
    m.Connection(x[i+1], x[i], 1, 'end', 1, 'end')
    m.Connection(x[i+1],'calculated', pos1=1, node1=1)
    m.Connection(v[i+1], v[i], 1, 'end', 1, 'end')
    m.Connection(v[i+1],'calculated', pos1=1, node1=1)

# Make final time equal to 1
m.Minimize((m.sum(tf)-1)**2)
#m.Equation(m.sum(tf) == 1)  # Could be used instead of objective

#m.open_folder()

# Run optimization with Diagnostics
m.solve(disp=True)

# Generate plot
t = [m.time*tf[i].value[0] for i in range(3)]
t[1] += t[0][-1]
t[2] += t[1][-1]
for i in range(3):
    plt.plot(t[i],x[i].value)
    plt.plot(t[i],v[i].value)
plt.xlabel('Time')
plt.show()    

缺少2自由度(-1自由度)是因为当使用m.fix_final(x[n-1], val=1)m.fix_final(v[n-1], val=0)时,端点处的导数也是固定的。这是关于Gekko和如何定义变量的一个已知问题。如果您确实需要一个硬约束,还有另一种方法(创建一个连接到端点的固定FV )。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72250534

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档