CPLEX OPL约束未生效:决策变量c未被限制为小于等于元组集s对应值
问题根因
- 执行顺序不符合OPL运行规则:OPL会优先完成模型声明、约束生成,最后才执行
execute脚本块。你在subject to约束块中计算card(s)时,s还没被脚本填充,是空集,此时card(s)=0,对应的forall循环没有任何迭代,根本不会生成约束,自然约束不生效。 - 约束逻辑错误:即便
s提前填充完成,你写的双重循环forall( k in w, i in 1.. card(s) )会给每个c[k]叠加所有s元素的value上限,最终所有c都会被限制为小于等于s中的最小值1,和你「每个c[k]仅对应s中同位置value上限」的需求完全不符。 - 元组取值逻辑错误:
item(s,<i>)是按元组定义的key字段做匹配查找,你的元组key是rank字段,不是元组在集合中的插入序号,哪怕s填充完成,这种写法也不能按位置取到对应元组。
修复方法
- 将元组集
s的填充逻辑从后置execute块移到模型声明阶段,保证约束生成时s已经是填充完成的状态。 - 删掉错误的双重循环,直接遍历
s中的元素,按元素的rank字段匹配c的索引添加上限约束即可。
修复后可运行的完整代码:
int n=4; range r=1..n; int m=11; range w=1..m; int a[r]=[1,3,2,5]; tuple t { key int rank; int value; } // 声明阶段直接生成s,无需后置脚本填充 {t} s={ <rank, a[i]> | i in r, j in 1..a[i], rank == sum(pre in 1..i-1) a[pre] + j }; // 按实际需求定义c的类型,整数变量用dvar int+,连续变量用dvar float+ dvar int+ c[w]; subject to { // 遍历s的每个元素生成对应约束 forall( elem in s ) c[elem.rank] <= elem.value; } execute { // 可通过writeln打印s验证内容 writeln("生成的元组集s:", s); }
效果验证
上述代码生成的s内容为<1 1>, <2 3>, <3 3>, <4 3>, <5 2>, <6 2>, <7 5>, <8 5>, <9 5>, <10 5>, <11 5>,对应生成的约束完全匹配需求:
- c[1] ≤ 1
- c[2]、c[3]、c[4] ≤ 3
- c[5]、c[6] ≤ 2
- c[7]~c[11] ≤5
内容的提问来源于stack exchange,提问作者MO MO MA
相关产品推荐
相关产品推荐

