什么是建模語言
建模語言是一種描述信息或模型的編程語言,在運籌優化領域,一般是指代數建模語言。
比如要寫一個線性規劃問題的建模和求解,可以采用C、Python、Java等通用編程語言來實現計算機編程(碼代碼),也可以換采用建模語言。
本文將以阿里達摩院研發的MindOpt建模語言(MindOpt Algebra Programming Language, MindOptAPL,簡稱為MAPL)來講解。MAPL是一種高效且通用的代數建模語言,當前主要用于數學規劃問題的建模,并支持調用多種求解器求解。
代數建模語言工作原理
在數學規劃領域,遇到一個實際問題時候,我們需要數學建模成優化問題模型、然后編程、然后計算優化結果,得到這個實際問題的解決方案。
在這個編程過程中,可以根據選用的計算工具——優化求解器提供的通用編程語言的API來編寫代碼,也可以采用建模語言來編寫代碼。如下示例,就是一個利用MAPL建模語言來進行一個優化問題碼的代碼。
- 左邊是數學模型,三要素:兩個變量xa和xb,目標函數是最大化一個公式,約束是最下面兩行,限定取值關系。
- 中間是用MAPL建模語言編的代碼。可以看到前面4行就表達清楚了左邊的數學公式。最后“option solver mindopt;”是設置計算這個問題的求解器為mindopt求解器,“solve;”是執行求解。
- 右邊就是求解器的計算結果,xa = 3,xb=5,此時目標函數最大,是1050。
為什么要用建模語言
語法更簡單(代碼對比)
從上面我們可以看到建模語言可以方便地進行數學建模和求解的代碼。這里我們對比一下建模語言和通用的編程語言,來看看用建模語言優勢。
以下面這個問題為示例:
| 線性規劃模型:
max x0 + 2 * x1 + 3 * x2 + x3
s.t. (-1) * x0 + x1 + 3 * x2 + 10 * x3 <= 20
x0 - 3 * x1 + x2 = 30
x1 - 3.5 * x3 = 0
0 ≤ x0 ≤ 40
0 ≤ x1
0 ≤ x2
2 ≤ x3 ≤ 3
我們使用 MindOpt APL 建模語言 和 MindOpt 求解器的 Python APIs,分別對上面的線性規劃模型建模,并求解模型。
MAPL代碼:
clear model; #清除model,多次run的時候使用
option modelname test; #運行完代碼之后會自動生成.nl和.sol文件 model是存放的地址,test是文件名#--------------------------
# twoTask.mapl
var x0 >= 0; # 聲明決策變量xa |
var x1 >= 0;
var x2 >= 0;
var x3 >= 2;
maximize Reward: x0 + 2 * x1 + 3 * x2 + x3; # 聲明目標函數
subto c1: (-1) * x0 + x1 + 3 * x2 + 10 * x3 <= 20; # 聲明約束
subto c2: x0 - 3 * x1 + x2 <= 30;
subto c3: x1 - 3.5 * x3 == 0;
subto c4: x0 <= 40;
subto c5: x3 <= 3;
#--------------------------option solver mindopt; # (可選)指定求解用的求解器,默認是MindOpt
solve; # 求解print "-----------------Display---------------";
display; # 展示結果
print "目標函數值 = ",x0 + 2 * x1 + 3 * x2 + x3;
Python代碼:
from mindoptpy import *if __name__ == "__main__":# Step 1. Create model.model = Model("test")try:# Step 2. Input model.# Change to minimization problem.model.ModelSense = MDO.MAXIMIZE# Add variables.x = []x.append(model.addVar(0.0, 40.0, 1.0, 'C', "x0"))x.append(model.addVar(0.0, float('inf'), 2.0, 'C', "x1"))x.append(model.addVar(0.0, float('inf'), 3.0, 'C', "x2"))x.append(model.addVar(2.0, 3.0, 1.0, 'C', "x3"))# Add constraints.model.addConstr(- 1.0 * x[0] + 1.0 * x[1] + 3.0 * x[2] + 10.0 * x[3] <= 20, "c1")model.addConstr(1.0 * x[0] - 3.0 * x[1] + x[2] <= 30, "c2")model.addConstr(1.0 * x[1] - 3.5 * x[3] == 0, "c3")# Step 3. Solve the problem and populate optimization result.model.optimize()if model.status == MDO.OPTIMAL:print(f"Optimal objective value is: {model.objval}")print("Decision variables: ")for v in x:print(f"x[{v.VarName}] = {v.X}")else:print("No feasible solution.")except MindoptError as e:print("Received Mindopt exception.")print(" - Code : {}".format(e.errno))print(" - Reason : {}".format(e.message))except Exception as e:print("Received other exception.")print(" - Reason : {}".format(e))finally:# Step 4. Free the model.model.dispose()
從上面的例子可以看到,MAPL建模語言比較簡潔,沒有Python運行這么多復雜的創建、添加、異常捕捉和釋放的過程,就聚焦在編個模型去求解計算,更易于理解和添加。上面的例子還只是線性規劃,對于非線性規劃的問題,Python的API會更復雜。而采用MAPL建模語言只需要表達清楚數學公式,對于調試模型修改更方便。
支持多種求解器,換求解器的時候不用重復編程
很多人選擇建模語言,最大的原因是希望切換求解器方案。因為不同品牌的求解器的求解能力不一樣,遇到一個問題數學模型調整了一行公式,可能之前選擇的求解器就不支持了,需要更換求解器。
此時如果選擇用各家求解器的API來編程,換一個求解器,就需要重新學習對應的API,重新碼代碼,維護起來困難。雖然業界也有通用的 .mps 和 .nl 的優化問題數據格式,但是熟悉不同求解器的調用數據計算的方法也很耗時,或者裝對應的軟件也很麻煩。這個時候,建模語言的優勢就很大。
比如下面是MAPL代碼中,只需要換一行,就能換求解器進行計算:
option solver highs; # 更換求解器
更多MAPL支持的求解器,可以參考上一個博客MindOpt APL,可以支持調用幾十種求解器的建模語言
建模語言也支持通用編程語言的API,如Python
有很多同學喜歡Python語言,更希望用Python編程。MAPL建模語言支持Python來調用,import maplpy后就用Python的方式來編代碼,能繼續享受一行代碼換求解器的優良屬性。可一看廣告流量分配:曝光和轉化均衡案例中的代碼對比。
常見的建模語言
市面上的建模語言有很多個,需要看各家求解器支持的建模語言,比如MindOpt求解器支持如下4種建模語言:MAPL(MindOpt APL)、AMPL、Pyomo、PuLP。
其中MindOpt APL(MAPL)就是阿里達摩院自研的建模語言,是目前中國唯一一款代數建模語言。其他建模語言的描述大家可以點擊上面的鏈接查看:https://opt.aliyun.com/platform/docs/htmldoc/solver
MAPL的優點
MAPL國內第一款擁有自主知識產權,完全自研的國產建模語言,提供了豐富文檔學習以及案例參考。并且在電力SCUC等領域問題上建模性能優秀,對標或超越已有產品。對比AMPL等建模語言,部分語法上更靈活簡單,后續也會支持向量化建模等特色能力,提升建模易用性等。
靈活性:
MAPL具有非常高的靈活性,可以用來建模和求解各種類型的優化問題,包括線性規劃、整數規劃、非線性規劃等。它支持多種數學表達式和運算符,可以方便地表示復雜的數學關系和約束條件。如下是它支持數值計算。
易用性
MAPL建模語言采用了類似于自然語言的語法和結構,使得用戶可以很容易地理解和編寫優化模型。并且支持讀寫csv文件,使得數據的讀取和寫入變得容易,數據儲存也很方便。
如下將結果print輸出為csv表格:
更多選擇
MAPL與MindOpt Studio平臺集成,可以在線上環境使用,無需下載,并且支持調用多種求解器,可直接對比結果。還支持將輸出mps文件,可以在不同的計算環境和操作系統之間進行導入和導出。