首页 > 解决方案 > Cplex Refiner:如何仅添加现有的约束条件为左手或右手?

问题描述

cplex 细化器会发现损坏的约束。我想向用户展示有关其模型实际冲突的详细信息。

因此,我想将矩阵的每个约束拆分为单独的约束。左撇子和右撇子。例子:

10 <= x1 <= 40

应该变成

10 <= x1 <= infinity
-infinity <= x1 <= 40

这在数学上是相等的。

IBM 关于 cplex 精炼器的示例 ( http://www-01.ibm.com/support/docview.wss?uid=swg21429472 ) 使用这段代码来考虑约束:

for (int c1 = 0; c1 < rng.Length; c1++)
{
    constraints[c1] = rng[c1];
}

我稍微更新了它,以拆分约束(请注意:IBM 示例大量使用约束数组的索引。所有这些 locs 也需要更新)

for (int c1 = 0; c1 < rng.Length; c1++)
{
    constraints[c1] = cplex.Ge(rng[c1].Expr, rng[c1].LB);
}
for (int c1 = 0; c1 < rng.Length; c1++)
{
    constraints[rng.Length + c1] = cplex.Le(rng[c1].Expr, rng[c1].UB);
}

这是我使用的模型文件。(显然,x1 的边界与 c3 和 c4 冲突。)

 Maximize
      obj: x1 + 2 x2 + 3 x3
 Subject To
      c1:  x2 + x3 <= 20
      c2: x1 - 3 x2 + x3 <= 30
      c3: x1 <= 40
      c4: x1 >= 40
 Bounds
      10 <= x1 <= 10    
 Generals
      x1 x2 x3
 End

具有拆分约束的代码的更新版本会打印损坏的结果(首先是左侧,然后是右侧)。它只显示 x1 是冲突的一部分(你不能单独成为冲突。它需要有一个伙伴!)

Solution status = Infeasible
Model Infeasible, Calling CONFLICT REFINER
Number of SOSs=0
IloRange  : -infinity <= (1*x2 + 1*x3) <= infinity
IloRange  : -infinity <= (1*x1 - 3*x2 + 1*x3) <= infinity
IloRange  : -infinity <= (1*x1) <= infinity
IloRange  : 40 <= (1*x1) <= infinity
IloRange  : -infinity <= (1*x2 + 1*x3) <= 20
IloRange  : -infinity <= (1*x1 - 3*x2 + 1*x3) <= 30
IloRange  : -infinity <= (1*x1) <= 40
IloRange  : -infinity <= (1*x1) <= infinity
Lower bound of x1
Upper bound of x1
Lower bound of x2
Upper bound of x2
Lower bound of x3
Upper bound of x3
Conflict Refinement process finished: Printing Conflicts
 Proved : Upper bound of x1
Conflict Summary:
 Constraint conflicts = 0
 Variable Bound conflicts = 1
 SOS conflicts = 0
Calling FEASOPT

带有双手约束的原始版本打印出预期的结果(c4 和 x1 是冲突的一部分)

Solution status = Infeasible
Model Infeasible, Calling CONFLICT REFINER
Number of SOSs=0
IloRange c1 : -infinity <= (1*x2 + 1*x3) <= 20
IloRange c2 : -infinity <= (1*x1 - 3*x2 + 1*x3) <= 30
IloRange c3 : -infinity <= (1*x1) <= 40
IloRange c4 : 40 <= (1*x1) <= infinity
Lower bound of x1
Upper bound of x1
Lower bound of x2
Upper bound of x2
Lower bound of x3
Upper bound of x3
Conflict Refinement process finished: Printing Conflicts
 Proved : IloRange c4 : 40 <= (1*x1) <= infinity
 Proved : Upper bound of x1
Conflict Summary:
 Constraint conflicts = 1
 Variable Bound conflicts = 1
 SOS conflicts = 0
Calling FEASOPT

标签: cplex

解决方案


RefineConflict的文档为参数说明了以下内容cons

一组约束。它们可能是一组范围上的 IRange 或 IAnd 构造。只能指定直接添加到模型的约束。

在您修改的代码段中,您正在向尚未添加到模型中的数组添加新约束例如,您使用constraints方法而不是方法)。GeAddGe

我想您可以执行以下操作:

cplex.Remove(rng); // First remove the original constraints
for (int c1 = 0; c1 < rng.Length; c1++)
{
    IRange tmp = rng[c1];
    // Now, add new constraints to the model and save them in the constraints array.
    constraints[c1] = cplex.AddGe(tmp.Expr, tmp.LB);
    constraints[rng.Length + c1] = cplex.AddLe(tmp.Expr, tmp.UB);
}

您应该在调用之前添加以下行RefineConflict以确保修改后的模型看起来像您期望的那样:

cplex.ExportModel("modified.lp");

推荐阅读