如何在CPLEX中实现指定集合约束?现有代码是否正确?
分析你的CPLEX约束写法是否正确
首先明确你要表达的原约束核心含义:对于任意两个不同的需求d1、d2,各自的K_sp条最短路径集合中,至少存在一对路径(一条来自d1,一条来自d2)共享至少一条链路。接下来拆解你的代码问题:
你的代码和原约束的匹配问题
你的代码做了两件事:
- 定义
Path[i]存储需求i所有路径的链路并集 - 当
Path[i]和Path[j]的链路交集非空时,约束D[i][j]+D[j][i]==1
这里存在几个关键问题:
原约束是存在性断言,不需要引入D变量
原约束是关于路径集合的固有属性(要么预先计算的路径集合天然满足这个条件,要么你实际想约束的是所选路径需满足类似要求),但你的代码引入了D[i][j]这个额外变量,却完全没把原约束的逻辑和模型决策变量关联起来。这段约束只是强制了D[i][j]和D[j][i]的和为1,根本没实现原约束的核心要求。card(Path[i] inter Path[j])!=0的实际意义
这个条件确实等价于原约束的“存在路径对共享链路”——因为Path[i]是需求i所有路径的链路并集,两个并集的交集非空,就说明存在某个链路同时出现在i的某条路径和j的某条路径中,也就是存在符合要求的路径对。但如果这是一个需要模型满足的约束,那它是基于静态数据的属性,不需要写成模型约束,只需要在预处理阶段检查数据是否满足即可。
如果你实际想建模「所选路径必须共享链路」(更常见的业务需求)
很多时候用户会混淆“路径集合中存在这样的对”和“最终所选路径必须满足这个对”。如果你实际想约束的是:任意两个需求最终选择的路径(从各自K_sp条中选)必须共享至少一条链路,那你的写法完全不对,需要用路径选择变量来建模:
假设你有0-1决策变量x[i][k],表示需求i是否选择第k条路径,正确的线性化约束应该是:
// 引入辅助变量,表示需求i选路径k且需求j选路径m dvar boolean y[Demands][Demands][K_sp][K_sp]; // 约束辅助变量y和路径选择变量x的关联关系 forall(i in Demands, j in Demands, k in K_sp, m in K_sp: i != j) { y[i][j][k][m] <= x[i][k]; y[i][j][k][m] <= x[j][m]; y[i][j][k][m] >= x[i][k] + x[j][m] - 1; } // 对每对不同需求,至少存在一对共享链路的路径被同时选择 forall(i in Demands, j in Demands: i != j) { sum(k in K_sp, m in K_sp: card(path[i][k] inter path[j][m]) > 0) y[i][j][k][m] >= 1; }
总结你的原代码是否正确
- 如果你的目标是实现原约束的「存在路径对共享链路」:你的代码没有实现这个约束,反而引入了无关的
D变量和约束。这个存在性是数据层面的属性,只需在预处理时检查forall(i,j: i!=j) card(Path[i] inter Path[j])>0是否成立即可,不需要写入模型。 - 如果你的目标是约束「所选路径必须共享链路」:你的代码完全不符合要求,需要用上面的路径选择变量+辅助变量的方式建模。
内容的提问来源于stack exchange,提问作者Mina H
相关产品推荐
相关产品推荐

