简介
SCIP是目前最快的混合整数线性规划(mixed integer programming,MIP)和混合整数非线性规划(mixed integer nonlinear programing, MINLP)的求解器之一。到本文记录时,SCIP的版本已经到了8.0.4。
SCIP可以使用不同的编程语言来访问,对于Python有官方提供的PySCIPOpt, 使用conda可安装:
conda install --channel conda-forge pyscipopt
安装完后,使用PySCIPOpt的readme提供的例子,测试是否可以正常求解
from pyscipopt import Model
# 定义求解器实例,模型名是可选项
model = Model("Example")
# 定义变量名,可以指定类型
x = model.addVar("x")
y = model.addVar("y", vtype="INTEGER")
# 设置求解目标
model.setObjective(x + y)
# 添加约束
model.addCons(2*x - y*y >= 0)
# 优化目标
model.optimize()
# 返回最优解
sol = model.getBestSol()
print("x: {}".format(sol[x]))
print("y: {}".format(sol[y]))
非线性目标要做转换
SCIP不支持直接定义非线性目标,需要将非线性目标转化成线性目标,比如下面的例子,运行会报错:ValueError: Nonlinear objective functions are not supported!
。 更多关于这个错误的讨论可见github issue
from pyscipopt import Model
model = Model("Test") # model name is optional
x = model.addVar("x")
y = model.addVar("y")
# 直接定义的非线性目标会报错
model.setObjective((x - 3)**2 + (y - 4)**2)
model.addCons(x**2 + y**2 >= 10)
model.optimize()
sol = model.getBestSol()
print("x: {}".format(sol[x]))
print("y: {}".format(sol[y]))
对于上面的代码例子,可以将目标作一个转换,如下代码所示
from pyscipopt import Model
model = Model("Test") # model name is optional
x = model.addVar("x")
y = model.addVar("y")
z = model.addVar("z")
model.setObjective(z)
model.addCons(x**2 + y**2 >= 10)
model.addCons((x - 3)**2 + (y - 4)**2<=z)
model.optimize()
sol = model.getBestSol()
print("x: {}".format(sol[x]))
print("y: {}".format(sol[y]))
#虽然上面的代码里都是直接表达式,但是目标也可以定义为python函数,比如上面的目标可以定义函数来表示
def square(x, a):
return (x - a)**2
model = Model("Test") # model name is optional
x = model.addVar("x")
y = model.addVar("y")
z = model.addVar("z")
model.setObjective(z)
model.addCons(x**2 + y**2 >= 10)
model.addCons(square(x, 3) + square(y, 4)<=z)
model.optimize()
sol = model.getBestSol()
print("x: {}".format(sol[x]))
print("y: {}".format(sol[y]))