模擬退火算法求解指派問題

模擬退火算法(Simulated Annealing)求解工作指派問題(Assignment Problem)的Python實現

1 簡單指派問題

n 個工作可以由n 個工人分別完成。工人i 完成工作j 的時間爲dij 。如何安排可使總工作時間達到極小?

2 Python實現

# -*- coding: utf-8 -*-
'''
basic SA algorithm on assignment problem.
Hint:number of workers equals that of jobs.
coder:yangsen @ UCAS.
reference:中國科學院大學2017春季課程《智能優化算法》chapter4
'''
import numpy as np
#instance 1: 4 workers and 4 jobs. Every row corresponds one worker.
d=np.array([[2,15,13,4],[10,4,14,15],[9,14,16,13],[7,8,11,9]])
#best solution:x=[4,2,1,3], that is saying, worker 1 do job 4, and 
#worker 2 do job 2, etc.
#instance 2: 5 workers and 5 jobs
d=np.array([[7,2,8,11,12],[9,12,11,9,12],[8,5,6,8,12],[7,3,9,6,12],[4,6,5,11,12]])
#best solution:x=[2,5,3,4,1]
num=d.shape[0]#number of worker and job.
def cal_total_time(x):
    total_time=0
    for i in range(num):
        total_time+=d[i,x[i]]
    return total_time

T=100 #initial temperature
t=1# final temperature
alpha=0.9#annealing rate
markov_len=1000 #inner loop,aka,markov length
current_x=np.random.permutation(num)#initialize the solution
current_time=cal_total_time(current_x)
new_x=current_x.copy()
best_x=current_x.copy()
best_time=np.max
while T>t:
    for i in range(markov_len):
        while True:
            k=np.random.randint(0,num,2)
            if k[0]!=k[1]:
                break
        new_x[k[0]],new_x[k[1]]=new_x[k[1]],new_x[k[0]]
        new_time=cal_total_time(new_x)
        if new_time<current_time:#accept new solution with no condition.
            current_time=new_time
            current_x=new_x.copy()
            if new_time<best_time:
                best_time=new_time
                best_x=new_x.copy()
        else:
            delta=new_time-current_time
            if np.random.rand()<np.exp(-delta/T):#accept new solution with an probability.
                current_time=new_time
                current_x=new_x.copy()
            else:
                new_x=current_x.copy()#refuse new solution.
    T=T*alpha
    print current_x,current_time

程序中實例規模太小,無法體現SA算法的尋優能力,但一時找不到合適的實例。後面找到規模較大的實例後,補充到博客中去。
P.S:對於指派問題還有一種更一般的提法,就是工人數和工作數目不等的情況。針對這種情況,一種最容易想到的處理方式就是增加虛擬工人或虛擬工作,但會有很多問題需要處理。比如,如果工人數少,則必然有工人要做多個工作,而如果工人多,則有工人閒着。後者的處理比較簡單。
指派問題有經典的算法,匈牙利算法。

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