前言
近几年,在工业界的大规模问题上,越来越多的人将目光聚焦于问题的可行解,而非最优解上。也就是所谓的约束满足问题,而市面上能解决工业级大规模问题的规划求解器主要有CPLEX的CP组件(商业),和OR-Tools的CP-SAT求解器(开源)。
本文介绍的CP-SAT的底层是C++,而且包含了多种语言的API,即时是Python调用也十分高效。它的底层算法利用了一些约束满足性传播搜索等方法,在定义域上搜索满足所有约束的可行解,在一些高度非凸问题上,CP-SAT相比一些MIP求解器具有支配性的效率。这里将引用公开资料当中的案例,介绍下如何用CP-SAT进行求解。
CP-SAT入门案例
简单案例:给出如下问题:有三个变量 x , y , x x,y,x x,y,x,它们的取值范围均为 {0,1,2}。求 x + y + z x+y+z x+y+z 满足约束条件 x ≠ y x ≠ y x=y 下的最大取值,并给出相应的变量值。
1. 建立模型实例
引入相关 cp_model
模块,并建立 CpModel
实例,作为存储模型信息的对象。
from ortools.sat.python import cp_model
model = cp_model.CpModel()
2. 建立决策变量
接着对决策变量进行建模,CP-SAT只支持建立整数类型(布尔类型)的基础变量,高级变量(区间变量)也是围绕整数建立的。通过 NewIntVar()
建立
x
,
y
,
z
x,y,z
x,y,z 三个变量。
x = model.NewIntVar(lb=0, ub=2, name='x')
y = model.NewIntVar(lb=0, ub=2, name='y')
z = model.NewIntVar(lb=0, ub=2, name='z')
3. 建立约束条件
这个案例中的约束条件仅有 x ≠ y x\neq y x=y,建立如下约束:
model.Add( x != y )
4. 建立目标函数
案例目标是最大化 x + y + z x+y+z x+y+z 的取值,通过如下代码将目标函数添加到模型当中。
model.Maximize( x + y + z )
5. 求解问题
CP-SAT的求解需要先创建一个 CpSolver
类,并将模型传入该类的 Solve
函数。模型求解如下:
solver = cp_model.CpSolver()
status = solver.Solve(model=model)
模型求解之后,可以通过 solver.Value(var)
获取变量 var
的求解结果,通过 solver.objectiveValue()
获取目标函数值。
if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:
print(f'Maximum of objective function: {solver.ObjectiveValue()}\n')
print(f'x = {solver.Value(x)}')
print(f'y = {solver.Value(y)}')
print(f'z = {solver.Value(z)}')
else:
print('No solution found.')
输出结果如下:
Maximum of objective function: 5.0
x = 1
y = 2
z = 2
除此之外,可以通过 print(solver.ResponseStats())
将求解结果全打印出来(如下)。也可以通过仅通过 print(solver.param)
来打印指定信息,例如 print(solver.BestObjectiveBound())
。
CpSolverResponse summary:
status: OPTIMAL
objective: 5
best_bound: 5
integers: 1
booleans: 0
conflicts: 0
branches: 0
propagations: 0
integer_propagations: 1
restarts: 0
lp_iterations: 0
walltime: 0.010765
usertime: 0.0107651
deterministic_time: 0
gap_integral: 0
solution_fingerprint: 0xbc76f3d3e780d9b7