1. 程式人生 > 其它 >【VRP】基於matlab禁忌搜尋演算法求解初始點和終點確定的取送貨路徑問題【含Matlab原始碼 1224期】

【VRP】基於matlab禁忌搜尋演算法求解初始點和終點確定的取送貨路徑問題【含Matlab原始碼 1224期】

一、禁忌搜尋演算法簡介

1 引言
一個問題的求解過程就是搜尋,它是人工智慧的一個基本問題,而人工智慧在各應用領域中被廣泛地使用。現在搜尋技術滲透在各種人工智慧系統中,可以說沒有哪一種人工智慧的應用不用搜索方法。
禁忌搜尋演算法(Tabu Search or Taboo Search, TS) 的思想最早由美國工程院院士Glover教授於1986年提出[] , 並在1989年和1990年對該方法做出了進一步的定義和發展[2-4]。在自然計算的研究領域
中,禁忌搜尋演算法以其靈活的儲存結構和相應的禁忌準則來避免迂迴搜尋,在智慧演算法中獨樹一幟,成為一個研究熱點,受到了國內外學者的廣泛關注。迄今為止,禁忌搜尋演算法在組合優化、生產排程、機器學習、電路設計和神經網路等領域取得了很大的成功,近年來又在函式全域性優化方面得到較多的研究,並有迅速發展的趨勢[5-8].
所謂禁忌,就是禁止重複前面的操作。為了改進區域性鄰域搜尋容易陷入區域性最優點的不足,禁忌搜尋演算法引入一個禁忌表,記錄下已經搜尋過的區域性最優點,在下一次搜尋中,對禁忌表中的資訊不再搜尋或有選擇地搜尋,以此來跳出區域性最優點,從而最終實現全域性優化。禁忌搜尋演算法是對區域性鄰域搜尋的一種擴充套件,是一種全域性鄰域搜尋、逐步尋優的演算法。
禁忌搜尋演算法是一種迭代搜尋演算法,它區別於其他現代啟發式演算法的顯著特點,是利用記憶來引導演算法的搜尋過程;它是對人類智力過程的一種模擬,是人工智慧的一種體現。禁忌搜尋演算法涉及鄰域、
禁忌表、禁忌長度、候選解、藐視準則等概念,在鄰域搜尋的基礎上,通過禁忌準則來避免重複搜尋,並通過藐視準則來赦免一些被禁忌的優良狀態,進而保證多樣化的有效搜尋來最終實現全域性優化。

2禁忌搜尋演算法理論
2.1區域性鄰域搜尋
區域性鄰域搜尋是基於貪婪準則持續地在當前的鄰域中進行搜尋,雖然其演算法通用,易於實現,且容易理解,但其搜尋效能完全依賴於鄰域結構和初始解,尤其容易陷入區域性極小值而無法保證全域性優化。
區域性搜尋的演算法可以描述為:


這種鄰域搜尋方法易於理解,易於實現,而且具有很好的通用性,但是搜尋結果的好壞完全依賴於初始解和鄰域的結構。若鄰域結構設定不當,或初始解選擇不合適,則搜尋結果會很差,可能只會搜
索到區域性最優解,即演算法在搜尋過程中容易陷入區域性極小值。因此,若不在搜尋策略上進行改進,要實現全域性優化,區域性鄰域搜尋演算法採用的鄰域函式就必須是“完全”的,即鄰域函式將導致解的完全枚
舉。而這在大多數情況下是無法實現的,而且窮舉的方法對於大規模問題在搜尋時間上也是不允許的。為了實現全域性搜尋,禁忌搜尋採用允許接受劣質解的策略來避免區域性最優解。
2.2禁忌搜尋


禁忌搜尋演算法是模擬人的思維的一種智慧搜尋演算法,即人們對已搜尋的地方不會再立即去搜索,而是去對其他地方進行搜尋,若沒有找到,可再搜尋已去過的地方。禁忌搜尋演算法從一個初始可行解出
發,選擇一系列的特定搜尋方向(或稱為“移動”)作為試探,選擇使目標函式值減小最多的移動。為了避免陷入區域性最優解,禁忌搜尋中採用了一種靈活的“記憶”技術,即對已經進行的優化過程進行記錄,指導下一步的搜尋方向,這就是禁忌表的建立。禁忌表中儲存了最近若干次迭代過程中所實現的移動,凡是處於禁忌表中的移動,在當前迭代過程中是禁忌進行的,這樣可以避免演算法重新訪問在最近若
幹次迭代過程中已經訪問過的解,從而防止了迴圈,幫助演算法擺脫區域性最優解。另外,為了儘可能不錯過產生最優解的“移動”,禁忌搜尋還採用“特赦準則”的策略。
對一個初始解,在一種鄰域範圍內對其進行一系列變化,從而得到許多候選解。從這些候選解中選出最優候選解,將候選解對應的目標值與“best so far”狀態進行比較。若其目標值優於“best sofar”狀態, 就將該候選解解禁, 用來替代當前最優解及其“best sofar”狀態, 然後將其加入禁忌表, 再將禁忌表中相應物件的禁忌長度改變:如果所有的候選解中所對應的目標值都不存在優於“best sofar”狀態, 就從這些候選解中選出不屬於禁忌物件的最佳狀態, 並將其作為新的當前解,不用與當前最優解進行比較,直接將其所對應的物件作為禁忌物件,並將禁忌表中相應物件的禁忌長度進行修改。
2.3禁忌搜尋演算法的特點

禁忌搜尋演算法是在鄰域搜尋的基礎上,通過設定禁忌表來禁忌一些已經進行過的操作,並利用藐視準則來獎勵一些優良狀態,其中鄰域結構、候選解、禁忌長度、禁忌物件、藐視準則、終止準則等是影
響禁忌搜尋演算法效能的關鍵。鄰域函式沿用區域性鄰域搜尋的思想,用於實現鄰域搜尋;禁忌表和禁忌物件的設定,體現了演算法避免迂迴搜尋的特點:藐視準則,則是對優良狀態的獎勵,它是對禁忌策略的一種放鬆。
與傳統的優化演算法相比,禁忌搜尋演算法的主要特點是:
(1)禁忌搜尋演算法的新解不是在當前解的鄰域中隨機產生,它要麼是優於“best so far”的解, 要麼是非禁忌的最佳解, 因此選取優良解的概率遠遠大於其他劣質解的概率。
(2)由於禁忌搜尋演算法具有靈活的記憶功能和藐視準則,並且在搜尋過程中可以接受劣質解,所以具有較強的“爬山”能力,搜尋時能夠跳出區域性最優解,轉向解空間的其他區域,從而增大獲得更好的全域性最優解的概率。因此,禁忌搜尋演算法是一種區域性搜尋能力很強的全域性迭代尋優演算法。

2.4禁忌搜尋演算法的改進方向
禁忌搜尋是著名的啟發式搜尋演算法,但是禁忌搜尋也有明顯的不足,即在以下方面需要改進:
(1)對初始解有較強的依賴性,好的初始解可使禁忌搜尋演算法在解空間中搜索到好的解,而較差的初始解則會降低禁忌搜尋的收斂速度。因此可以與遺傳演算法、模擬退火演算法等優化演算法結合,先產生較好的初始解,再用禁忌搜尋演算法進行搜尋優化。
(2)迭代搜尋過程是序列的,僅是單一狀態的移動,而非並行搜尋。為了進一步改善禁忌搜尋的效能,一方面可以對禁忌搜尋演算法本身的操作和引數選取進行改進,對演算法的初始化、引數設定等方面實
施並行策略,得到各種不同型別的並行禁忌搜尋演算法[9]:另一方面則可以與遺傳演算法、神經網路演算法以及基於問題資訊的區域性搜尋相結合。
(3)在集中性與多樣性搜尋並重的情況下,多樣性不足。集中性搜尋策略用於加強對當前搜尋的優良解的鄰域做進一步更為充分的搜尋,以期找到全域性最優解。多樣性搜尋策略則用於拓寬搜尋區域,尤
其是未知區域,當搜尋陷入區域性最優時,多樣性搜尋可改變搜尋方向,跳出區域性最優,從而實現全域性最優。增加多樣性策略的簡單處理手段是對演算法的重新隨機初始化,或者根據頻率資訊對一些已知物件進行懲罰。

3 禁忌搜尋演算法流程
簡單禁忌搜尋演算法的基本思想是:給定一個當前解(初始解)和一種鄰域,然後在當前解的鄰域中確定若干候選解;若最佳候選解對應的目標值優於“best so far”狀態, 則忽視其禁忌特性, 用它替代當前解和“best so far”狀態, 並將相應的物件加入禁忌表, 同時修改禁忌表中各物件的任期:若不存在上述候選解,則在候選解中選擇非禁忌的最佳狀態為新的當前解,而無視它與當前解的優劣,同時將相應的物件加入禁忌表,並修改禁忌表中各物件的任期。如此重複上述迭代搜尋過程,直至滿足停止準則。其演算法步驟可描述如下:
(1)給定禁忌搜尋演算法引數,隨機產生初始解x,置禁忌表為空。
(2)判斷演算法終止條件是否滿足:若是,則結束演算法並輸出優化結果:否則,繼續以下步驟。
(3)利用當前解的鄰域函式產生其所有(或若干)鄰域解,並從中確定若干候選解。
(4)對候選解判斷藐視準則是否滿足:若滿足,則用滿足藐視準則的最佳狀態y替代x成為新的當前解,即x=y,並用與y對應的禁忌物件替換最早進入禁忌表的禁忌物件, 同時用y替換“best so far”狀態,然後轉步驟(6):否則,繼續以下步驟。
(5)判斷候選解對應的各物件的禁忌屬性,選擇候選解集中非禁忌物件對應的最佳狀態為新的當前解,同時用與之對應的禁忌物件替換最早進入禁忌表的禁忌物件。
(6)判斷演算法終止條件是否滿足:若是,則結束演算法並輸出優化結果:否則,轉步驟(3)。
禁忌搜尋演算法的運算流程如圖8.1所示。

4 關鍵引數說明
一般而言,要設計一個禁忌搜尋演算法,需要確定演算法的以下環節:初始解、適配值函式、鄰域結構、禁忌物件、候選解選擇、禁忌表、禁忌長度、藐視準則、搜尋策略、終止準則[10,11]。面對如此眾
多的引數,針對不同鄰域的具體問題,很難有一套比較完善的或非常嚴格的步驟來確定這些引數。
初始解
禁忌搜尋演算法可以隨機給出初始解,也可以事先使用其他啟發式演算法等給出一個較好的初始解。由於禁忌搜尋演算法主要是基於鄰域搜尋的,初始解的好壞對搜尋的效能影響很大。尤其是一些帶有很複雜
約束的優化問題,如果隨機給出的初始解很差,甚至通過多步搜尋也很難找到一個可行解,這時應該針對特定的複雜約束,採用啟發式方法或其他方法找出一個可行解作為初始解;再用禁忌搜尋演算法求解,以提高搜尋的質量和效率。也可以採用一定的策略來降低禁忌搜尋對初始解的敏感性。
適配值函式
禁忌搜尋的適配值函式用於對搜尋進行評價,進而結合禁忌準則和特赦準則來選取新的當前狀態。目標函式值和它的任何變形都可以作為適配值函式。若目標函式的計算比較困難或耗時較長,此時可採
用反映問題目標的某些特徵值來作為適配值,進而改善演算法的時間效能。選取何種特徵值要視具體問題而定,但必須保證特徵值的最佳性與目標函式的最優性一致。適配值函式的選擇主要考慮提高演算法的效率、便於搜尋的進行等因素。
鄰域結構
所謂鄰域結構,是指從一個解(當前解)通過“移動”產生另一個解(新解)的途徑,它是保證搜尋產生優良解和影響演算法搜尋速度的重要因素之一。鄰域結構的設計通常與問題相關。鄰域結構的設計方法很多,對不同的問題應採用不同的設計方法,常用設計方法包括互換、插值、逆序等。不同的“移動”方式將導致鄰域解個數及其變化情況的不同,對搜尋質量和效率有一定影響。

通過移動,目標函式值將產生變化,移動前後的目標函式值之差,稱之為移動值。如果移動值是非負的,則稱此移動為改進移動:否則,稱之為非改進移動。最好的移動不一定是改進移動,也可能是
非改進移動,這一點能保證在搜尋陷入區域性最優時,禁忌搜尋演算法能自動把它跳出區域性最優。

禁忌物件
所謂禁忌物件,就是被置入禁忌表中的那些變化元素。禁忌的目的則是為了儘量避免迂迴搜尋而多搜尋一些解空間中的其他地方。歸納而言,禁忌物件通常可選取狀態本身或狀態分量等。

候選解選擇
候選解通常在當前狀態的鄰域中擇優選取,若選取過多將造成較大的計算量,而選取較少則容易“早熟”收斂,但要做到整個鄰域的擇優往往需要大量的計算,因此可以確定性地或隨機性地在部分鄰域中選取候選解,具體資料大小則可視問題特徵和對演算法的要求而定。
禁忌表
不允許恢復(即被禁止) 的性質稱作禁忌(Tabu) 。禁忌表的主要目的是阻止搜尋過程中出現迴圈和避免陷入區域性最優,它通常記錄前若干次的移動,禁止這些移動在近期內返回。在迭代固定次數後,
禁忌表釋放這些移動,重新參加運算,因此它是一個迴圈表,每迭代一次,就將最近的一次移動放在禁忌表的末端,而它的最早的一個移動就從禁忌表中釋放出來。
從資料結構上講,禁忌表是具有一定長度的先進先出的佇列。禁忌搜尋演算法使用禁忌表禁止搜尋曾經訪問過的解,從而禁止搜尋中的區域性迴圈。禁忌表可以使用兩種記憶方式:明晰記憶和屬性記憶。明
晰記憶是指禁忌表中的元素是一個完整的解,消耗較多的記憶體和時間:屬性記憶是指禁忌表中的元素記錄當前解移動的資訊,如當前解移動的方向等。

禁忌長度
所謂禁忌長度,是指禁忌物件在不考慮特赦準則的情況下不允許被選取的最大次數。通俗地講,禁忌長度可視為禁忌物件在禁忌表中的任期。禁忌物件只有當其任期為0時才能被解禁。在演算法的設計和構
造過程中,一般要求計算量和儲存量儘量小,這就要求禁忌長度儘量小。但是,禁忌長度過小將造成搜尋的迴圈。禁忌長度的選取與問題特徵相關,它在很大程度上決定了演算法的計算複雜性。
一方面,禁忌長度可以是一個固定常數(如t=c,c為一常數),或者固定為與問題規模相關的一個量(如t=√n,n為問題維數或規模),如此實現起來方便、簡單,也很有效:另一方面,禁忌長度也可以是動態變化的,如根據搜尋效能和問題特徵設定禁忌長度的變化區間,而禁忌長度則可按某種規則或公式在這個區間內變化。

藐視準則
在禁忌搜尋演算法中,可能會出現候選解全部被禁忌,或者存在一個優於“best so far”狀態的禁忌候選解, 此時特赦準則將某些狀態解禁,以實現更高效的優化效能。特赦準則的常用方式有:
(1) 基於適配值的原則:某個禁忌候選解的適配值優於“bestso far”狀態, 則解禁此候選解為當前狀態和新的“best so far”狀態。
(2)基於搜尋方向的準則:若禁忌物件上次被禁忌時使得適配值有所改善,並且目前該禁忌物件對應的候選解的適配值優於當前解,則對該禁忌物件解禁。

搜尋策略
搜尋策略分為集中性搜尋策略和多樣性搜尋策略。集中性搜尋策略用於加強對優良解的鄰域的進一步搜尋。其簡單的處理手段可以是在一定步數的迭代後基於最佳狀態重新進行初始化,並對其鄰域進行再次搜尋。在大多數情況下,重新初始化後的鄰域空間與上一次的鄰域空間是不一樣的,當然也就有一部分鄰域空間可能是重疊的。多樣性搜尋策略則用於拓寬搜尋區域,尤其是未知區域。其簡單的處理手段可以是對演算法的重新隨機初始化,或者根據頻率資訊對一些已知物件進行懲罰。

終止準則
禁忌搜尋演算法需要一個終止準則來結束演算法的搜尋程序,而嚴格理論意義上的收斂條件,即在禁忌長度充分大的條件下實現狀態空間的遍歷,這顯然是不可能實現的。因此,在實際設計演算法時通常採用
近似的收斂準則。常用的方法有:
(1)給定最大迭代步數。當禁忌搜尋演算法執行到指定的迭代步數之後,則終止搜尋。
(2)設定某個物件的最大禁忌頻率。若某個狀態、適配值或對換等物件的禁忌頻率超過某一閾值,或最佳適配值連續若干步保持不變,則終止演算法。
(3)設定適配值的偏離閾值。首先估計問題的下界,一旦演算法中最佳適配值與下界的偏離值小於某規定閾值,則終止搜尋。

二、部分原始碼

clear;
CityNum=22;
[dislist,Clist]=tsp(CityNum);
Tlist=zeros(CityNum);%禁忌表(tabu list)
cl=60;%保留前cl個最好候選解
bsf=Inf;
tl=50; %禁忌長度(tabu length)
l1=100;%候選解(candidate),不大於n*(n)/2(全部領域解個數)
S0=randperm(CityNum);
S0(:,1)=0;
S0(:,CityNum)=CityNum-1;
S0(:,2:CityNum-1)=randperm(CityNum-2);
S0=S0+ones;
S=S0(:,2:CityNum-1);
Num=length(S);
BSF=S0;
Si=zeros(l1,Num);
StopL=100; %終止步數
p=1;
clf;
figure(1);
while (p<StopL+1)
    if l1>Num*(Num)/2
        disp('候選解個數,不大於n*(n)/2(全部領域解個數)! 系統自動退出!');
        l1=(Num*(Num)/2)^.5;
        break;
    end
    ArrS(p)=CalDist(dislist,S);        
    i=1;
    A=zeros(l1,2);
    while i<=l1        
        M=Num*rand(1,2);
        M=ceil(M);
        if M(1)~=M(2)
            m1=max(M(1),M(2));m2=min(M(1),M(2));
            A(i,1)=m1;A(i,2)=m2;
            if i==1
                isdel=0;
            else
                for j=1:i-1
                    if A(i,1)==A(j,1)&&A(i,2)==A(j,2)
                        isdel=1;
                        break;
                    else
                        isdel=0;
                    end
                end
            end
            if ~isdel
                i=i+1;
            else
                i=i;
            end
        else 
            i=i;
        end
    end
    
    for i=1:l1
        Si(i,:)=S;
        Si(i,[A(i,1),A(i,2)])=S([A(i,2),A(i,1)]);
        CCL(i,1)=i;
        CCL(i,2)=CalDist(dislist,Si(i,:));
        CCL(i,3)=S(A(i,1));
        CCL(i,4)=S(A(i,2));   
    end
    [fs fin]=sort(CCL(:,2));
    for i=1:cl
        CL(i,:)=CCL(fin(i),:);
    end
    
    if CL(1,2)<bsf  %藐視準則(aspiration criterion)
        bsf=CL(1,2);
        S=Si(CL(1,1),:);        
        BSF(:,2:CityNum-1)=S;
        for m=1:Num
            for n=1:Num
                if Tlist(m,n)~=0
                    Tlist(m,n)=Tlist(m,n)-1;
                end
            end
        end
        Tlist(CL(1,3),CL(1,4))=tl;
    else  
        for i=1:cl
            if Tlist(CL(i,3),CL(i,4))==0
                S=Si(CL(i,1),:);
                for m=1:Num
                    for n=1:Num
                        if Tlist(m,n)~=0
                            Tlist(m,n)=Tlist(m,n)-1;
                        end
                    end
                end
                Tlist(CL(i,3),CL(i,4))=tl;
                break;
            end
        end
        end
        
    Arrbsf(p)=bsf;
    drawTSP(Clist,BSF,bsf,p,0);
    p=p+1;
end
BestShortcut=BSF;
 
theMinDistance=bsf
figure(2);
plot(Arrbsf,'r'); hold on;
plot(ArrS,'b');grid;
title('搜尋過程');
legend('最優解','當前解');
function F=CalDist(dislist,s)
n=size(s,2);
v1=0.8;%裝卸速度
v2=20;%行車速度
w1=0.9;%比重
w2=3;
w3=6;
c=20;%固定損耗成本
r=0.025;%車損與載重質量的損耗係數
q=[0,5,0.5,1,10,4.7,4,1,2,5.5,4,1.5,10,11.1,2,1.4,2.9,0.1,4.7,2,7.9,0];%按照1-30個站點順序
t1=[0,9.2,10.7,5.9,8.0,9.4,8.8,10.1,11.2,12.0,12.9,13.4,14.2,15.0,16.5,14.3,13.5,13,14.2,16.2,15.3,17];
t2=[34.0,10.0,12.1,6.3,8.5,9.9,9.7,10.9,11.7,12.6,19.4,13.9,14.9,15.5,17.4,18.2,18.9,19.1,19.8,20.4,20.9,23];
q1=zeros(1,n);%更新後的站點順序
t11=zeros(1,n);
t21=zeros(1,n);
z1=zeros(1,n);%儲存超出時間窗的
z2=zeros(1,n);
t=zeros(1,n);%每個站點的到達時間
DistanV=0;%配送成本
loss=0;%車損成本
for i1=1:n
    k=find(s(:,:)==i1);
    q1(:,k)=q(:,i1);
    t11(:,k)=t1(:,i1);
    t21(:,k)=t2(:,i1);
end
q1;
t11;
t21;
for j=1:(n-1)
   DistanV=DistanV+dislist(s(j),s(j+1));
    t(:,j+1)=t(j)+(dislist(s(j),s(j+1))/v2)+max(0,t11(:,j)-t(:,j))+q1(:,j)/v1;
    loss=loss+c*(1+r*q1(:,j));
end
DistanV=DistanV+dislist(s(n),s(1));
loss=loss+c;
t(:,1)=t(:,n)+(dislist(s(n),s(1))/v2)+max(0,t11(:,n)-t(:,n))+q1(:,n)/v1;
t;
for m=1:n
if t11(:,m)-t(:,m)>0
    z1(:,m)=z1(:,m)+t11(:,m)-t(:,m);
end
if t(:,m)-t21(:,m)>0
    z2(:,m)=z2(:,m)+t(:,m)-t21(:,m);
end
end
 function [DLn,cityn]=tsp(n)
CityNum=22;
city=[1304,1312;
3488,1535;
3326,1556;
3238,1229;
4196,1004;
4386,570;
3007,1970;
2562,1756;
3918,2179;
4061,2370;
3780,2212;
3676,2578;
4029,2838;
4263,2931;
3429,1908;
3394,2643;
3439,3201;
2935,3240;
3140,3550;
2780,2092;
676,1978;
2449,748];
    for i=1:CityNum
        for j=1:CityNum
            DL(i,j)=((city(i,1)-city(j,1))^2+(city(i,2)-city(j,2))^2)^0.5;
        end
    end
    DLn=DL;
    cityn=city;

三、執行結果



四、matlab版本及參考文獻

1 matlab版本
2014a

2 參考文獻
[1] 包子陽,餘繼周,楊杉.智慧優化演算法及其MATLAB例項(第2版)[M].電子工業出版社,2016.
[2]張巖,吳水根.MATLAB優化演算法原始碼[M].清華大學出版社,2017.