背景
- ortools在求解MIP问题时默认使用CBC求解器,但支持调用第三方求解器:GLPK、Gurobi、CPLE和SCIP,调用第三方求解器时需要单独安装,同时ortools源码编译。
- 很多人遇到CBC求解器不能求得最优解的情况,实际上默认求解器是基于启发式求解的,如果仍然使用ortools进行建模,需要调用第三方求解器。
- 网上几乎没有介绍如何利用ortools调用第三方求解器,各种第三方求解器安装方法比较繁琐,按照官方介绍的步骤踩了超级多的坑才形成本文(按照我的步骤,绝对没问题)。
- 即使默认求解器能够求得最优解,你也可以尝试第三方求解器(快的飞起)。
GLPK求解器
- GLPK (GNU Linear Programming Kit) 是 GNU 项目开发并维护的一个线性规划工具包,用于建立大规模线性规划LP和混合型整数规划MIP问题,并对模型进行最优化求解。由于是GNU下的项目,因此没有商业非商业的版本限制,可以自由使用。
- 链接:http://ftp.gnu.org/gnu/glpk/,下载最新版本glpk-4.60.tar.gz
- tar -xzvf glpk-4.60.tar.gz
- cd glpk-4.60
- configure --prefix=你的路径/glpk (记住路径很重要,是安装的第一层路径,默认在usr/local,求解器glpsol在bin目录下)
- make
- make install
CPLEX求解器
- CPLEX 是 IBM 开发的一个商用线性规划求解器。该软件具有执行速度快、其自带的语言简单易懂、并且与众多优化软件及语言兼容(与C++,JAVA,EXCEL,Matlab,Python等都有接口)。
- 支持求解求解线性规划(LP)、二次规划(QP)、带约束的二次规划(QCQP)、二阶锥规划(SOCP)等四类基本问题,以及相应的混合整数规划(MIP)问题。
- 直接通过pip install cplex会发现使用的是社区版,运行规模较小(好像最大1000变量和1000约束)。
- 最好在官网下载免费版,网址:https://www.ibm.com/analytics/cplex-optimizer
- cd 你的路径/cplex(是第一层路径)
- python setup.py install --home 你的路径/cplex
SCIP求解器(推荐)
- 支持求解混合整数(非线性)规划、Constraint integer programming。
- 下载scipoptsuite压缩包:https://scip.zib.de/index.php#download
- tar xvf scipoptsuite-6.0.2.tgz
- cd scipoptsuite-6.0.2
- 深坑(花了半天时间解决):目前测试7.0.0版本,在编译时会报错,所以一定要选择6.0版本,不清楚scip什么时候会修复这个问题:
- 执行make,可能会报错:
- 解决办法,执行(深坑):brew install boost
- 然后执行:make
- make install INSTALLDIR=你的路径/scip(第一层安装路径)
- make test(测试是否安装成功)
ortools安装(可调用第三方求解器)
- 不使用第三方求解器的情况下,可直接pip install ortools,默认安装解决MIP问题只有CBC求解器,基于启发式,经常不能求得最优解。
- 若使用第三方求解器,需要从ortools源码编译:
- git clone https://github.com/google/or-tools
Copy - 深坑中的深坑:直接clone默认stable分支,分支中ortools/ortools/linear_solver/http://scip_interface.cc文件存在错误,需要注释掉scip_callbace的引用(不清楚作者为什么没有发现,还是stble版本):
- 或者直接指定master版本(则无需更改):git clone -b master https://github.com/google/or-tools
- make third_party
- 此时需要将第三方求解器的路径添加到Makefile.local文件中,每加一个求解器就要加一个路径,如下图GLPK求解器所示(注意变量名称和路径层级),如:UNIX_SCIP_DIR、UNIX_GLPK_DIR、UNIX_CPLEX_DIR
- make python
- make test_python(测试)
- make clean
- make all
- make install_python
- 愉快的玩耍,参数可选:pywraplp.Solver.GLPK_MIXED_INTEGER_PROGRAMMING、pywraplp.Solver.SCIP_MIXED_INTEGER_PROGRAMMING、pywraplp.Solver.CPLEX_MIXED_INTEGER_PROGRAMMING
实例
from ortools.linear_solver import pywraplp
from ortools.algorithms import pywrapknapsack_solver
def main():
# Create the mip solver with the CBC backend.
solver = pywraplp.Solver('simple_mip_program',
pywraplp.Solver.SCIP_MIXED_INTEGER_PROGRAMMING)
infinity = solver.infinity()
x = solver.IntVar(0.0, infinity, 'x')
y = solver.IntVar(0.0, infinity, 'y')
print('Number of variables =', solver.NumVariables())
solver.Add(x + 7 * y <= 17.5)
solver.Add(x <= 3.5)
print('Number of constraints =', solver.NumConstraints())
solver.Maximize(x + 10 * y)
status = solver.Solve()
if status == pywraplp.Solver.OPTIMAL:
print('Solution:')
print('Objective value =', solver.Objective().Value())
print('x =', x.solution_value())
print('y =', y.solution_value())
else:
print('The problem does not have an optimal solution.')
if __name__ == '__main__':
main()