1. 程式人生 > 其它 >【TSP】基於matlab遺傳模擬退火演算法求解旅行商問題【含Matlab原始碼 696期】

【TSP】基於matlab遺傳模擬退火演算法求解旅行商問題【含Matlab原始碼 696期】

一、簡介

1 遺傳演算法概述
遺傳演算法(Genetic Algorithm,GA)是進化計算的一部分,是模擬達爾文的遺傳選擇和自然淘汰的生物進化過程的計算模型,是一種通過模擬自然進化過程搜尋最優解的方法。該演算法簡單、通用,魯棒性強,適於並行處理。

2 遺傳演算法的特點和應用
遺傳演算法是一類可用於複雜系統優化的具有魯棒性的搜尋演算法,與傳統的優化演算法相比,具有以下特點:
(1)以決策變數的編碼作為運算物件。傳統的優化演算法往往直接利用決策變數的實際值本身來進行優化計算,但遺傳演算法是使用決策變數的某種形式的編碼作為運算物件。這種對決策變數的編碼處理方式,使得我們在優化計算中可借鑑生物學中染色體和基因等概念,可以模仿自然界中生物的遺傳和進化激勵,也可以很方便地應用遺傳操作運算元。
(2)直接以適應度作為搜尋資訊。傳統的優化演算法不僅需要利用目標函式值,而且搜尋過程往往受目標函式的連續性約束,有可能還需要滿足“目標函式的導數必須存在”的要求以確定搜尋方向。遺傳演算法僅使用由目標函式值變換來的適應度函式值就可確定進一步的搜尋範圍,無需目標函式的導數值等其他輔助資訊。直接利用目標函式值或個體適應度值也可以將搜尋範圍集中到適應度較高部分的搜尋空間中,從而提高搜尋效率。
(3)使用多個點的搜尋資訊,具有隱含並行性。傳統的優化演算法往往是從解空間的一個初始點開始最優解的迭代搜尋過程。單個點所提供的搜尋資訊不多,所以搜尋效率不高,還有可能陷入區域性最優解而停滯;遺傳演算法從由很多個體組成的初始種群開始最優解的搜尋過程,而不是從單個個體開始搜尋。對初始群體進行的、選擇、交叉、變異等運算,產生出新一代群體,其中包括了許多群體資訊。這些資訊可以避免搜尋一些不必要的點,從而避免陷入區域性最優,逐步逼近全域性最優解。
(4) 使用概率搜尋而非確定性規則。傳統的優化演算法往往使用確定性的搜尋方法,一個搜尋點到另一個搜尋點的轉移有確定的轉移方向和轉移關係,這種確定性可能使得搜尋達不到最優店,限制了演算法的應用範圍。遺傳演算法是一種自適應搜尋技術,其選擇、交叉、變異等運算都是以一種概率方式進行的,增加了搜尋過程的靈活性,而且能以較大概率收斂於最優解,具有較好的全域性優化求解能力。但,交叉概率、變異概率等引數也會影響演算法的搜尋結果和搜尋效率,所以如何選擇遺傳演算法的引數在其應用中是一個比較重要的問題。
綜上,由於遺傳演算法的整體搜尋策略和優化搜尋方式在計算時不依賴於梯度資訊或其他輔助知識,只需要求解影響搜尋方向的目標函式和相應的適應度函式,所以遺傳演算法提供了一種求解複雜系統問題的通用框架。它不依賴於問題的具體領域,對問題的種類有很強的魯棒性,所以廣泛應用於各種領域,包括:函式優化、組合優化生產排程問題、自動控制
、機器人學、影象處理(影象恢復、影象邊緣特徵提取......)、人工生命、遺傳程式設計、機器學習。

3 遺傳演算法的基本流程及實現技術
基本遺傳演算法(Simple Genetic Algorithms,SGA)只使用選擇運算元、交叉運算元和變異運算元這三種遺傳運算元,進化過程簡單,是其他遺傳演算法的基礎。

3.1 遺傳演算法的基本流程
通過隨機方式產生若干由確定長度(長度與待求解問題的精度有關)編碼的初始群體;
通過適應度函式對每個個體進行評價,選擇適應度值高的個體參與遺傳操作,適應度低的個體被淘汰;
經遺傳操作(複製、交叉、變異)的個體集合形成新一代種群,直到滿足停止準則(進化代數GEN>=?);
將後代中變現最好的個體作為遺傳演算法的執行結果。

其中,GEN是當前代數;M是種群規模,i代表種群數量。

3.2 遺傳演算法的實現技術
基本遺傳演算法(SGA)由編碼、適應度函式、遺傳運算元(選擇、交叉、變異)及執行引數組成。
3.2.1 編碼
(1)二進位制編碼
二進位制編碼的字串長度與問題所求解的精度有關。需要保證所求解空間內的每一個個體都可以被編碼。
優點:編、解碼操作簡單,遺傳、交叉便於實現
缺點:長度大
(2)其他編碼方法
格雷碼、浮點數編碼、符號編碼、多引數編碼等
3.2.2 適應度函式
適應度函式要有效反映每一個染色體與問題的最優解染色體之間的差距。
3.2.3選擇運算元

3.2.4 交叉運算元
交叉運算是指對兩個相互配對的染色體按某種方式相互交換其部分基因,從而形成兩個新的個體;交叉運算是遺傳演算法區別於其他進化演算法的重要特徵,是產生新個體的主要方法。在交叉之前需要將群體中的個體進行配對,一般採取隨機配對原則。
常用的交叉方式:
單點交叉
雙點交叉(多點交叉,交叉點數越多,個體的結構被破壞的可能性越大,一般不採用多點交叉的方式)
均勻交叉
算術交叉
3.2.5 變異運算元
遺傳演算法中的變異運算是指將個體染色體編碼串中的某些基因座上的基因值用該基因座的其他等位基因來替換,從而形成一個新的個體。

就遺傳演算法運算過程中產生新個體的能力方面來說,交叉運算是產生新個體的主要方法,它決定了遺傳演算法的全域性搜尋能力;而變異運算只是產生新個體的輔助方法,但也是必不可少的一個運算步驟,它決定了遺傳演算法的區域性搜尋能力。交叉運算元與變異運算元的共同配合完成了其對搜尋空間的全域性搜尋和區域性搜尋,從而使遺傳演算法能以良好的搜尋效能完成最優化問題的尋優過程。

3.2.6 執行引數

4 遺傳演算法的基本原理
4.1 模式定理

4.2 積木塊假設
具有低階、定義長度短,且適應度值高於群體平均適應度值的模式稱為基因塊或積木塊。
積木塊假設:個體的基因塊通過選擇、交叉、變異等遺傳運算元的作用,能夠相互拼接在一起,形成適應度更高的個體編碼串。
積木塊假設說明了用遺傳演算法求解各類問題的基本思想,即通過積木塊直接相互拼接在一起能夠產生更好的解。

二、原始碼

%
%     
%輸入input:               文字檔案[序號,x座標,y座標]
%輸出bestRoute:           全域性最優路線
%輸出bestL:               全域性最優路線對應的路徑長度
function [bestRoute,bestL]=SAGA_TSP(filename)
%% 輸入資料
input=importdata(filename);
n=size(input,1);                        %n-城市數目
vertexs=input(:,2:3);                   %城市xy座標
x=vertexs(:,1);                         %x座標
y=vertexs(:,2);                         %y座標
h=pdist(vertexs);
dist=squareform(h);                     %距離矩陣
%% 遺傳演算法引數設定
NIND=50;                                %種群大小
MAXGEN=10;                             %迭代次數
GGAP=0.9;                               %代溝
Pc=0.8;                                 %交叉概率
Pm=0.2;                                 %變異概率
pSwap=0.2;                              %選擇交換結構的概率
pReversion=0.5;                         %選擇逆轉結構的概率
pInsertion=1-pSwap-pReversion;          %選擇插入結構的概率
N=n;                                    %染色體長度=城市數目
%% 模擬退火演算法引數
MaxOutIter=300;                         %外層迴圈最大迭代次數
MaxInIter=15;                           %裡層迴圈最大迭代次數
T0=0.025;                               %初始溫度
alpha=0.99;                             %冷卻因子
%% 種群初始化
Chrom=InitPop(NIND,N);
%% 優化
gen=1;                                  %計數器
bestChrom=Chrom(1,:);                   %初始全域性最優個體
bestL=RouteLength(bestChrom,dist);      %初始全域性最優個體的總距離
BestChrom=zeros(MAXGEN,N);              %記錄每次迭代過程中全域性最優個體
BestL=zeros(MAXGEN,1);                  %記錄每次迭代過程中全域性最優個體的總距離
while gen<=MAXGEN
    %% 計算目標函式值
    ObjV=ObjFunction(Chrom,dist);
    %% 二元錦標賽選擇
    SelCh=BinaryTourment_Select(Chrom,GGAP,ObjV);
    %% OX交叉
    SelCh=Recombin(SelCh,Pc);
    %% 變異
    SelCh=Mutate(SelCh,Pm,pSwap,pReversion,pInsertion);
    %% 對種群中前30%的個體都進行模擬退火操作
    SelCh=SA_Chrom(SelCh,dist,MaxOutIter,MaxInIter,T0,alpha,pSwap,pReversion,pInsertion);
    %% 重插入子代的新種群
    Chrom=Reins(Chrom,SelCh,ObjV);
    %% 計算當前代所有個體總距離
    Obj=ObjFunction(Chrom,dist);
    %% 找出當前代中最優個體
    [minObj,minIndex]=min(Obj);
    %% 將當前代中最優個體與全域性最優個體進行比較,如果當前代最優個體更好,則將全域性最優個體進行替換
    if minObj<=bestL
        bestChrom=Chrom(minIndex,:);
        bestL=minObj;
    end
    %% 記錄每一代全域性最優個體,及其總距離
    BestChrom(gen,:)=bestChrom;
    BestL(gen,:)=bestL;
    %% 顯示外層迴圈每次迭代的信全域性最優路線的總距離
    disp(['第' num2str(gen) '次迭代:全域性最優路線總距離 = ' num2str(bestL)]);
    %% 畫出每次迭代的全域性最優路線圖
    figure(1);
    PlotRoute(bestChrom,x,y)
    pause(0.01);
    %% 計數器加1
    gen=gen+1;
end
%% 對一個個體進行模擬退火操作
%輸入Individual:          種群中的一個個體
%輸入dist:                距離矩陣
%輸入MaxOutIter:          模擬退火外層迴圈最大迭代次數
%輸入MaxInIter:           模擬退火裡層迴圈最大迭代次數
%輸入T0:                  初始溫度
%輸入alpha:               冷卻因子
%輸入pSwap:               選擇交換結構的概率
%輸入pReversion:          選擇逆轉結構的概率
%輸入pInsertion:          選擇插入結構的概率
%輸出newIndividual:       經模擬退火操作後的新個體
function newIndividual=SA_Individual(Individual,dist,MaxOutIter,MaxInIter,T0,alpha,pSwap,pReversion,pInsertion)
%% 初始化
currRoute=Individual;               %當前個體所對應的解
currL=RouteLength(currRoute,dist);  %初始解總距離
bestRoute=currRoute;                %初始將初始解賦值給全域性最優解
bestL=currL;                        %初始將初始解總距離賦值給全域性最優解總距離
T=T0;                               %溫度初始化
%% 模擬退火
for outIter=1:MaxOutIter
    for inIter=1:MaxInIter
        newRoute=Neighbor(currRoute,pSwap,pReversion,pInsertion);       %經過鄰域結構後產生的新的路線
        newL=RouteLength(newRoute,dist);                                %該路線的總距離
        %如果新路線比當前路線更好,則更新當前路線,以及當前路線總距離
        if newL<=currL 
            currRoute=newRoute; 
            currL=newL;
        else 
            %如果新路線不如當前路線好,則採用退火準則,以一定概率接受新路線
            delta=(newL-currL)/currL;           %計算新路線與當前路線總距離相差的百分比
            P=exp(-delta/T);                    %計算接受新路線的概率
            %如果0~1的隨機數小於P,則接受新路線,並更新當前路線,以及當前路線總距離
            if rand<=P
                currRoute=newRoute; 
                currL=newL;
            end
        end
        %將當前路線與全域性最優路線進行比較,如果當前路線更好,則更新全域性最優路線,以及全域性最優路線總距離
        if currL<=bestL
            bestRoute=currRoute;
            bestL=currL;
        end
    end
    %更新當前溫度
    T=alpha*T;
end
newIndividual=bestRoute;                %把bestRoute賦值給newIndividual,更新個體Individual
end
function newChrom=SA_Chrom(Chrom,dist,MaxOutIter,MaxInIter,T0,alpha,pSwap,pReversion,pInsertion)
NIND=size(Chrom,1);         %個體數目
Obj=ObjFunction(Chrom,dist);%計算種群的目標函式值
[~,index]=sort(Obj);        %將種群按照目標函式值從小打大的順序進行排序
SA_num=ceil(NIND*0.3);      %選擇前30%的個體進行模擬退火操作
SA_Chrom=Chrom(index(1:SA_num),:);  %進行模擬退火操作的個體
newChrom=Chrom;             %將新種群初始化為舊種群
for i=1:SA_num
    Individual=SA_Chrom(i,:);  %SA_Chrom中第i個個體,即Chrom中的第index(i)個個體
    %將SA_Chrom中第i個個體進行模擬退火操作後生成的新個體
    newIndividual=SA_Individual(Individual,dist,MaxOutIter,MaxInIter,T0,alpha,pSwap,pReversion,pIns ;
    newChrom(index(i),:)=newIndividual;    %更新新種群的第index(i)個個體
end
end

三、執行結果


四、備註

版本:2014a
完整程式碼或代寫加1564658423