1. 程式人生 > >Optaplanner與Google OR-Tools的區別

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郵件列表,國內網路可能較難訪問,需自行解