Optaplanner與Google OR-Tools的區別

在規劃相關的項目工作中,近兩年我們的項目主要使用的是Optaplanner作爲規劃引擎,其核心也是一個的規劃求解器(Solver)。但作爲另一個著名開源求解器Google OR-Tools(下稱OR-Tools)也日漸流行。且因Google自帶流量的支持,OR-Tools有更多專門研究運籌的學者使用和研究。而Optaplanner則更偏向工程實踐上的應用。本文就二者在技術特性、使用方法與場景等方面,列出若干差異。希望爲需要使用開源求解器進行項目工作的同行提供初步入門參考與選擇。

簡介

Optaplanner

Optaplanner目前是Apache基金會的一款開源軟件,JBOSS社區,基於Apache開源軟件協議,該協議對商用友好,因此可以自由地將該技術的部門或全部應用於商用軟件項目中。該項目目前由受僱於Redhat的團隊在維護.其創業人Geoffrey De Smit先生作爲該項目的Leader. 其實Optaplanner已發展了十餘年,最初是由Geoffrey在參加運籌規劃大賽中,針對各種競賽題目 開發的一個求解器。後來將它貢獻給開源社區,並作爲開源項目一直維護至今,其版本發佈仍十分高效,除進行一些對用戶透明不可視的算法與架構優化外,不時還有極具價值的新功能與新特徵發佈,如7.09版本發佈的多線程支持,本人認爲是極具里程碑意義的新特徵,可以令對運算資源敏感的求解過程,最大程度上提高對CPU的利用率。

Google OR-Tools

Google OR-Tools, 顧名思義是由Google提代的一套運籌規劃的運算工具,它針對不同的規劃場景,提供了不同的求解器(以組件方式提供)。OR-Tools同樣是基於Apache開源軟件協議,它是由受僱於Google的Laurent Perron博士帶領團隊維護。OR-Tools的討論區討論相當熱烈,主要原因是它的使用方法與傳統商用的求解器(如Cplex, Gurobi等)相當類似,因此相當一些運籌學的學者、學生對該軟件比較感興趣。

下面,從使用方法,結構構成等方面,分別對兩個規劃引擎進行分別討論。

開發技術與使用方式的區別

Optaplanner的技術特性

Optaplanner是使用Java語言開發,是基於純Java技術。因此,使用它的時候也只需要使用Java語言本身的特性,即可滿足幾乎所有基本的建模、開發及求解過程;而無需使用其它第三方的技術或框架。當然當你在實際的工程實踐中,還是需要依賴強大的Java生態圈,才能讓項目事半功倍。例如通過第三方組件實現日誌,數據的持久化、Web服務等。

Optaplanner的評分邏輯,需要使用Drools作爲規則描述語言,實現約束的評分。事實上Optaplanner同時支持Java語言實現約束評分的,即Easy Java Score Calculation與Incremental Java Score Calculation,使用這兩種評分方式,評分邏輯可直接使用Java語言實現。僅需通過POJO即可對業務實體進行建模,通過Java程序代碼即可描述業務約束。Optaplanner的核心程序以Jar包方式提供;當然你也可以獲取它的源代碼,從源代碼級把它的核心集成到你自己的系統中去。但作爲商業軟件項目,此方法並非最佳實踐,直接使用官方發佈的Jar 包即可。Optaplanner不支持MiniZinc作爲建模語言,OR-Tools則支持該種約束建模語言。在對MiniZinc的支持方面,可能各位ORer感覺有些許遺憾。

與既有系統集成成

從另一個角度來看,純Java技術實現的Optaplanner,對使用環境起到簡化作用的同時,又會形成了一種限制。例如對於一些非Java技術開發的系統(例如一些舊系統),要與Optaplanner集成到同一個程序中,則無法實現嘗試結合。對於這種情況,解決辦法是將Optaplanner獨立成一個Web服務,以WebAPI 的方式對外提供服務。事實上這種系統結構即使是在整個項目都是用Java開發,也是直得推薦的方法。因爲規劃服務程序在運行的時候,主要佔用的資源是CPU的運算資料,在一些規模大,規則複雜的規劃程序中,對CPU資源的佔用更明顯。從另一方面來看,在某些複雜的規劃場景中,CPU的性能,直接決定了在固定時間內,找到相對最優方案的質量。因此,將規劃服務獨立成一個服務,使用獨立的服務器資源作爲運行環境,爲規劃引擎提供充足的CPU資源;同時也消除了規劃運算對系統其它部分的影響。

Google OR-Tools的技術特性

OR-Tools內核是使用C++開發,因此,其兼任性相對Optapalnner來說好很多。目前Google OR-Tools支持C++, C#, Java和Python四種語言接口。即他具有動態鏈接庫存(DLL), Jar包和Python包三種提供提供形式。當然因爲它的原始形式是dll文件,用過Java對它進行調用的時候,就需要通過JNI對它進行裝載,下文的示例中會展示。因爲OR-Tools提供豐富的兼容形式,因此,與不同系統集成較容易。可直接將它的源代碼或DLL嵌入到自己的系統中去。當然,如果使用源代碼的方式集成,只能嵌入到C++開發的系統中。

建模語言方面,OR-Tools同時支持使用程序語言(Python, C++, Java, C#)描述模型,如上文提到,它同時也支持MiniZinc作爲約束建模語言。各位科班出身的ORer應該對此較有親切感。也因此在OR-Tools的討論區,其中提出討論的問題,除了工程實踐的問題,還有非常多是運籌學方面較專業的理論問題。這也許反映了世界各地存在着大量的ORer正在使用OR-Tools作爲他們的研究工具。

與既然有系統的體成

在系統集成方面,因爲OR-Tools接口相對開放,集成的問題則基本上不存在任何問題。其核心(規劃求解器)可以作爲系統的一個組件存在於任何系統中;也可以將其封裝成一個服務對外提供服務。

建模方式的區別

在建模方式方面,兩者都可以使用程序設計語言進行規則、約束描述。同時也可使用使用其它專用的約束或建模語言;Optaplanner支持Drools, OR-Tools支持MiniZinc。但兩者面對的場景,或說偏向解決的具體問題,還是有區別的。

Optaplanner更偏向於面向對象

使用Optaplanner進行系統開發的時候(例如開發APS系統),如其它商用軟件一樣,先對業務進行分析,設計出具體的業務實體,識別出需要規則的實體和因素(字段),提練出業務規則,歸納出哪些規則是硬約束,哪些是可以優化的軟約束。然後根據Optaplanner的固定對象結構模式,建立Planning Entity, Planning Variable,Problem Fact和Solution等類;並配置好求解器的各種參數。整個核心系統的設計就差不多完成了。

Google OR-Tools偏向於傳統的數據建模

OR-Tools除了同樣需要進行業務分析與設計外,還需要加多一步工作 - 數學建模。因爲OR-Tools求解規劃問題時,輸出的必須是一個完整的數學模型。也就是在使用OR-Tools進行系統開發時,需要先進行業務分析設計,獲得各種業務要素和約束後,需要對這些業務要素進行數學建模,並將這個模型以程序語言(Python, C++, Java, C#)或MiniZinc進行模型描述。然後才能啓動規劃求解器進行尋找優勢方案。事實現Optaplanner在使用其求解器進行規劃求解時,也需要有相應的數學模型的,只不過它可以在求解之前,把用Java對象表示的業務模型,轉換成數學模型;而這個步驟對使用都來說是透明的,因此無需關心。

使用場景的區別

基於上一節中兩者建模方式上的差別,對於偏向於理論研究、學習的學者來說,OR-Tools更接近於他們日常接觸的各類規模模型,與CPLEX和Gurobi等知名商用(有免費的學術用途授權)求解器的應用方法與設計思想均較接近。因此,對於一些考研類的應用場景,OR-Tools來得更直接。

而Optaplanner則更趨向解決具體的業務問題,從期誕生的背景可以得知,它主就是爲解決具體問題而生的。關於 Optaplanner的來歷,可以參考其作者Geoffrey的一篇博文《A decade of OptaPlanner》。儘管Optaplanner與OR-Tools其核心是相當接近的,都是通過各種啓發式算法,對NP-Hard問題尋找相對最優解。但Optaplanner考慮到非運籌專業人員的數學功底,對問題多做了一層封裝,將程序中描述業務問題的各種對象,轉換成相應的規劃模型,再進行規劃求解。從而在商用軟件開發環境中,普通的程序設計人員,只需要關注具體的業務細則,根據Optaplanner提供的模式,建立合理的對象模型,來反映業務模型,確保這些業務模型能準確地反映業務需求即可。而無需再將這些業務模型轉換成可運籌學上數學規劃所需的數學規劃模型。從而大大降低了規劃程序的開發難度。

從規劃到AI

目前兩個引擎都號稱自己屬於AI約束求解器,OR-Tools被納入作爲Google AI的其中一個產品。也難慘,畢竟這兩個引擎的規劃求解器都是基於啓發工算法,確實有對於NP-Hard問題,啓發式算法是目前較常用的算法,而這些算法對數據的各要素的具體分佈情況依賴較大。一定程度上體現了“智能”的感覺。不過我更覺得這是爲了蹭近年AI的火,覺得沒必要呀,雖然AI的核心算法追溯回去與運籌規劃是同源的。但運籌畢竟已經是一個很成熟獨立的分支了。

Google OR-Tools最基礎入門

以下代碼是OR-Tools的一個最基本的入門示例,它解決的是《Excel與Google Sheets中實現線性規劃求解》一文中的生產資源優化問題。讀者可以結合這篇文章中相關的模型,來對照這些代碼進行理解,從中體OR-Tools在進行規劃求解時所需的規劃模型的建立方法。

數學模型

import com.google.ortools.linearsolver.MPConstraint;
import com.google.ortools.linearsolver.MPObjective;
import com.google.ortools.linearsolver.MPSolver;
import com.google.ortools.linearsolver.MPVariable;

public class HelloOR {
        // 通過JNI調用OR-Tools包
	static { System.loadLibrary("resources/jniortools"); }

         // 創建求解器對象
	 private static MPSolver createSolver (String solverType) {
	    return new MPSolver("my_program", MPSolver.OptimizationProblemType.valueOf(solverType));
	 }

          // 程序入口,創建一個線性規劃求解器,並求解規模模型。
          public static void main(String[] args) throws Exception {
	    solverTest("GLOP_LINEAR_PROGRAMMING");
	  }

	  private static void solverTest(String solverType) {
	    MPSolver solver = createSolver(solverType);
	    // 創建決策變量,Optaplanner中稱爲Planning Variable, 規劃變量.
	    double infinity = MPSolver.infinity();
	    MPVariable x = solver.makeIntVar(0.0, infinity, "x");
	    MPVariable y = solver.makeIntVar(0.0, infinity, "y");
	    
	    // 創建約束
	    //資源1限制: 5x + 3y <= 280
	    MPConstraint c1 = solver.makeConstraint(-infinity, 280);
	    c1.setCoefficient(x, 5);
	    c1.setCoefficient(y, 3);
	    
	    //資源2限制: 4x + 8y <= 580
	    MPConstraint c2 = solver.makeConstraint(-infinity, 580);
	    c2.setCoefficient(x, 4);
	    c2.setCoefficient(y, 8);
	    
	    //資源3限制: 3x + 5y <= 360
	    MPConstraint c3 = solver.makeConstraint(-infinity, 360);
	    c3.setCoefficient(x, 3);
	    c3.setCoefficient(y, 5);
	    
	    // 創建目標函數,求20*x + 25*y 的最大值.
	    MPObjective objective = solver.objective();
	    objective.setCoefficient(x, 20);
	    objective.setCoefficient(y, 25);
	    objective.setMaximization();
	    
	    // 調用求解器求解模型,並輸出結果.
	    solver.solve();
	    System.out.println("Solution:");
	    System.out.println("x = " + x.solutionValue());
	    System.out.println("y = " + y.solutionValue());
	    System.out.println("20x + 25y = " + (20 * x.solutionValue() + 25 * y.solutionValue()));
	  }

	 
}

可以看到,使用OR-Tools裏,需要先建立Solver對,並將模型中的各不等式以係數方式體現到程序中,最後求解得出結果。因爲這是一個線性規劃問題,因此代碼中創建的是一個線性求解器(以GLOP_LINEAR_PROGRAMMING參數表示)。儘管都是規劃問題,但針對不同同的類型,OR-Tools提供不同的Solver解,例如線性規劃問題,TSP問題等,有專用的Solver對象解決。

輸出結果爲:

 

關於Optaplanner的使用方法,則可以《Optaplanner規劃引擎的工作原理及簡單示例(2)》。

  • End.

如需瞭解更多關於Optaplanner的應用,請發電郵致:[email protected]

或到討論組發表你的意見:https://groups.google.com/forum/#!forum/optaplanner-cn​groups.google.com

若有需要可添加本人微信(13631823503)或QQ(12977379)實時溝通,但因本人日常工作繁忙,通過微信,QQ等工具可能無法深入溝通,較複雜的問題,建議以郵件或討論組方式提出。(討論組屬於google郵件列表,國內網絡可能較難訪問,需自行解決)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章