我试图使用 Python GEKKO 在用于控制信号调度的 MPC 优化问题中引入滞后约束。这已成为一项艰巨的任务,因为我无法将以下问题转换为 GEKKO 理解的方程。 问题:
-
如果开启时间 < 最短开启时间,则给定资产的控制调度不应将其关闭。
-
如果关闭时间 < 最小关闭时间,则同一资产的控制调度不应能够将其关闭将其打开。
我正在尝试做的一个示例
其中:
engine = GEKKO(remote = False)
control = engine.Param(value = control_signal)
key = engine.MV(value = 0)
key.STATUS = 1
key.LOWER = -1
key.UPPER = 1
engine.Equation(hysteresis_equation(key))
在这种情况下,操纵变量是称为“关键”的控制信号的调度百分位数,它将影响问题动态。| ||其中键是操纵变量,而 hysteresis_equation 是键值的函数,应模拟时间相关的滞后。我没有提供更多细节,因为没有意义,问题在于 GEKKO 模型中非线性磁滞约束的实现。
我尝试过查看二进制变量,但是,我不明白如何获得它们在整个优化过程中使用 GEKKO 更改值。
尝试调用返回 True 或 False 的外部函数不受支持并产生 @error:方程定义 没有等式 (=) 或不等式 (>,<)
的方程我还尝试在类似于 power == (can_on * key + (1-can_on) *b0 + can_off * 0 + (1 -can_off) * 键)/2。布尔值是 hysteresis_equation 中的受控变量,根据滞后状态设置为 1 或 0,但不是 GEKKO 变量。
提前感谢您的帮助。
Thank you in advance for your help.
以下是使用 Python GEKKO 实现磁滞控制的两种方法:
方法 1:互补约束
此方法使用互补约束来强制执行磁滞逻辑。
from gekko import GEKKO
import numpy as np
import matplotlib.pyplot as plt
m = GEKKO(remote=False)
m.time = np.linspace(0, 20, 101)
# 参数
on_time_min = 2 # 最小开启时间
off_time_min = 3 # 最小关闭时间
# 变量
control = m.MV(value=0, lb=-1, ub=1) # 控制信号(假设范围为 -1 到 1)
control.STATUS = 1
on_state = m.Var(value=0, lb=0, ub=1) # 开启状态(二进制)
off_state = m.Var(value=1, lb=0, ub=1) # 关闭状态(二进制)
on_timer = m.Var(value=0) # 开启时间计数器
off_timer = m.Var(value=0) # 关闭时间计数器
# 方程
m.Equation(on_state + off_state == 1) # 始终处于开启或关闭状态之一
# 开启/关闭逻辑
m.Equation(on_timer.dt() == m.if3(control - 0.5, 1, 0)) # 如果 control > 0.5,则增加 on_timer
m.Equation(off_timer.dt() == m.if3(0.5 - control, 1, 0)) # 如果 control < 0.5,则增加 off_timer
# 磁滞约束
m.Equation(on_state * on_time_min <= on_timer) # 在切换到关闭状态之前保持开启至少 on_time_min
m.Equation(off_state * off_time_min <= off_timer) # 在切换到开启状态之前保持关闭至少 off_time_min
# 互补约束
m.Equation(on_state * (control.dt() - 1) <= 0) # 如果 on_state=1,则 control 必须增加(开启)
m.Equation(off_state * (control.dt() + 1) >= 0) # 如果 off_state=1,则 control 必须减少(关闭)
# 模拟
m.options.IMODE = 6
m.solve(disp=False)
# 绘制结果
plt.figure(figsize=(10, 6))
plt.plot(m.time, control.value, label='Control Signal')
plt.plot(m.time, on_state.value, label='On State')
plt.plot(m.time, off_state.value, label='Off State')
plt.legend()
plt.xlabel('Time')
plt.ylabel('Value')
plt.title('Hysteresis Control with GEKKO')
plt.show()
方法 2:状态机
此方法使用状态机框架来表示磁滞行为。
from gekko import GEKKO
import numpy as np
import matplotlib.pyplot as plt
m = GEKKO(remote=False)
m.time = np.linspace(0, 20, 101)
# 参数
on_time_min = 2 # 最小开启时间
off_time_min = 3 # 最小关闭时间
# 变量
control = m.MV(value=0, lb=-1, ub=1) # 控制信号(假设范围为 -1 到 1)
control.STATUS = 1
# 状态:关闭=1,开启=2
state = m.Var(value=1, lb=1, ub=2, integer=True)
# 时间计数器
time_in_state = m.Var(value=0)
# 方程
m.Equation(time_in_state.dt() == 1)
# 状态转换逻辑
m.Equation(m.if3(state - 1.5, # 如果处于关闭状态
m.if3(time_in_state - off_time_min, # 如果 off_time_min 已经过去
m.if3(control - 0.5, 2, 1), # 如果 control > 0.5,则转换到开启,否则保持在关闭
1), # 保持在关闭
m.if3(time_in_state - on_time_min, # 如果处于开启状态且 on_time_min 已经过去
m.if3(0.5 - control, 1, 2), # 如果 control < 0.5,则转换到关闭,否则保持在开启
2)) - state == 0) # 保持在开启
# 模拟
m.options.IMODE = 6
m.solve(disp=False)
# 绘制结果
plt.figure(figsize=(10, 6))
plt.plot(m.time, control.value, label='Control Signal')
plt.plot(m.time, state.value, label='State (1=Off, 2=On)')
plt.legend()
plt.xlabel('Time')
plt.ylabel('Value')
plt.title('Hysteresis Control with GEKKO (State Machine)')
plt.show()
这两种方法都实现了磁滞控制,但它们使用不同的方法。第一种方法更简洁,使用互补约束直接强制执行磁滞逻辑。第二种方法更明确,使用状态机框架来模拟系统行为。可以选择最适合的需求和编码风格的一种。
标签:python,optimization,nonlinear-optimization,gekko From: 78798267