1. 程式人生 > >TSP 遺傳算法

TSP 遺傳算法

代碼 滿足 進制 生物學 data- lin 衡量 隨機 進行

GA——遺傳算法

同模擬退火算法一樣,都是現代優化算法之一。模擬退火是在一定接受程度的情況下仍然接受一個比較差的解。

遺傳算法,是真真正正的和大自然的遺傳進化有著非常緊密的聯系的,當然遺傳進化的只是在生物學中已經講過了,8個字,物競天擇,適者生存。

  • 簡介

《物種起源》,有興趣可以看看達爾文的著作。

物競天擇,適者生存,這兩句話,也可以說是對遺傳算法過程的偽代碼描述了,物競天擇,就是我們的目標函數,只有越滿足我們的目標函數的個體才會留下來,適者生存,就是我們在算法的過程中要淘汰一些個體。

  • 基因編碼方式

生物學裏面告訴我們,遺傳,變異都是以種群為研究對象的,怎麽表示一個解呢?用他的基因表示,嘿嘿,組成這個解的步驟表示,第一步幹什麽,第二步幹什麽,怎麽在程序中編碼呢?

常用兩種編碼方式:二進制編碼,浮點數編碼。

二進制編碼:一定精度的二進制只能表示一定精度的浮點數。栗子,要求精確到6位小數,而區間是 [-1,2],至少要把區間劃分為3*10^6等分。編碼也就需要22位。這裏就涉及到一個二進制串轉換到一個區間為 [-1,2] 的實數,兩者相互轉換。比如得到的十進制數為 x,那麽對應的 [-1,2] 區間的浮點數就是

技術分享圖片

浮點數編碼:為改善遺傳算法的復雜度,提出來浮點數編碼

  • 適應評分及選擇函數

適應評分函數就是用來衡量哪個個體應該被淘汰。但是也不能說,取值差點的個體一定就被淘汰了,這裏會有一個概率存在,怎麽建立一種概率關系呢?常用的方法是輪盤法。假設種群數為 n,某個個體 i 的適應度為 fi,那麽個體 i 被選擇的概率是:

技術分享圖片

So,遺傳算法中的自然選擇過程:

適應評分函數——求出各個體的適應評分值

輪盤選擇——個體被選擇的概率

技術分享圖片

技術分享圖片

  • 基因重組與基因突變

在生物學中,基因重組有兩種情況。

技術分享圖片

技術分享圖片

基因重組,就是兩個個體基因發生交換。

基因突變是一種小概率事件。

使得一個基因變成他的等位基因,引起一定的表現型變化。

技術分享圖片

技術分享圖片

  • TSP問題求解

TSP問題,之前已經用費用流,和模擬退火做過了,現在用遺傳來討論。

程序過程和自然界中的遺傳與進化是一樣的。

  1. 生成50個個體,形成種群,並基因編碼。

  2. 基因重組,突變,和父代,一起進行天擇。

  3. 重復100次進化。得到較優的解。

技術分享圖片

技術分享圖片

clc,clear;
sj0 = load(sj.txt);
x = sj0(:,1:2:8); x = x(:);
y = sj0(:,2:2:8); y = y(:);
sj = [x,y];d1 = [70,40];
sj = [d1;sj;d1]; sj = sj*pi/180;
?
d = zeros(102);
?
for i  = 1:101
    for j = i+1:102
        d(i,j) = 6370*acos(cos(sj(i,1)-sj(j,1))*cos(sj(i,2))*cos(sj(j,2))+sin(sj(i,2))*sin(sj(j,2)));
    end
end
?
d = d + d;
% w 為種群數,g為進化的代數
w = 50;
g = 100;
rand(state,sum(clock));
?
% 改良圈算法選取初始種群
for k=1:w  %通過改良圈算法選取初始種群
    c=randperm(100); %產生1,...,100的一個全排列  
    c1=[1,c+1,102]; %生成初始解
    for t=1:102 %該層循環是修改圈
        flag=0; %修改圈退出標誌
        for m=1:100
            for n=m+2:101
                if d(c1(m),c1(n))+d(c1(m+1),c1(n+1))<d(c1(m),c1(m+1))+d(c1(n),c1(n+1))
                    c1(m+1:n)=c1(n:-1:m+1);  flag=1; %修改圈
                end
            end
        end
        if flag==0
            J(k,c1)=1:102; break %記錄下較好的解並退出當前層循環
        end
   end
end
?
% 染色體編碼
J(:,1) = 0;
J = J/102;
?
% 100次進化
for k = 1:g
    A = J;
    c = randperm(w);
    for i = 1:2:w                       % 基因重組
        F = 2 + floor(100*rand(1));     % 產生交叉操作的染色體對
        tmp = A(c(i),[F:102]);
        A(c(i),[F:102]) = A(c(i+1),[F:102]);
        A(c(i+1),F:102) = tmp;
    end
?
    % 變異
    by = [];
    while ~isempty(by)      % 變異的個體數也是隨機的
        by =find(rand(1,w)<0.1);
    end
    
    B = A(by,:);        % 變異染色體
    for j = 1:length(by)
        bw = sort(2+floor(100*rand(1,3)));      % 產生變異操作的3個地址
        B(j,:) = B(j,[1:bw(1),bw(2)+1:bw(3),bw(1):bw(2),bw(3)+1:102]);
        
    end
    
    G=[J;A;B];       % 父代和子代
    % 基因翻譯為解空間,把染色體翻譯成1,...,102的序列ind1
    [SG,ind1] = sort(G,2);
    num = size(G,1);        % 父子種群的總個體數
    long = zeros(1,num);
    
    % 每一個體的優劣
    for j = 1:num
        for i = 1:101
            long(j) = long(j)+d(ind1(j,i),ind1(j,i+1));
        end
    end
    
    [slong,ind2] = sort(long);
    J = G(ind2(1:w),:);
end
?
path = ind1(ind2(1),:);
flong = slong(1);
xx = sj(path,1);
yy = sj(path,2);
plot(xx,yy,-o);

參考:

ACdreamer

司守奎

TSP 遺傳算法