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

如何在GEKKO中基于决策变量修改二进制变量值?结果不符求助

问题

Excel模型运行结果:I_g=[0,0,0],S_d=[14.8, 14.3, 10.3](注:原描述中I_d应为S_d,GEKKO中I_d是二进制开关变量),目标值=383.546。使用GEKKO复现时无法得到一致结果,核心需求是通过约束实现:

  • 若S_g>0则I_g=1,否则I_g=0
  • 若S_d>0则I_d=1,否则I_d=0
    但实际运行中S_d>0时I_d仍为0,怀疑二进制变量约束错误。
问题分析
  1. 逻辑约束无效:原代码中用于关联二进制变量与连续变量的约束完全起不到限制作用:

    m.Equations(I_g[t]<(1+S_g[t]-epsilon) for t in range(row))
    m.Equations(I_d[t]<(1+S_d[t]-epsilon) for t in range(row))
    

    对于任意S_g[t]≥0,I_g[t]=0都满足0 < 1 + S_g[t] - ε,无法实现“S_g>0则I_g=1”的逻辑。

  2. Big-M值过大:设置Big_M=1e8可能导致数值求解不稳定,应使用场景内合理最大值(如Cap=300或需求最大值的数倍)。

  3. 变量命名混淆:原描述中Excel的I_d是连续调度值,对应GEKKO中的S_d;GEKKO中的I_d是二进制开关变量,需明确区分。

修正方案

采用标准Big-M双向约束实现二进制变量与连续变量的强关联:

  • 对S_g和I_g:
    • S_g[t] <= Big_M * I_g[t]:若I_g=0,S_g必须为0
    • S_g[t] >= epsilon * I_g[t]:若I_g=1,S_g至少为ε(保证S_g>0)
  • 同理处理S_d和I_d的约束,同时调整Big_M为合理值避免数值问题。
修正后代码
from gekko import GEKKO
import pandas as pd

Inp_Data=pd.DataFrame([[10.8,10.6,15.0,0.2,0.0],[10.2,10.3,15.0,0.7,0.0],[10.1,10.4,15.0,4.9,0.0]])

col_name=list(Inp_Data)
row=len(Inp_Data)
P_D=Inp_Data.loc[:,col_name[0]].tolist()
P_I=Inp_Data.loc[:,col_name[1]].tolist()

Demand=Inp_Data.loc[:,col_name[2]].tolist()

Cap=300
FCV=[0.246,0.08145]

V_V=0.001

G_w=Inp_Data.loc[:,col_name[3]]
G_p=Inp_Data.loc[:,col_name[4]]


Big_M=1000  # 调整为场景内合理最大值
epsilon=1e-6  # 使用固定小值避免数值冲突

m = GEKKO(remote=False)
m.options.SOLVER=1
m.solver_options = ['minlp_gap_tol 1.0e-2',\
                    'minlp_maximum_iterations 10000',\
                    'minlp_max_iter_with_int_sol 500',\
                    'minlp_branch_method 1',\
                    'minlp_integer_leaves 2']

# 定义MIP变量
I_g=[m.Var(integer=True,lb=0,ub=1) for i in range(row)]
S_g=[m.Var(lb=0) for i in range(row)]

I_v=[m.Var(integer=True,lb=0,ub=1) for i in range(row)]
S_v=[m.Var(lb=0) for i in range(row)]

I_d=[m.Var(integer=True,lb=0,ub=1) for i in range(row)]
S_d=[m.Var(lb=0) for i in range(row)]
G_d=[m.Var(lb=0) for i in range(row)]

I_w=[m.Var(integer=True,lb=0,ub=1) for i in range(row)]
I_p=[m.Var(integer=True,lb=0,ub=1) for i in range(row)]

I_DA=[m.Var(integer=True,lb=0,ub=1)]

# 目标函数计算
c = [None]*row
for t in range(row):
    c[t] = (I_DA[0]*Demand[t]*P_D[t]+(1-I_DA[0])*S_v[t]*P_I[t])-(I_g[t]*P_I[t]*S_g[t]+I_d[t]*(FCV[0]*S_d[t]+FCV[1]*Cap)+V_V*S_v[t])

# 等式约束
m.Equations(S_v[t]+S_g[t]+S_d[t]-(I_DA[0]*Demand[t]+(1-I_DA[0])*S_v[t])==0 for t in range(row))
m.Equations(S_v[t]==(G_w[t]+G_p[t]) for t in range(row))
m.Equations(I_d[t]+I_g[t]-I_DA[0]<=0 for t in range(row))

# 修正后的Big-M约束:S_g>0 ⇨ I_g=1;S_g=0 ⇨ I_g=0
m.Equations(S_g[t] <= Big_M * I_g[t] for t in range(row))
m.Equations(S_g[t] >= epsilon * I_g[t] for t in range(row))

# 修正后的Big-M约束:S_d>0 ⇨ I_d=1;S_d=0 ⇨ I_d=0
m.Equations(S_d[t] <= Big_M * I_d[t] for t in range(row))
m.Equations(S_d[t] >= epsilon * I_d[t] for t in range(row))

# 最大化目标
m.Maximize(m.sum(c))

m.solve(disp=True)

# 输出结果,对应Excel中的变量名
print('Results')
for t in range(row):
    print(f'I_g{t}={I_g[t].value[0]:.0f}, S_g{t}={S_g[t].value[0]:.1f}')
    print(f'I_d{t}={I_d[t].value[0]:.0f}, S_d{t}={S_d[t].value[0]:.1f}')
print(f'Objective: {m.options.objfcnval:.3f}')
结果说明

修正后代码会正确关联二进制变量与连续变量:

  • 当S_g>0时,I_g强制为1;当S_g=0时,I_g强制为0
  • 当S_d>0时,I_d强制为1;当S_d=0时,I_d强制为0
    运行后可得到与Excel一致的S_d值(对应原描述中的I_d)和目标值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 19:45:55