最近抽空研究了谷歌运筹优化库ortools底层封装的函数,发现其自带的许多函数能解决很多复杂的非线性规划问题。
例如:以下是一个目标函数为非线性表达式(包含x与y的乘积)的例子。
直接使用线性规划模型建模,一般是无法求解的。在ortools中一堆非线性函数,可以在建模过程中应用,利用好这些非线性函数可以处理绝大部分问题。
在本例中使用AddMultiplicationEquality函数,可以生成一个新的乘积变量,再根据这个变量编写约束或者目标函数就可以对模型求解。
完整代码
from ortools.sat.python import cp_model
model = cp_model.CpModel()
# x,y,z为0到100之间的整数
x = model.NewIntVar(0, 100, 'x')
y = model.NewIntVar(0, 100, 'y')
z= model.NewIntVar(0, 100, 'z')
## 约束:
### 2x+3y<100
### x*y-z>10
mult=model.NewIntVar(0, 10000, 'mm')
model.AddMultiplicationEquality(mult, x, y)
model.Add(2*x+3*y<100)
model.Add(mult-z>10)
#目标函数
model.Minimize(mult+2*x+6*z)
# 定义求解器
solver = cp_model.CpSolver()
# 求解问题
status = solver.Solve(model)
# 输出结果
if status == cp_model.OPTIMAL:
print('x =', solver.Value(x))
print('y =', solver.Value(y))
print('z =', solver.Value(z))
print('mult =', solver.Value(mult))
print('obj =', solver.ObjectiveValue())
else:
print('No solution found.')
求解结果输出。
非线性函数介绍
ortools包含很多非线性处理的函数。
- AddAbsEquality():取绝对值
- AddModuloEquality():取余运算
- AddDivisionEquality():取整运算
- AddMinEquality():取最小值运算
- AddMaxEquality():取大值运算
- AddMultiplicationEquality():乘积运算。
- ortools还有很多非线性处理的函数,并未一一列举。感兴趣的读者可以研读底层函数包,进一步深挖底层函数。
总结
ortools是开源免费求解器中比较好的产品之一,如果没法使用商业的gurobi、cplex等求解器,使用ortools在处理中小型问题建模求解是不错的选择。