OR-Tools/SCIP中如何为MIP问题使用Indicator Constraints?
OR-Tools Java MIP 指示约束实现方案
目前官方未公开MIP场景下指示约束的Java示例,以下为两种可直接落地的实现方式:
方案1:大M法等效实现(全MIP求解器通用)
该方案不需要调用特定指示约束API,通过常规线性约束即可等效实现指示约束逻辑,适配所有MIP求解器。
示例场景
当二进制变量b取值为1时,满足约束x + 2y ≤ 10;b取值为0时该约束无限制。
代码示例
import com.google.ortools.Loader; import com.google.ortools.linearsolver.MPConstraint; import com.google.ortools.linearsolver.MPObjective; import com.google.ortools.linearsolver.MPSolver; import com.google.ortools.linearsolver.MPVariable; public class IndicatorConstraintDemo { public static void main(String[] args) { Loader.loadNativeLibraries(); // 选择SCIP作为MIP求解器 MPSolver solver = MPSolver.createSolver("SCIP"); if (solver == null) { System.out.println("无法加载SCIP求解器"); return; } // 定义变量 double INF = Double.POSITIVE_INFINITY; MPVariable b = solver.makeIntVar(0, 1, "b"); // 二进制指示变量 MPVariable x = solver.makeNumVar(0, 100, "x"); MPVariable y = solver.makeNumVar(0, 100, "y"); // 大M取值需大于等于x+2y的最大可能值,这里x和y最大都是100,所以大M取300足够 double M = 300; // 等效指示约束:x + 2y ≤ 10 + M*(1 - b) → 整理为x + 2y + M*b ≤ 10 + M MPConstraint indicatorEq = solver.makeConstraint(-INF, 10 + M); indicatorEq.setCoefficient(x, 1); indicatorEq.setCoefficient(y, 2); indicatorEq.setCoefficient(b, M); // 示例目标:最大化x + y MPObjective objective = solver.objective(); objective.setCoefficient(x, 1); objective.setCoefficient(y, 1); objective.setMaximization(); // 测试:强制b=1,看约束是否生效 MPConstraint fixB = solver.makeConstraint(1, 1); fixB.setCoefficient(b, 1); solver.solve(); System.out.println("b = " + b.solutionValue()); System.out.println("x = " + x.solutionValue()); System.out.println("y = " + y.solutionValue()); System.out.println("x + 2y = " + (x.solutionValue() + 2*y.solutionValue())); } }
方案2:直接调用MPIndicatorConstraint类(仅支持兼容指示约束的求解器如SCIP)
Java API中MPIndicatorConstraint类已存在但未在MPSolver中暴露直接添加方法,可通过构造对象后调用求解器的addConstraint方法添加,仅适配支持指示约束的求解器。
代码示例(对应上述相同场景)
import com.google.ortools.Loader; import com.google.ortools.linearsolver.MPIndicatorConstraint; import com.google.ortools.linearsolver.MPObjective; import com.google.ortools.linearsolver.MPSolver; import com.google.ortools.linearsolver.MPVariable; import com.google.ortools.linearsolver.LinearExpr; public class NativeIndicatorDemo { public static void main(String[] args) { Loader.loadNativeLibraries(); MPSolver solver = MPSolver.createSolver("SCIP"); if (solver == null) { System.out.println("无法加载SCIP求解器"); return; } MPVariable b = solver.makeIntVar(0, 1, "b"); MPVariable x = solver.makeNumVar(0, 100, "x"); MPVariable y = solver.makeNumVar(0, 100, "y"); // 构造指示约束:b=1时,x+2y ≤10 LinearExpr expr = LinearExpr.sum(new LinearExpr[] {x, LinearExpr.term(y, 2)}); MPIndicatorConstraint indicator = new MPIndicatorConstraint( b, 1, // 指示变量的激活值 expr, Double.NEGATIVE_INFINITY, // 约束下界 10 // 约束上界 ); solver.addConstraint(indicator); // 后续目标、求解逻辑和方案1一致 MPObjective objective = solver.objective(); objective.setCoefficient(x, 1); objective.setCoefficient(y, 1); objective.setMaximization(); MPConstraint fixB = solver.makeConstraint(1, 1); fixB.setCoefficient(b, 1); solver.solve(); System.out.println("b = " + b.solutionValue()); System.out.println("x = " + x.solutionValue()); System.out.println("y = " + y.solutionValue()); System.out.println("x + 2y = " + (x.solutionValue() + 2*y.solutionValue())); } }
注意事项
- 方案2仅支持带指示约束原生支持的求解器,如SCIP、CBC 2.10+版本,不可用于GLOP、CLP等纯LP求解器
- 大M法取值需要根据变量上下界合理选择,避免过大导致数值精度问题,或过小导致约束逻辑错误
内容的提问来源于stack exchange,提问作者epol
相关产品推荐
相关产品推荐

