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

GEKKO优化出现方程约束超限及变量生成异常问题求助

问题原因分析与修正方案

问题1:总降价支出约束未生效

约束失效的根源是delta变量被错误地生成为数组,同时初始参数计算逻辑有误:

  • 原本预期每个用户对应1个delta标量,但代码中用np.sum(ml_bought[user]*delta_user[user])时,GEKKO会将标量Var与数组Param进行元素级乘法,自动把delta广播成和购买量数组同形状的数组。此时每个数组元素都能取到delta_max,总支出自然超出预算。
  • delta_basic的计算逻辑错误:sum(cons['user1'] +cons['user2']+cons['user3']+cons['user4'])是先元素级相加数组再求和,正确的总购买量应该是每个用户的购买量数组求和后再累加,这导致delta_min、delta_max的基准值计算偏差。

问题2:delta_user变成数组而非单个值

核心原因是使用了numpy的np.sum()处理GEKKO变量与数组的运算:
GEKKO的Var默认是标量,当与numpy数组Param进行元素级乘法时,会自动触发广播机制,将标量Var扩展为同形状的数组Var,违背了“每个用户对应1个delta值”的预期。


修正后的代码

import numpy as np
from gekko import GEKKO

cons = {'user1' :np.array([1,2,3,4]),
        'user2' : np.array([5,6,7,8]),
        'user3' : np.array([0.8,1,5,9]),
        'user4' : np.array([16,8,7,1])}
auto = {
    'user1': 0.7,
    'user2' : 0.6,
    'user3' : 0.32,
    'user4': 0.44
}

m=GEKKO(remote=False)
m.options.IMODE = 2
m.options.SOLVER = 1
m.options.CV_TYPE = 2
m.options.RTOL=1e-4
m.options.OTOL=1e-4

delta_user = {} # 每个用户对应单个降价幅度变量
ml_bought={} # 用户购买量数组
benefit_user = {} # 用户总降价支出
self_cons = {} # 自耗权重参数

fondos = m.Const(value =30)

# 修正总购买量计算:累加每个用户的购买总量
total_quantity = sum(np.sum(v) for v in cons.values())
delta_basic = 30 / total_quantity
delta_min = delta_basic * 0.75
delta_max = delta_basic * 1.25

for user in cons:
    # 每个用户仅创建1个标量降价变量
    delta_user[user] = m.Var(lb=delta_min, ub=delta_max, value=delta_basic)
    self_cons[user] = m.Param(auto[user])
    ml_bought[user] = m.Param(cons[user])
    # 使用GEKKO原生sum函数,避免numpy广播生成数组
    benefit_user[user] = m.Intermediate(m.sum(ml_bought[user] * delta_user[user]))

# 总支出约束
m.Equation(m.sum([benefit_user[user] for user in cons]) <= fondos)

# 目标函数:加权总收益最大化
m.Maximize(m.sum([benefit_user[user] * (self_cons[user]**2) for user in cons]))

m.solve(disp=True)

# 输出结果
print("各用户降价幅度:")
for user in delta_user:
    print(f"{user}: {delta_user[user].value[0]}")

total_expense = sum(benefit_user[user].value[0] for user in benefit_user)
print(f"\n总降价支出:{total_expense}")

关键修正点

  1. 参数计算修正:用sum(np.sum(v) for v in cons.values())正确计算总购买量,确保delta_basic等基准值准确。
  2. 避免数组广播:替换np.sum()为GEKKO原生的m.sum(),保证每个delta_user[user]始终是标量变量。
  3. 结果提取:通过.value[0]获取GEKKO标量Var的数值(Var的value属性为列表,单个值取索引0)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 16:13:12