如何在GEKKO中实现OR约束?电机优化求解遇阻求助
电机成本优化问题的解决方案
问题根源分析
核心问题出在决策变量x[motor]的下限设置错误:
- 原代码中
x[motor]的lb被设为电机的功率下限(比如Motor1的lb=0.6),但电机不运行时功率应为0,这导致当y[motor]=0(不运行)时,约束x[motor] <= 功率上限 * y[motor]要求x=0,与x的下限限制冲突,无法满足。 - 当总功率约束设为4.7时,刚好是所有电机运行的最小总功率(0.6+2.1+1+1=4.7),此时所有
y[motor]=1,x[motor]取下限即可满足所有约束;但总功率小于4.7时,必须有电机不运行,而x的下限限制导致无法实现,因此找不到可行解。
修正步骤
- 调整
x[motor]的下限为0:允许电机不运行时功率为0,运行时通过约束限制功率范围。 - 保留运行/不运行的约束逻辑:
x[motor] >= 功率下限 * y[motor]:运行时(y=1)功率不低于下限,不运行时(y=0)功率≥0(符合lb=0)。x[motor] <= 功率上限 * y[motor]:运行时功率不超过上限,不运行时功率≤0(结合lb=0,功率只能为0)。
- 简化价格函数:消除冗余计算,避免潜在数值问题。
- 按需设置总功率约束:可设为固定值或范围约束。
修正后的代码
from gekko import GEKKO power_ranges = { 'Motor1': (0.6, 1.1), 'Motor2': (2.1, 6), 'Motor3': (1, 1.94), 'Motor4': (1, 1.94), } # 简化价格函数,消除冗余计算 prices = { 'Motor1': lambda x: x * 5000, 'Motor2': lambda y: (y / 0.45) * 5500, 'Motor3': lambda z: z * 0.45 * 5100, 'Motor4': lambda a: (a / 0.45) * 5200, } model = GEKKO() # 定义决策变量:x的lb改为0,允许电机不运行时功率为0 x = {} y = {} for motor in power_ranges: lower, upper = power_ranges[motor] x[motor] = model.Var(lb=0, ub=upper) # lb设为0 y[motor] = model.Var(lb=0, ub=1, integer=True) # 目标函数:最小化总成本 model.Minimize(sum(prices[motor](x[motor]) for motor in power_ranges)) # 运行/不运行约束:要么x=0(y=0),要么x在功率范围内(y=1) for motor in power_ranges: lower, upper = power_ranges[motor] model.Equation(x[motor] >= lower * y[motor]) model.Equation(x[motor] <= upper * y[motor]) # 设置总功率约束:可替换为范围约束 # 范围约束示例: # model.Equation(sum(x[motor] for motor in power_ranges) >= 1) # model.Equation(sum(x[motor] for motor in power_ranges) < 4.7) model.Equation(sum(x[motor] for motor in power_ranges) == 1) # 求解模型(SOLVER=1为APOPT,适合混合整数优化) model.options.SOLVER = 1 model.solve(disp=False) # disp=False关闭求解过程输出 # 输出结果 if model.options.APPSTATUS == 1: print("最优解:") for motor in power_ranges: print(f"{motor}: {round(float(x[motor].value[0]), 2)} (运行状态:{'运行' if round(y[motor].value[0]) ==1 else '停止'})") print(f"总成本:{round(float(model.options.OBJFCNVAL), 2)}") else: print("未找到可行解。")
运行结果说明
- 当总功率约束设为
==1时,最优解为Motor3运行(功率1),其他电机停止,总成本2295.0,符合预期的最低成本。 - 当设置为
1<=sum(x)<4.7时,求解器会自动选择成本最低的组合(如仅运行Motor3)。
内容的提问来源于stack exchange,提问作者Miguff
相关产品推荐
相关产品推荐

