GAMS中如何实现依赖其他方程变量的带条件方程?
GAMS中解决内生变量条件分支问题(修复"Endogenous $ operation not allowed"错误)
问题描述
我在构建以最小化总成本为目标的MiNLP模型时,需要实现以下逻辑:
- 当
P_Net(t) = Req_Load(t) - P_RE(t) >= 0(可再生能源不足以满足负荷,需从电网购电/储能)时,让C_sell=0 - 当
P_Net(t) < 0(可再生能源过剩,需售电回电网)时,让C_sell=1
基于这个逻辑,我尝试写出如下方程:
Scalar C_sell /1/; Eq_P_New(t).. P_New(t) = P_Net(t) - [P_grid(t) * (1 - C_sell$(P_Net.l(t) < 0))];
但运行时收到错误:
Endogenous $ operation not allowed.
我试过将变量转为标量,但解会固定为单一值;也尝试用循环模拟if逻辑,均未成功。
解决方案:用二元变量建模互斥场景
GAMS不允许在方程的$条件中引用内生变量(优化过程中会变化的变量值,比如P_Net.l(t)),因此需要通过二元整数变量显式定义两种互斥场景,这是处理这类逻辑的标准方法,适配MiNLP模型。
步骤1:定义二元变量
添加一个时段维度的二元变量is_selling(t),用来标记当前时段的场景:
Binary Variable is_selling(t);
is_selling(t) = 1:当前时段为售电回电网场景(P_Net(t) < 0)is_selling(t) = 0:当前时段为购电/储能场景(P_Net(t) >= 0)
步骤2:绑定二元变量与P_Net(t)的逻辑关系
使用大M法(Big M)添加约束,确保is_selling(t)的取值与P_Net(t)的正负严格对应:
Scalar M /1e6/; // 根据模型中P_Net的最大可能绝对值调整,需足够大 Eq_Sell_Upper(t).. P_Net(t) <= M * (1 - is_selling(t)); Eq_Sell_Lower(t).. P_Net(t) >= -M * is_selling(t);
- 当
is_selling(t)=1时,Eq_Sell_Upper强制P_Net(t) <= 0,Eq_Sell_Lower放松; - 当
is_selling(t)=0时,Eq_Sell_Lower强制P_Net(t) >= 0,Eq_Sell_Upper放松。
步骤3:重构目标方程
用is_selling(t)替代原逻辑中的C_sell,重构Eq_P_New:
原逻辑中,1-C_sell在购电场景取1,售电场景取0,正好对应1-is_selling(t)的取值,因此方程可写为:
Eq_P_New(t).. P_New(t) =e= P_Net(t) - P_grid(t) * (1 - is_selling(t));
此时无需再使用标量C_sell。
步骤4:(可选)在目标函数中区分场景成本
如果购电和售电有不同的成本/收益,可在目标函数中通过is_selling(t)区分:
Scalar cost_buy /0.2/; // 单位购电成本 Scalar revenue_sell /0.15/; // 单位售电收益 Obj.. TotalCost =e= sum(t, cost_buy * P_grid(t) * (1 - is_selling(t)) // 购电成本 - revenue_sell * P_grid(t) * is_selling(t) // 售电收益(抵减总成本) );
原方法失效原因
GAMS的$条件仅支持引用外生变量(优化过程中固定不变的量),而P_Net.l(t)是内生变量的迭代值,属于求解器动态调整的对象,因此无法用$来基于它做条件判断,这就是报错的核心原因。
内容的提问来源于stack exchange,提问作者Alaa Alsaffar
相关产品推荐
相关产品推荐

