
cvxpy 不直接支持 `!=` 约束,但可通过引入小正数 ε 构造绝对值不等式 `|x − c| ≥ ε` 来等价建模,从而将“不等于”转化为标准凸约束(需注意该技巧仅适用于离散化或容差可接受的场景)。
在 CVXPY 中,所有约束必须满足凸性与可解析性要求,因此原生仅支持 ==(仿射等式)、=(凸/凹不等式)三类基本约束。!= 本质上是非凸、非闭合的集合约束(即开集并集:(-∞, c) ∪ (c, +∞)),CVXPY 无法直接处理。但实践中,我们常可借助数值容差将其近似为一个可行的凸替代形式。
✅ 推荐做法:用绝对值下界模拟“不等于”
对任意变量 x 与目标值 c = 3/M,添加约束:
eps = 1e-4 # 建议从 1e-4 开始,根据问题尺度(如 M 大小)调整 constraints.append(cp.abs(z[p][i, j] - 3/M) >= eps)
其中 i = offices.index(office), j = offices.index(linked_office)。该约束强制 z[p][i, j] 落在区间 [0, 3/M − ε] ∪ [3/M + ε, 1] 内,从而避开 3/M 的邻域,逼近你所需的 z ∈ [0, 3/M) ∪ (3/M, 1]。
⚠️ 注意事项:ε 需谨慎选择:若 ε 过大(如 1e-1),可能意外裁剪掉本应可行的解;若过小(如 1e-12),易因数值精度导致求解器判定不可行(feasibility tolerance 冲突)。建议结合 3/M 的量级设定——例如当 M=1000 时,3/M = 0.003,则 eps = 1e-4(约为其 3%)是合理起点。不可用于严格理论证明:该方法是工程近似,不保证数学上完全排除 z[i,j] == 3/M,但在实际优化中可有效规避该点。避免在整数规划中滥用:若 z 本应为整数变量(如 0–1 变量),请改用 cp.Variable(..., boolean=True) 或 integer=True,此时 != 可通过逻辑拆分自然满足(如 z = 1),无需 abs 技巧。
? 整合到你的代码中(推荐写法)
# 在定义 constraints 后、调用 cp.Problem 前插入:
eps = 1e-4
for p in range(P):
for office in offices:
for linked_office in linked_offices[office]:
i = offices.index(office)
j = offices.index(linked_office)
# 添加避开 3/M 的约束
constraints.append(cp.abs(z[p][i, j] - 3/M) >= eps)? 进阶提示:更鲁棒的建模方式
若问题允许,更优策略是重构变量语义:例如将 z[p][i,j] 显式定义为二元组合 z = α * a + β * b,其中 a ∈ [0, 3/M), b ∈ (3/M, 1],α + β = 1, α, β ∈ {0,1} —— 即引入辅助二元变量,将开区间约束转化为混合整数凸规划(MIP)。但这会显著增加求解难度,仅在精度要求极高且 P, n 较小时考虑。
总之,cp.abs(x - c) >= eps 是 CVXPY 中实现 != 的标准、简洁且广泛验证的工程方案。只要合理设置 eps 并理解其数值意义,即可稳健支撑你的优化建模需求。










