如何让CPLEX正确识别tuple中所指代的特定字段对应关系
解决方案
1. 修正过滤条件的逻辑优先级问题
你原有代码的过滤条件存在逻辑优先级错误,&&的运算优先级高于||,会导致c.copia3 != 0的判断仅作用于m == c.copia1的分支,像你举例的<3,3,4,0>这类copia3为0的实例会被错误过滤。如果你的需求是匹配特定macchina值对应的copia字段,直接添加对应判断即可:
// 仅匹配macchina为3的tuple实例,访问c.copia1、c.copia2就能直接拿到3和4 forall (c in copie : c.macchina == 3) { // 此处写对应业务逻辑 }
如果需要匹配所有“m为当前tuple三个copia字段之一且对应字段非0”的实例,需要给逻辑加括号修正优先级:
forall (c in copie : (m == c.copia1 && c.copia1 != 0) || (m == c.copia2 && c.copia2 !=0) || (m == c.copia3 && c.copia3 !=0))
2. 修正约束的变量重名问题
你现有约束里sum (m in M) y[i1][j][m] == 1的sum下标m和外层forall循环的m重名,会导致变量覆盖,CPLEX无法正确识别索引,需要把sum的下标改名:
sum (m2 in M) y[i1][j][m2] == 1;
3. 可选优化:给tuple加索引提高查询效率
如果经常需要按macchina字段查询对应tuple,可以把macchina设为tuple的键字段,CPLEX可以快速定位到对应实例:
tuple copie_macchine { key int macchina; // 设为键字段 int copia1; int copia2; int copia3; } {copie_macchine} copie = ...; // 后续查询macchina=3的实例可以直接调用item函数 copie_macchine c3 = item(copie, <3>); // 直接访问c3.copia1、c3.copia2即可拿到对应值
完整修改参考代码
tuple copie_macchine { key int macchina; int copia1; int copia2; int copia3; } {copie_macchine} copie = { <3,3,4,0>, <6,7,8,9>, <8,11,12,0>, <9,13,14,0>, <10,15,16,0>, <20,26,27,28> }; // 示例约束:每个i1、j组合下,对应macchine的非空可选copia中恰好选一个 forall (j in J) { forall (i1 in I) { forall (c in copie) { sum (m in {c.copia1, c.copia2, c.copia3} : m != 0) y[i1][j][m] == 1; } } }
内容的提问来源于stack exchange,提问作者Francesca
相关产品推荐
相关产品推荐

