遺傳算法MATLAB程序

遺傳算法的基本處理流程:

  1. 產生初始種羣
  2. 計算種羣中個體對應的實際結果的值
  3. 計算個體對應的適應度
  4. 根據適應度可以選擇個體
  5. 交叉
  6. 變異
  7. 求最佳結果

【遺傳算法】搜狗百科

研一的課程要求讓我們自己學習對應的算法並做課堂展示,講義中給出了案例,並給出了這7步對應的函數,自己編寫代碼求解最佳結果

【問題】有8個城市,旅行商要尋找一條路線使路徑距離之和最短

結果如圖:

在這裏插入圖片描述

代碼如下:

GA(遺傳算法)求最短路徑

%% 遍歷8個城市的最短路徑問題
%產生初始種羣
popsize=factorial(8);%初始種羣的大小
chromlength=8;%8個城市,種羣個體的串數據長度爲8
pop=initpop1(popsize,chromlength); %pop的形狀爲40320*8
%計算種羣中所有個體的值,此處爲計算出路徑的距離
[objvalue]=calobjvalue1(pop);
%計算個體適應度,此處爲距離的倒數
[fitvalue]=calfitvalue1(objvalue);
%選擇
[newpop,a,b]=selection1(pop,fitvalue);
%交叉,交叉位置爲3
pc=3;
[newpop1]=crossover1(newpop,pc);
%變異,變異位置爲2
pm=2;
[newpop2]=mutation1(newpop1,pm);
%重新計算距離
[newobjvalue]=calobjvalue1(newpop2);
%重新計算個體適應度
[newfitvalue]=calfitvalue1(newobjvalue);
%選出最佳個體、終止
[bestindividual,bestfit,worstindividual,worstfit]=best1(a,newpop2,newfitvalue);
bestindividual
%bestfit
worstindividual
%worstfit
%最佳結果繪圖展示
D=[5 0;3.54 3.54;0 5;-3.54 3.54;-5 0;-3.54 -3.54;0 -5;3.54 -3.54];%城市座標
bestD=D;
for i=1:8
    bestD(i,1)=D(bestindividual(i),1);
    bestD(i,2)=D(bestindividual(i),2);
end
figure(1);
subplot(1,2,1);
plot(bestD(:,1),bestD(:,2),'-*');
title("最近路徑");
strbestfitvalue="適應度"+num2str(bestfit);
text(3,4.5,strbestfitvalue);
for ii=1:8
    text(D(ii,1)+0.1,D(ii,2)+0.1,int2str(ii));
end
figure(gcf);
%最壞結果繪圖展示
worstD=D;
for i=1:8
    worstD(i,1)=D(worstindividual(i),1);
    worstD(i,2)=D(worstindividual(i),2);
end
%figure(2);
subplot(1,2,2);
plot(worstD(:,1),worstD(:,2),'-*');
title("最遠路徑");
strworstfitvalue="適應度"+num2str(worstfit);
text(3,4.5,strworstfitvalue);
for ii=1:8
    text(D(ii,1)+0.1,D(ii,2)+0.1,int2str(ii));
end
figure(gcf);

其中使用到的函數有以下7個:

產生初始種羣

%% 產生初始種羣,popsize爲初始種羣的個數,chromlength爲每個個體的長度
function pop=initpop1(popsize,chromlength)
for i=1:popsize
    pop(i,:)=randperm(chromlength);% randperm產生1-chromlength的隨機排列
end

計算個體的值

function [objvalue]=calobjvalue1(pop)%計算目標函數值即距離
D=[5 0;3.54 3.54;0 5;-3.54 3.54;-5 0;-3.54 -3.54;0 -5;3.54 -3.54];%確定城市座標
[px,py]=size(pop);
for i=1:px
    k=sqrt((D(pop(i,1),1)-D(pop(i,py),1))^2+(D(pop(i,1),2)-D(pop(i,py),2))^2);
    for j=1:py-1
        k=k+sqrt((D(pop(i,j),1)-D(pop(i,j+1),1))^2+(D(pop(i,j),2)-D(pop(i,j+1),2))^2);
    end
    objvalue(i)=k;
end

計算個體對應的適應度

%%計算個體適應度
function [fitvalue]=calfitvalue1(objvalue)
x=objvalue;
fitvalue=1./x;%距離最小映射爲適應度最大
fitvalue=10.*x.*x-1400*x+49000;%二次函數,可以實現非線性映射,並使種羣更易收斂到最優解

選擇

function [newpop,a,b]=selection1(pop,fitvalue) %選擇
totalfit=sum(fitvalue); %求適應度值之和
pfitvalue=fitvalue/totalfit; %單個個體被選擇的概率
mfitvalue=cumsum(pfitvalue); %如fitvalue=[1 2 3 4]cumsum(fitvalue)=[1 3 6 10] 
[px,py]=size(pop);
ms=(rand(px,1)); %轉動輪盤
a=ms;
b=mfitvalue;
fitin=1; 
newin=1;
newpop=zeros(px,py);
while newin<=px
    if mfitvalue(fitin)>ms(newin)
        newpop(newin,:)=pop(fitin,:); 
        newin=newin+1; 
        fitin=1;
    else
        fitin=fitin+1;
    end
end

交叉

function [newpop1]=crossover1(newpop,pc)%交叉
[px,py]=size(newpop);
newpop1=zeros(size(newpop));
for i=1:px
    po=rand(1);
    if po<pc
        y=round(rand*px);%隨機尋找交叉對象
        x1=round(rand*py); %隨機尋找交叉點
        x2=round(rand*py); %隨機尋找交叉點
        cpoint1=min(x1,x2);%尋找交叉起點 
        cpoint2=max(x1,x2);%尋找交叉終點
        while cpoint1==0||cpoint2==0||y==0
            y=round(rand*px);%隨機尋找交叉對象
            x1=round(rand*py); %隨機尋找交叉點
            x2=round(rand*py); %隨機尋找交叉點
            cpoint1=min(x1,x2);%尋找交叉起點
            cpoint2=max(x1,x2);%尋找交叉終點
        end
        newpop1(i,:)=[newpop(i,1:cpoint1-1),newpop(y,cpoint1:cpoint2),newpop(i,cpoint2+1:py)]; %兩個染色體在交叉點位置交叉
        t=1;
        while t==1
            t=0;
            for m=1:py
                for n=cpoint1:cpoint2
                    if newpop1(i,m)==newpop1(i,n) &&(m<cpoint1||m>cpoint2)
                        newpop1(i,m)=newpop(i,n);
                    t=1;
                    end
                end %對交叉後染色體做調整
            end
        end
    else
        newpop1(i,:)=newpop(i,:);% 產生新染色體
    end
end

變異

function [newpop2]=mutation1(newpop1,pm) % 變異
%Name: mutation.m
[px,py]=size(newpop1);
newpop2=zeros(px,py);
for i=1:px
    ps=rand;
    if ps<pm
        mpoint1=round(rand*py);
        mpoint2=round(rand*py);
        if mpoint1<=0||mpoint2<=0
            mpoint1=1;
            mpoint2=1;
        end
        t=newpop1(i,mpoint1);
        newpop1(i,mpoint1)=newpop1(i,mpoint2);
        newpop1(i,mpoint2)=t;
    end
end
newpop2=newpop1;

找到最佳和最差的個體

%% 找到最佳個體
function [bestindividual,bestfit,worstindividual,worstfit]=best1(a,newpop2,newfitvalue)%最佳個體
%Name: best.m
[px,py]=size(newpop2);
bestindividual=newpop2(1,:);%假設新的經過交叉變異的種羣中第一個個體就是距離最短的
bestfit=newfitvalue(1);%假設第一個是適應度最好的,爲了比較設置初始值
wostfit=newfitvalue(1);%假設第一個是適應度最壞的,爲了比較設置初始值
j=1;
%挨個對比所有的個體找到適應度最差的位置
for i=1:px
    if newfitvalue(i)<wostfit
        j=i;
        wostfit=newfitvalue(i);
    end
end
worstindividual=newpop2(j,:);%將最差的替換爲上一代的最好的
worstfit=newfitvalue(j);
for i=1:px
    if newfitvalue(i)>bestfit %更新爲適應度大的個體
        bestindividual=newpop2(i,:);%循環下去求最佳個體
        bestfit=newfitvalue(i);%循環下去求最佳適應度
    end
end

祝你科研順利

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