幹貨 | 這裏有份數學規劃求解器SCIP超詳細的使用教程,請你收下
小夥伴們大家好呀!繼上次lp_solve規劃求解器的推文出來以後,大家都期待著更多求解器的具體介紹和用法。小編哪敢偷懶,這不,趕在考試周之際,又在忙裏偷閑中給大家送上一篇SCIP規劃求解的推文教程。快一起來看看吧。
Part1 慣例科普篇
What is SCIP?
官方的介紹:
SCIP is currently one of the fastest non-commercial solvers for mixed integer programming (MIP) and mixed integer nonlinear programming (MINLP). It is also a framework for constraint integer programming and branch-cut-and-price. It allows for total control of the solution process and the access of detailed information down to the guts of the solver.
SCIP is a framework for Constraint Integer Programming oriented towards the needs of mathematical programming experts who want to have total control of the solution process and access detailed information down to the guts of the solver. SCIP can also be used as a pure MIP and MINLP solver or as a framework for branch-cut-and-price.
SCIP is implemented as C callable library and provides C++ wrapper classes for user plugins. It can also be used as a standalone program to solve mixed integer programs given in various formats such as MPS, LP, flatzinc, CNF, OPB, WBO, PIP, etc. Furthermore, SCIP can directly read ZIMPL models.
有關SCIP概述及其算法的實現原理方法更多詳情,可以點擊下面鏈接下載相關文檔:
- Constraint Integer Programming: a New Approach to Integrate CP and MIP
(http://opus.kobv.de/zib/volltexte/2008/1081/pdf/ZR_08_01.pdf) - SCIP: Solving Constraint Integer Programs
(http://mpc.zib.de/index.php/MPC/article/view/4)
SCIP的更詳細描述:
-
Constraint Integer Programming
(http://opus4.kobv.de/opus4-zib/frontdoor/index/index/docId/1112)
有關凸與非凸MILPS的全局優化的非線性求解特征:
-
SCIP: Global Optimization of Mixed-Integer Nonlinear Programs in a Branch-and-Cut Framework
(http://dx.doi.org/10.1080/10556788.2017.1335312)
SCIP Optimization
SuiteSCIP優化套件是用於生成和求解混合整數非線性規劃模型、混合整數線性規劃模型和整數約束規劃模型的工具集。 它由以下部分組成:
- SCIP mixed integer (linear and nonlinear) programming solver and constraint programming framework
- SoPlex linear programming solver
- ZIMPL mathematical programming language
- UG parallel framework for mixed integer (linear and nonlinear) programs
- GCG generic branch-cut-and-price solver
用戶可以使用建模語言ZIMPL輕松生成線性,混合整數和混合整數二次約束的規劃模型。 得到的模型可以直接加載到SCIP中並求解。 在解決方案過程中,SCIP可以使用SoPlex作為底層LP求解器。
上面五個組件都可以獲得它們的源代碼,並且都是免費的。因此它們是用於學術研究和混合整數編程的理想工具。
可以點擊下面鏈接下載SCIP Optimization Suite:
(https://scip.zib.de/index.php#download)
目前最新版本是SCIP version 6.0.0。
支持以下平臺:
- Linux
- Mac
- Windows
- SunOS
- Android
SCIP的特點
對於SCIP,它主要有以下幾個優點:
- very fast standalone solver for linear programming (LP), mixed integer programming (MIP), and mixed integer nonlinear programming (MINLP)
- framework for branching, cutting plane separation, propagation, pricing, and Benders‘ decomposition,
- large C-API, C++ wrapper classes for user plugins
- interfaces to other applications and programming languages (contained in source code packages or available from http://github.com/SCIP-interfaces):
Python
Java
AMPL
GAMS
MATLAB
- open LP solver support:
CPLEX
Gurobi
XPress
Mosek
SoPlex
QSopt
CLP.
- highly flexible through many possible user plugins
Part2 基礎入門篇
SCIP-下載和安裝前面介紹了這麽多,終於要動手擼一擼代碼了。想必各位小夥伴也迫不及待了吧。不過這裏再強調兩句,SCIP和SCIP Optimization Suite的區別就是前者是一個工具,後者是一個工具集。後者包含了前者之外,還包含了其他的求解器。
下載:
前面已經給出了下載地址,大家根據自己的平臺下載相應的文件即可。小編系統平臺是Windows 10 64bit的。所以就下載了:
安裝的話,照舊×××。需要註意的是,這裏把這些勾選以下,免得後續出現麻煩:
關於SCIP的說明文檔,訪問(https://scip.zib.de/)定位到右上角Documentation,版本選6.0即可。
0) 好了現在興高采烈打開命令行,輸入SCIP:
納尼?劇本好像不是這麽寫的啊。
是什麽問題呢?(敲黑板),剛剛即使勾選了把SCIP Optimization Suite添加到系統路徑裏面,可能對某些情況並不會成功(可能是被殺毒軟件攔截了)。所以咱們還是要手動添加一下。
如下圖:右鍵此電腦-屬性。然後按下圖操作:
找到我們SCIPOptSuite 6.0.0的安裝路徑,把它復制下來:
然後添加到PATH變量裏面:
然後再回到命令行。(註意要重啟一下命令行)輸入SCIP:
大功告成。
SCIP-簡單上手那麽,怎麽用SCIP求解一個規劃問題呢?例如下面一個簡單的例子:
Max z = x1 + 2 x2 + 3 x3 + x4
Subject To
- x1 + x2 + x3 + 10 x4 <= 20
x1 - 3 x2 + x3 <= 30
x2 - 3.5 x4 = 0
0 <= x1 <= 40
2 <= x4 <= 3
SCIP支持以下格式的文件:
部分格式文件說明可以點擊下面的鏈接(個別需要×××):
- CNF - file format:
http://people.sc.fsu.edu/~jburkardt/data/cnf/cnf.html - FZN - file format:
http://www.g12.cs.mu.oz.au/minizinc/downloads/doc-1.5/flatzinc-spec.pdf - (R)LP - file formats:http://publib.boulder.ibm.com/infocenter/cosinfoc/v12r3/topic/ilog.odms.cplex.help/Content/Optimization/Documentation/Optimization_Studio/_pubskel/ps_reffileformatscplex2159.html
- MPS - file format:
http://en.wikipedia.org/wiki/MPS_%28format%29 - OPB/WBO - file formats:
http://www.cril.univ-artois.fr/PB12/format.pdf - OSiL format for MINLP:
http://www.coin-or.org/OS/OSiL.html - PIP - file format:
http://polip.zib.de/pipformat.php - ZPL - file format:
http://zimpl.zib.de/download/zimpl.pdf
在這裏我們選擇CPLEX lp files格式的文件作為演示。將上述模型改寫為CPLEX lp files格式便可以用SCIP讀取並且求解。例如我們在D:\scip目錄下建立一個simple.lp文件,輸入以下代碼:
Maximize
obj: x1 + 2 x2 + 3 x3 + x4
Subject To
c1: - x1 + x2 + x3 + 10 x4 <= 20
c2: x1 - 3 x2 + x3 <= 30
c3: x2 - 3.5 x4 = 0
Bounds
0 <= x1 <= 40
2 <= x4 <= 3
General
x4
End
保存。
在我們的命令行模式下,進入到D:\scip這個目錄。
然後輸入以下命令:
1) 首先進入scip:> scip
2) 然後讀取我們的模型文件:> read simple.lp
3) 求解我們的問題:> optimize
4) 輸出一大堆信息以後,問題已經求解完畢。我們把solution顯示出來:> display solution
OK,至此,問題已經求解完畢。
有關SCIP的更多使用,使用help命令可以查看詳細說明:
關於CPLEX lp files,可以訪問下面鏈接查看詳細說明: (http://lpsolve.sourceforge.net/5.5/CPLEX-format.htm)
Part3 實戰篇
python下使用SCIP
平臺還是Windows10 64位。
先用pip把SCIP的包給裝上:
pip install pyscipopt
然後記得把環境變量給配置好了。(不知道的同學會去看【SCIP-下載和安裝】PATH路徑的配置)。
1、進入Python,導入相應的模塊:
\>>?from pyscipopt import Model
2、創建一個實例模型.
\>>?model = Model("Example") # model name is optional
3、通過模型求解相關問題,舉一個栗子, e.g.:
\>>?x = model.addVar("x")
\>>?y = model.addVar("y", vtype="INTEGER")
\>>?model.setObjective(x + y)
\>>?model.addCons(2x - yy >= 0)
\>>?model.optimize()
更多詳細說明可以查看這個:
https://github.com/SCIP-Interfaces/PySCIPOpt
Java下使用SCIP
java下使用SCIP比較麻煩的是,需要自己編譯後才能調用。這裏簡要說明一下編譯過程(不想了解的可以跳到第4)步,編譯好的文件小編會分享給大家的。):
環境:Windows 10 64位、jdk 64位
註意路徑都不要有中文!!!註意路徑都不要有中文!!!
1) 小編在這裏使用的是Cmake+VS2017編譯(所以在此之前確保你安裝了Cmake和相關的C編譯器)。首先到
(https://github.com/SCIP-Interfaces/JSCIPOpt)
下載整個項目下來,解壓到某個文件夾,在命令行下進入該文件夾:
2) 進來以後,創建一個build目錄,以用來生成相關文件,然後進入build目錄:
進來以後,輸入cmake .. -G "Visual Studio 15 2017 Win64" 進行相關配置。註意你的編譯器,我這裏用的是vs2017所以是"Visual Studio 15 2017 Win64",其他編譯器設置成相應的名字,比如vs2015就是"Visual Studio 14 2015 Win64"等等。
3) 最後,輸入cmake --build . --config "Release" 進行編譯。
4) 在build\Release目錄下得到我們的成品,然後把jscip.dll文件拷貝到C:\Windows\System32,後續編程過程需要用到這個dll,以便編譯器找到它。:
至此,編譯已經完成。
如何在項目裏調用SCIP的接口呢?小編還是先新建一個工程testscip為大家講解:
1) 新建好一個java工程以後,右鍵項目,選擇Properties,和上次一樣,把我們編譯出來的scip.jar給導入到工程裏面:
2) 然後就可以開始寫代碼了,下面提供了一個example:
1package testscip;
2import jscip.*;
3
4
5public class testscipMain {
6
7 public static void main(String[] args) {
8 // TODO Auto-generated method stub
9 Scip scip = new Scip();
10 System.loadLibrary("jscip");
11
12 // set up data structures of SCIP
13 scip.create("LinearExample");
14
15 // create variables (also adds variables to SCIP)
16 Variable x = scip.createVar("x", 2.0, 3.0, 1.0, SCIP_Vartype.SCIP_VARTYPE_CONTINUOUS);
17 Variable y = scip.createVar("y", 0.0, scip.infinity(), -3.0, SCIP_Vartype.SCIP_VARTYPE_INTEGER);
18
19 // create a linear constraint
20 Variable[] vars = {x, y};
21 double[] vals = {1.0, 2.0};
22 Constraint lincons = scip.createConsLinear("lincons", vars, vals, -scip.infinity(), 10.0);
23
24 // add constraint to SCIP
25 scip.addCons(lincons);
26
27 // release constraint (if not needed anymore)
28 scip.releaseCons(lincons);
29
30 // set parameters
31 scip.setRealParam("limits/time", 100.0);
32 scip.setRealParam("limits/memory", 10000.0);
33 scip.setLongintParam("limits/totalnodes", 1000);
34
35 // solve problem
36 scip.solve();
37
38 // print all solutions
39 Solution[] allsols = scip.getSols();
40
41 for( int s = 0; allsols != null && s < allsols.length; ++s )
42 System.out.println("solution (x,y) = (" + scip.getSolVal(allsols[s], x) + ", " + scip.getSolVal(allsols[s], y) + ") with objective value " + scip.getSolOrigObj(allsols[s]));
43
44 // release variables (if not needed anymore)
45 scip.releaseVar(y);
46 scip.releaseVar(x);
47
48 // free SCIP
49 scip.free();
50
51 }
52
53}
輸出結果:
更多的example可以在這裏找到
(https://github.com/SCIP-Interfaces/JSCIPOpt/tree/master/examples)
小編編譯好的成品庫文件和dll可以在這裏下載
(https://pan.baidu.com/s/1w3Dd4lP8ypslFHC5wtvPGQ)
C/C++下使用SCIP
這官方的文檔給的是Linux環境的配置,小編在Windows下摸索了老半天,總算是把這程序跑起來了。天吶,這過程太艱難了。下面開始說重點啦。
1) 首先在這裏(https://github.com/SCIP-Interfaces/CSIP)把整個項目給download下來。解壓到某個位置。
2) 打開編譯器,小編這裏還是用VS2017作為演示,新建一個空項目。然後把include\csip.h、src\csip.c這兩個文件復制到我們的項目目錄:
把這兩個文件添加到項目文件裏面:
3) 編譯環境選擇64位,一定要選擇64位,一定要選擇64位,不然不會成功:
在項目屬性裏面:
包含目錄把之前安裝的SCIPOptSuite 6.0.0下的include目錄包含進去。
庫目錄把之前安裝的SCIPOptSuite 6.0.0下的lib目錄包含進去。
4) 然後,在鏈接器-輸入-附加依賴庫-把scip.lib添加進去:
最後,在csip.c開頭添加這句:
至此,已經配置完成了。另外,把include<csip.h> 改為 include"csip.h"。
下面進行代碼測試,下面的代碼實例了很多模型的求解過程:
找到之前在GitHub下載的CSIP項目的解壓文件,把test目錄的代碼文件復制到vs的項目目錄:
同樣,把這兩文件添加到源代碼裏面:
*test.c文件裏面,拉到最後,把這兩行註釋掉:*
編譯時提示除0錯誤,也改過來就行。然後就可以愉快跑起來啦。
不得不吐槽一下這說明文檔,寫得太模糊不清了,害的小編苦苦編譯調試了老半天,最後走投無路的時候發現是lib庫沒法生成,是版本問題(所以,敲黑板,一定要選64位的編譯模式啊。)。不過,也可能是小編太菜啦。然後嘛,畢竟人家是開源的項目,咱們也不能要求太高啦。
附:相關代碼文件下載請移步留言區。
Part4 小結
好啦,上面就是SCIP大體的使用教程了。總結起來無非就下面幾點:
- 使用SCIP自帶的求解器,在命令行模式下求解相應的模型文件。
- 寫程序進行建模,調用SCIP相關的API,進行求解。
可能還有很多遺漏的點沒有說,還請各位讀者見諒哈,各個方面的資料說明都在文章中給出了。相應的資源也在文章中給出了。最後,謝謝大家!
Part 5 獲取代碼
欲獲取代碼,請關註我們的微信公眾號【程序猿聲】,在後臺回復:SCIP。即可獲取。
推薦文章:10分鐘教你用Python做個打飛機小遊戲超詳細教程
推薦文章:10分鐘教你用python下載和拼接微信好友頭像圖片
幹貨 | 這裏有份數學規劃求解器SCIP超詳細的使用教程,請你收下