GAMS MCP模型:能否自动循环修改集合t结束值求解?
可行实现方案
要实现自动循环求解不同时间范围的场景,核心是动态调整时间集合范围并在每次循环中重新初始化依赖该集合的子集与参数,以下是具体实现步骤和修正后的代码:
关键思路
- 先定义包含所有时间点的基础集合
t_all,再用动态集合t控制每次循环的有效时间范围 - 遍历目标结束时间(从29到2倒序),每次循环更新
t的范围 - 重新计算依赖
t的子集(t0、ts、ts2、tn),因为这些子集的定义依赖集合t的长度和元素位置 - 求解模型后,将结果按结束时间存储到参数中
修正后的完整核心代码
Sets t_all time period /0*30/ // 包含所有时间点的基础集合 t(t_all) active time periods // 动态集合,控制每次循环的有效时间范围 t0(t) Period t=0 ts(t) Simulation periods ts2(t) Simulation periods except t=1 tn(t) Last period ; Scalars end_t ; // 循环变量,存储当前场景的结束时间 Parameters SumD(t_all) ; // 存储每个结束时间对应的CumD结果 Variables p(t) Price d(t) Demand CumD Cumulative demand m_in(t) Inflow m_out(t) Outflow M(t) Size C(t) Cancellation ; Equations EQ1(t) EQ2(t) EQ3(t) EQ4(t) EQ5(t) EQ6(t) EQ7(t) EQ7SUM ; Model MSR_YES /EQ1.m_in, EQ2.m_out, EQ3.C, EQ4.M, EQ5.p, EQ6.B, EQ7.d, EQ7SUM.CumD / ; // 倒序循环结束时间:从29到2 loop(end_t$(end_t ge 2 and end_t le 29), // 1. 设置当前循环的有效时间范围:0到end_t t(t_all) = yes$(ord(t_all) le end_t + 1); // ord(t_all)从1开始,对应t=0是第1个元素,所以end_t对应ord=end_t+1 // 2. 重新计算依赖t的子集 t0(t) = yes$(ord(t) eq 1); // 对应t=0 ts(t) = yes$(ord(t) gt 1); ts2(t) = yes$(ord(t) gt 1 and ord(t) lt card(t)); tn(t) = yes$(ord(t) eq card(t)); // 对应当前t的最后一个元素(即end_t) // 3. 求解模型 solve MSR_YES using mcp; // 4. 保存当前场景的CumD结果 SumD(end_t) = CumD.l; );
关键细节说明
- 动态集合赋值:
t(t_all) = yes$(ord(t_all) le end_t + 1)是因为GAMS中集合元素的ord()从1开始,t_all的第1个元素是0,第31个是30,所以当end_t=29时,需要取前30个元素(ord≤30),对应t=0*29 - 子集重计算:每次循环必须重新计算
t0、ts等子集,因为card(t)(集合t的元素个数)和ord(t)会随t的范围变化而改变 - 循环范围控制:用
end_t$(end_t ge 2 and end_t le 29)确保只遍历目标结束时间,倒序循环直接通过end_t从29到2的自然递减实现(GAMS的loop会自动按数值顺序遍历) - 结果存储:用
SumD(end_t)直接关联结束时间和对应结果,后续可通过display SumD;查看所有场景的结果
内容的提问来源于stack exchange,提问作者MaxIsaac
相关产品推荐
相关产品推荐

