You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用GEKKO求解分式目标的混合整数非线性规划时出现NaN解求助

解决GEKKO求解最大化毛利率的混合整数规划问题

问题分析

原代码直接最大化分式目标(总利润/总收入)时,出现全0解(违反3选2约束)和目标值NaN的问题,核心原因:

  • 分式目标在数值计算中易产生奇异(分母为0),导致求解器陷入局部最优;
  • 整数规划初始点选择可能触发分母为0的情况,求解器无法自动恢复。

解决方案

方法一:枚举法(适合小规模问题)

因仅3选2,共3种可行组合,直接计算每种组合的毛利率即可快速找到最优解:

# 枚举所有3选2的可行组合
combinations = [(1,1,0), (1,0,1), (0,1,1)]
max_margin = -1.0
best = None

for x1, x2, x3 in combinations:
    profit = 150*x1 + 120*x2 + 100*x3
    revenue = 200*x1 + 150*x2 + 250*x3
    margin = profit / revenue
    if margin > max_margin:
        max_margin = margin
        best = (x1, x2, x3)

print(f"最优组合:x1={best[0]}, x2={best[1]}, x3={best[2]}")
print(f"最大毛利率:{max_margin:.4f}")

运行结果:

最优组合:x1=1, x2=1, x3=0
最大毛利率:0.7714

方法二:线性化重构目标(适合大规模问题)

将分式目标转化为线性约束+线性目标,避免数值奇异:

  • 引入辅助变量gamma表示毛利率;
  • 最大化gamma,同时满足总利润 >= gamma * 总收入(等价于gamma <= 总利润/总收入);
  • 保留原约束(3选2、总收入>0)。

修正后的GEKKO代码:

from gekko import GEKKO

m = GEKKO(remote=False)
# 二进制决策变量
x1 = m.Var(integer=True, lb=0, ub=1)
x2 = m.Var(integer=True, lb=0, ub=1)
x3 = m.Var(integer=True, lb=0, ub=1)
# 毛利率变量,范围0-1
gamma = m.Var(lb=0, ub=1)

# 定义总利润和总收入
profit = 150*x1 + 120*x2 + 100*x3
revenue = 200*x1 + 150*x2 + 250*x3

# 核心约束:毛利率的等价转化
m.Equation(profit >= gamma * revenue)
# 3选2约束
m.Equation(x1 + x2 + x3 == 2)
# 确保总收入不为0(可选,3选2自动满足)
m.Equation(revenue >= 1e-3)

# 目标:最大化毛利率
m.Maximize(gamma)

# 使用APOPT求解混合整数规划
m.options.SOLVER = 1
m.solve(disp=True)

print(f"x1: {x1.value[0]}, x2: {x2.value[0]}, x3: {x3.value[0]}")
print(f"最大毛利率: {gamma.value[0]:.4f}")

运行结果:

x1: 1.0, x2: 1.0, x3: 0.0
最大毛利率: 0.7714

关键说明

  • 原代码失败的本质是分式目标的数值不稳定性,求解器遇到分母为0的奇异点后无法找到可行解;
  • 线性化重构后的模型属于混合整数线性规划(MILP),APOPT求解器能高效处理这类问题,避免数值奇异;
  • 若变量规模大(如几十上百个产品),优先使用线性化方法,枚举法仅适用于小规模场景。

内容的提问来源于stack exchange,提问作者soumyajt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 13:53:12