做者|Antoine Champion 編譯|VK 來源|Towards Data Sciencepython
機器學習和深度學習一直是業界的熱門話題。品牌領先於功能,致使深度學習在許多人工智能應用中被過分使用。算法
這篇文章將提供對約束求解的快速理解,這是一個強大但未被充分利用的方法,能夠解決人工智能和其餘計算機科學領域的大量問題,例如物流和調度時間推理和圖形問題。編程
讓咱們來考慮一個事實性的和高度話題性的問題。網絡
病人人數正在上升。醫院必須迅速組織起來治療病人。架構
世界上須要一種算法,在疾病嚴重程度、患者年齡和位置、醫院容量和設備等多個標準下,將感染者和醫院匹配起來。app
許多人會說,神經網絡將是最適合它的:它能夠有不一樣的配置,普遍的參數範圍,能夠根據須要減小到一個獨特的解決方案。框架
然而,也有一些不利因素會破壞這個方案:機器學習
模型須要訓練,所以須要之前案例的歷史數據,函數
清理和整合數據集會浪費不少時間,學習
各類體系結構都須要經過冗長的訓練而且要進行測試。
另外一方面,若是用一個布爾可知足性問題來描述,在不肯定多項式時間(NP徹底問題)中仍然給出次優解,而且不須要任何歷史數據的狀況下,不會有上述任何缺點。
這篇文章幫助你快速一覽CSPs。理論和問題的表述將被忽略。有關更嚴格的方法,請參考論文,論文在文章的末尾
這篇文章將介紹約束編程,旨在解決這個案例。上面那張圖說明了咱們算法的輸出,應該該算法將感染者與醫院匹配。現有幾個框架用於約束求解。Google Optimization Tools(又稱Tools)是一個用於解決組合優化問題的開源軟件套件。咱們的問題將使用Python中的這個框架進行建模。
from ortools.sat.python import cp_model
colab:https://colab.research.google.com/drive/1vFkt5yIQtyelqvCh2TsJ9UDeM5miXqui
如今,讓咱們將問題簡化爲4個參數(1):
感染者所在地
感染者的嚴重程度
醫院位置
每家醫院的牀位數
讓咱們用python定義這些參數:
# 醫院數量 n_hospitals = 3 # 感染者人數 n_patients = 200 # 每家醫院的牀位數 n_beds_in_hospitals = [30,50,20] # 病人位置,tuple (x,y) patients_loc = [(randint(0, 100), randint(0, 100)) for _ in range(n_patients)] # 醫院位置,tuple (x,y) hospitals_loc = [(randint(0, 100), randint(0, 100)) for _ in range(n_hospitals)] # 病人嚴重等級 1~5 patients_severity = [randint(1, 5) for _ in range(n_patients)]
約束知足問題由一組變量組成,這些變量必須以知足一組約束。
令I爲醫院的集合
令$J_i$爲醫院i的牀位集合
令$K$爲病人集合
定義變量的索引族:
若是在醫院i中,牀j由病人k取走,則$x_{ijk} = 1$。爲了將醫院的每一張牀與一個病人聯繫起來,咱們的目標是找到一組知足全部約束條件的變量。
咱們能夠將這些變量添加到模型中:
model = cp_model.CpModel() x = {} for i in range(n_hospitals): for j in range(n_beds_in_hospitals[i]): for k in range(n_patients): x[(i,j,k)] = model.NewBoolVar("x(%d,%d,%d)" % (i,j,k))
硬約束定義了模型的目標。它們是必不可少的,若是它們得不到解決,就沒法解決問題:
讓咱們關注第一個硬約束。對於每家醫院的每一張牀,我:
要麼有一個惟一的病人k,
要麼牀是空的。
所以,能夠用如下方式表示:
咱們的求解器是一個組合優化求解器,它只能處理整數約束。所以,必須轉化爲一個整數方程:
這個不等式能夠加到咱們的模型中。
# 每張牀最多隻能住一我的 for i in range(n_hospitals): for j in range(n_beds_in_hospitals[i]): model.Add(sum(x[(i,j,k)] for k in range(n_patients)) <= 1)
接下來,第二個硬約束:對於每一個患者k:
同理,能夠轉化爲一個整數不等式:
最後,能夠將此約束添加到模型中。
# 每一個人最多隻能睡一張牀 for k in range(n_patients): inner_sum = [] for i in range(n_hospitals): inner_sum.append(sum(x[(i,j,k)] for j in range(n_beds_in_hospitals[i]))) model.Add(sum(inner_sum) <= 1)
接下來是軟約束。這些都是很是須要的:咱們的解決方案必須儘量知足它們,但它們不是找到解決方案的必要條件:
每一個病人都應該躺在牀上
每一個人都應該由最近的醫院處理
病牀不足時,應先處理病情嚴重的病人
當硬約束被建模爲等式或不等式時,軟約束是最小化或最大化的表達式。
設Ω爲知足硬約束的全部解的集合。
每個病人都應該被安排在一張牀上,這意味着最大限度地增長被佔用的牀的數量。
每一個人都應該由最近的醫院處理,以儘可能減小每一個病人與其指定醫院之間的距離。
若是沒有足夠的牀位,應首先處理病情嚴重的病人,以最大限度地提升全部處理病人的總嚴重程度。經過表示sev(k)患者k的嚴重程度:
而後咱們能夠將全部軟約束簡化爲一個目標:
須要注意的是:這些軟約束沒有相同的定義域。
患者最大化約束範圍從0到n,其中n是患者數,
病情嚴重性限制範圍從0到5n
距離約束範圍從0到全部i和k的最大歐幾里得距離。
考慮到全部這些約束具備相同的優先級,咱們必須定義懲罰因子來平衡不一樣的約束。
下面是相應的代碼:
# 整數的距離函數 idist = lambda xy1, xy2: int(((xy1[0]-xy2[0])**2 + (xy1[1]-xy2[1])**2)**0.5) gain_max_patients = 140 gain_severity = int(140/5) gain_distance = -1 #最大化的目標 soft_csts = [] for i in range(n_hospitals): for j in range(n_beds_in_hospitals[i]): for k in range(n_patients): factor = \ gain_max_patients \ + gain_distance * idist(hospitals_loc[i], patients_loc[k]) \ + gain_severity * patients_severity[k] soft_csts.append(factor * x[(i,j,k)]) model.Maximize(sum(soft_csts))
如今咱們能夠啓動求解器了。它將試圖在指定的時間限制內找到最優解。若是沒法找到最優解,則返回最近的次優解。
solver = cp_model.CpSolver() solver.parameters.max_time_in_seconds = 60.0 status = solver.Solve(model)
在咱們的例子中,求解器在2.5秒內返回一個最優解。
要建立這個解決方案,只須要1小時的研究和30分鐘的編程。
若是使用深度學習,要進行幾天的數據清理,至少一天測試不一樣的架構,另外一天進行訓練。
此外,若是模型良好,CP-SAT模型是很是健壯的。下面是不一樣模擬參數的結果。結果在許多不一樣的狀況下仍然是一致的,隨着模擬參數的增長(3000名患者,1000張病牀),解決方案推斷只需不到3分鐘。
固然,csp幾乎不適用於計算機視覺和NLP等主題,在這些主題中,深度學習有時是最好的方法。然而,在物流、調度和計劃方面,這每每是能夠實現的方法。
深度學習的炒做激發了一些人嘗試一些瘋狂的舉動來得到承認。有時,最好仍是經過閱讀幾篇關於你正在研究的問題的調查報告再想一想你應該如何解決。
[1] Jingchao Chen, Solving Rubik’s Cube Using SAT Solvers, arXiv:1105.1436, 2011.
[2] Biere, A., Heule, M., and van Maaren, H. Handbook of satisfiability, volume 185. IOS press, 2009a
[3] Knuth, D. E., The art of computer programming, Volume 4, Fascicle 6: Satisfiability. Addison-Wesley Professional, 2015
[4] Vipin Kumar, Algorithms for constraint-satisfaction problems: a survey, AI Magazine Volume 13, Issue 1, 1992.
歡迎關注磐創AI博客站: http://panchuang.net/
sklearn機器學習中文官方文檔: http://sklearn123.com/
歡迎關注磐創博客資源彙總站: http://docs.panchuang.net/