如何在GAMS中记忆索引t并调用between函数编写约束?
在GAMS中实现带between函数的关联约束
核心思路
要实现“记录第一个约束满足条件的t值,再用该值作为第二个约束的起始点”,需要通过辅助变量捕获关键t值,再基于这个值构建后续约束。以下是具体实现步骤:
1. 定义基础集合与变量
首先声明索引集合、核心变量及辅助变量:
Set t /1*10/; * 核心变量(根据实际需求替换) Variable x(t), y(t); * 辅助变量:用于记录第一个约束满足条件的t值 Integer Variable t0; t0.up = card(t); * 上限设为t的最大索引值10 t0.lo = 1; * 下限设为t的最小索引值1 * 二进制辅助变量:标记哪个t满足第一个约束的between条件 Binary Variable delta(t);
2. 第一个约束:捕获满足between条件的t值
假设第一个约束要求x(t)落在[L1, U1]区间内,且仅存在一个这样的t(若允许多个,可删除约束1a):
* 约束1:x(t)在[L1, U1]区间时,delta(t)=1;否则delta(t)=0 Constr1(t): between(L1, x(t), U1) = delta(t); * 约束1a:确保只有一个t满足条件(按需保留) Constr1a: sum(t, delta(t)) = 1; * 约束1b:将满足条件的t值赋值给t0 Constr1b: t0 = sum(t, t*delta(t));
3. 第二个约束:以t0为起始点判断终止条件
假设第二个约束要求从t0到10的所有t,y(t)落在[L2, U2]区间内:
* 约束2:对t >= t0的索引,y(t)需在[L2, U2]区间内 Constr2(t): if(t.val >= t0.l, between(L2, y(t), U2) = 1);
注:GAMS中
if语句可用于约束的条件性定义,t.val是集合t的当前元素值,t0.l是辅助变量t0的当前水平值。
替代实现(无需二进制变量)
如果需要找到最小的满足between条件的t,可直接用逻辑约束定义t0:
* 约束1:x(t)在[L1, U1]区间 Constr1(t): between(L1, x(t), U1) = 1; * 约束1a:t0是满足Constr1的最小t Constr1a(t): t0 <= t + (1 - between(L1, x(t), U1))*card(t); Constr1b: t0 >= sum(t, t*between(L1, x(t), U1))/card(t);
关键说明
between(lower, expr, upper)是GAMS内置函数,当lower <= expr <= upper时返回1,否则返回0;- 辅助变量
t0的取值逻辑需根据业务场景调整,比如是否允许多个t满足第一个约束; - 若第二个约束的终止条件是“从t0到指定t_end”,只需调整
if语句中的判断条件即可。
内容的提问来源于stack exchange,提问作者Starwinwin
相关产品推荐
相关产品推荐

