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

如何通过OR-Tools调用SCIP获取MIP问题的Top N最优解?

问题

希望通过SCIP获取MIP问题的前N个最优解——SAT求解器在解数量过多时耗时太长,已知OR-Tools仅支持Gurobi或SCIP实现多解获取,于是用OR-Tools的MIP示例测试,代码如下:

from ortools.linear_solver import pywraplp

solver = pywraplp.Solver.CreateSolver("SCIP")

infinity = solver.infinity()
x = solver.IntVar(0.0, infinity, "x")
y = solver.IntVar(0.0, infinity, "y")

solver.Add(x + 7 * y <= 17.5)
solver.Add(x <= 3.5)

solver.Maximize(x + 10 * y)

print(f"Solving with {solver.SolverVersion()}")
status = solver.Solve()

if status == pywraplp.Solver.OPTIMAL:

    for _ in range(5):

        print(f"Objective value = {solver.Objective().Value():0.3f}")
        print("x =", x.solution_value())
        print("y =", y.solution_value())

        if solver.NextSolution():
            print(f"There is another solution: ")
        else:
            print("No more solutions")
            break

else:
    print("The problem does not have an optimal solution.")

执行后仅得到两个解,第二个为非最优的0值解,不符合需求:

Solving with SCIP 9.0.0 [LP solver: Glop 9.10]
Objective value = 23.000
x = 3.0
y = 2.0
There is another solution:
Objective value = 0.000
x = 0.0
y = 0.0
No more solutions

尝试配置SCIP参数但无效果:

solver = pywraplp.Solver.CreateSolver("SCIP")

solver.SetSolverSpecificParametersAsString("limits/solutions=-1")
solver.SetSolverSpecificParametersAsString("limits/bestsol=-1")
solver.SetSolverSpecificParametersAsString("constraints/countsols/sollimit=-1")
solver.SetSolverSpecificParametersAsString("constraints/countsols/collect=TRUE")
solver.SetSolverSpecificParametersAsString("constraints/countsols/discardsols=FALSE")
...

请问操作是否有误?获取前N个最优解的需求是否可实现?


解决方案

你的需求完全可实现,操作上存在两个核心问题:

1. 参数设置方式错误

SetSolverSpecificParametersAsString每次调用会覆盖之前的参数,无法累加。必须将所有参数合并为一个字符串一次性设置:

solver.SetSolverSpecificParametersAsString("""
limits/solutions=-1
limits/bestsol=-1
constraints/countsols/sollimit=-1
constraints/countsols/collect=TRUE
constraints/countsols/discardsols=FALSE
""")

2. 缺少最优解枚举的关键配置

默认情况下NextSolution()会返回任意可行解,而非仅最优解。要获取前N个最优解,需添加以下SCIP参数:

  • focus/bestsol=TRUE:让SCIP优先搜索最优解
  • limits/bestsol=N:限制仅收集N个最优解(替换N为目标数量)
  • constraints/countsols/onlybest=TRUE:仅收集最优解,过滤非最优可行解

修改后的完整参数示例:

solver = pywraplp.Solver.CreateSolver("SCIP")
# 配置收集前3个最优解
solver.SetSolverSpecificParametersAsString("""
focus/bestsol=TRUE
limits/bestsol=3
constraints/countsols/collect=TRUE
constraints/countsols/discardsols=FALSE
constraints/countsols/onlybest=TRUE
""")

3. 测试问题的最优解数量验证

你的测试问题本身只有1个整数最优解:x=3、y=2,目标值23。其他可行解(如x=0、y=0)均为非最优解,这也是你只能获取一个最优解的原因。

若要测试多最优解场景,可调整问题为:

# 将x改为连续变量,扩大上限
x = solver.NumVar(0.0, 10.0, "x")
y = solver.IntVar(0.0, infinity, "y")
solver.Add(x + 7 * y <= 17.5)
solver.Maximize(x + 10 * y)

此时y=2时,x可取0到3.5之间的任意值,均为最优解(目标值20+x),能验证多最优解的收集逻辑。


内容的提问来源于stack exchange,提问作者Manuel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 16:27:34