利用遺傳學演算法求解工作分配問題

萬倉一黍 發表於 2021-07-24
演算法

問題:現在有10份工作。有300名工人被分配參與這10份工作,每份工作需要30人。每人蔘與不同的工作都有個評價值,代表該人蔘與該工作的損耗值,損耗值的範圍在0-9。問:如何分配這300人工作,使得總的損耗值最低。

 

本問題的基礎資料: 工人選擇工作損耗表資料.rar

 

 

這是一個典型的工作分配問題。當然,利用匈牙利演算法能求出該問題的最優解

 

今天,本文介紹利用遺傳學演算法來求解該工作分配問題

 

下面先介紹些名詞解釋:

 

先給工人編個號,工人001-工人300

再給工作編個號,工作01-工作10

 

個體例項:一個實際的分配方案被稱為個體例項。例如:工人001-工人030參與工作01、工人031-工人060參與工作02、……、工人271-工人300參與工作10。這就是一個個體例項。當然,個體例項的總的可能數非常多,要遍歷每個個體例項並找到最優解幾乎不可能。

 

例項權重:每個個體例項代表一個實際分配方案,那麼該方案的所有工人的損耗值的總和——總的損耗值,就是該個體例項例項權重。求解最優解就是找到例項權重最小的那個個體例項

 

基因:每個個體例項中,每一位工人選擇參與的工作,稱為該個體例項的一個基因。很顯然,每個個體例項有300個基因,每個基因有10個選擇可能。基因間有相互約束的作用(每份工作有且只有30人選擇,不能多也不能少)。給基因編個號,基因001-基因300

 

繁衍:兩個個體例項生成一個新的個體例項的過程稱為繁衍。兩個個體例項稱為父代,新個體例項稱為子代。子代,從基因001開始,隨機從兩個父代的基因001中選擇一個,依次類推,直到基因300為止。這樣隨機選擇300個基因後,會產生一個新的問題——基因衝突,即某些工作會有超過30人,而某些工作會不足30人。再利用平衡演算法進行例項內部的基因調整,使得每份工作有且只有30人。這樣的子代才是符合問題的個體例項。

 

變異:一個個體例項生成一個新的個體例項的過程稱為變異。一個個體例項稱為父代,新個體例項稱為子代。父代中隨機選取N對基因,對換這N對基因,生成子代(例如:選擇基因033和基因254,分別代表工人033和工人254的選擇,交換他們的選擇,這樣不會產生基因衝突的問題)。

 

種群:若干個個體例項組成一個種群。遺傳學演算法的核心就是構建一個種群種群裡個體例項數要合適。不能太少,太少了求解最優解的可能性降低;不能太多,雖然能提高求解最優解的可能性,但是也會大大增加求解的時間消耗。

 

迭代種群進化的過程稱為迭代。過程如下:先在種群中選取部分個體例項,通過繁衍生成若干子代;再在種群中選取部分個體例項,通過變異生成若干子代。這樣子代歸入到種群中,種群中的數量就增加了,再對種群中的個體例項按照例項權重進行選擇,淘汰掉部分個體例項,以維持種群中的個體例項數量(像不像大自然的自然選擇,優勝劣汰?)。本問題中,按照例項權重進行排序,保留例項權重小的個體例項,淘汰掉例項權重大的個體例項

 

下面介紹如何用遺傳學演算法求解本問題

 

構建種群

先構造一個含有2000個個體例項的種群

每個個體例項的建立過程如下:先隨機產生一個工人序列,然後按照工人序列,每位工人都選擇當前對他來說損耗最小的工作(最好是選擇損耗為0的工作,但假如該工作已經滿員了,就選擇損耗為1的工作,依次類推)。很顯然,最後一位工人只有一種選擇。這樣生成的個體例項的例項權重大約在85-140之間

 

進行迭代

每次迭代,隨機選擇父代繁衍出1000個子代,變異出100個子代。這樣父代和子代加在一起一共3100個(2000+1000+100),然後對這3100個個體例項按照例項權重進行排序,保留權重最低的2000個個體例項,1100個個體例項被淘汰掉,保留種群中2000個個體例項的數量穩定

 

之前提過,在繁衍的生成的子代可能會有基因衝突(某些工作會有超過30人,而某些工作會不足30人),需要通過平衡演算法進行例項內部的基因調整,使得每份工作有且只有30人。下面介紹該平衡演算法

1、 找到超過30人的工作,假設超過K人。若找不到,說明已經平衡,退出演算法

2、 找到所有低於30人的工作,記工作集W

3、 在步驟1中的每一位工人,計算出在工作集W中所有工作的損耗值的最小值,並記錄對應的工作編號

4、 對步驟1中的所有工人按照步驟3中的最小值進行排序,取最小的前K人,分配到其所對應的工作中。這樣保證步驟1中的工作就只有30人了

5、 重複步驟1

 

通過上面的迭代過程,進行若干次迭代,在迭代結束後,在種群中找到例項權重最小的個體例項就是該問題的最優解

 

那麼,如何判斷出已經得到最優解,來終止迭代過程呢?有兩種方法

一是,指定迭代次數,例如迭代1000次。

這個由於沒有理論支撐,並不知道1000次能迭代到什麼地步,故不合適。

 

二是,每次迭代後,都計算一下新的子代在種群中的數目。若連續若干次迭代(例如10次)新的子代在種群中的數目為0,那麼迭代結束(說明迭代已經不能產生新的個體例項了)

本文中,用的就是這個,下面把迭代過程貼一下

 

迭代過程:迭代過程.rar

最優解:最優解.rar

 

後記

遺傳學演算法能不能找到最優解?這個不一定的,看迭代的資料收斂性了,但是能收斂到一個區域性最優解(接近最優解或者就是最優解)。目前,通過幾次的求解過程,所得到的最優解是55,假如有人算出更優解,歡迎交流

 

通過檢視迭代資料,發現,迭代結束的時候,種群中的個體例項的權重都是55,也就是全部個體例項都一樣了。