You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 14:18:02