遺傳算法(Genetic Algorithm)是模擬達爾文生物進化論的天然選擇和遺傳學機理的生物進化過程的計算模型,是一種經過模擬天然進化過程搜索最優解的方法算法
遺傳算法的基本運算過程以下:函數
a)初始化:設置進化代數計數器t=0,設置最大進化代數T,隨機生成M個個體做爲初始羣體P(0)。測試
b)個體評價:計算羣體P(t)中各個個體的適應度。優化
c)選擇運算:將選擇算子做用於羣體。選擇的目的是把優化的個體直接遺傳到下一代或經過配對交叉產生新的個體再遺傳到下一代。選擇操做是創建在羣體中個體的適應度評估基礎上的。spa
d)交叉運算:將交叉算子做用於羣體。所謂交叉是指把兩個父代個體的部分結構加以替換重組而生成新個體的操做。遺傳算法中起核心做用的就是交叉算子。code
e)變異運算:將變異算子做用於羣體。便是對羣體中的個體串的某些基因座上的基因值做變更。orm
羣體P(t)通過選擇、交叉、變異運算以後獲得下一代羣體P(t 1)。ip
f)終止條件判斷:若t=T,則以進化過程當中所獲得的具備最大適應度個體做爲最優解輸出,終止計算。ci
下面用C語言模擬遺傳算法模擬TSP問題string
TSP問題及旅行商問題,假設有一個旅行商人要拜訪n個城市,他必須選擇所要走的路徑,路徑的限制是每一個城市只能拜訪一次,並且最後要回到原來出發的城市。路徑的選擇目標是要求得的路徑路程爲全部路徑之中的最小值
交叉的算法以下圖
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> #include<time.h> #define cities 10 //城市的個數 #define MAXX 100//迭代次數 #define pc 0.8 //交配機率 #define pm 0.05 //變異機率 #define num 10//種羣的大小 int bestsolution;//最優染色體 int distance[cities][cities];//城市之間的距離 struct group //染色體的結構 { int city[cities];//城市的順序 int adapt;//適應度 double p;//在種羣中的倖存機率 }group[num],grouptemp[num]; //隨機產生cities個城市之間的相互距離 void init() { int i,j; memset(distance,0,sizeof(distance)); srand((unsigned)time(NULL)); for(i=0;i<cities;i++) { for(j=i+1;j<cities;j++) { distance[i][j]=rand()%100; distance[j][i]=distance[i][j]; } } //打印距離矩陣 printf("城市的距離矩陣以下\n"); for(i=0;i<cities;i++) { for(j=0;j<cities;j++) printf("%4d",distance[i][j]); printf("\n"); } } //隨機產生初試羣 void groupproduce() { int i,j,t,k,flag; for(i=0;i<num;i++) //初始化 for(j=0;j<cities;j++) group[i].city[j]=-1; srand((unsigned)time(NULL)); for(i=0;i<num;i++) { //產生10個不相同的數字 for(j=0;j<cities;) { t=rand()%cities; flag=1; for(k=0;k<j;k++) { if(group[i].city[k]==t) { flag=0; break; } } if(flag) { group[i].city[j]=t; j++; } } } //打印種羣基因 printf("初始的種羣\n"); for(i=0;i<num;i++) { for(j=0;j<cities;j++) printf("%4d",group[i].city[j]); printf("\n"); } } //評價函數,找出最優染色體 void pingjia() { int i,j; int n1,n2; int sumdistance,biggestsum=0; double biggestp=0; for(i=0;i<num;i++) { sumdistance=0; for(j=1;j<cities;j++) { n1=group[i].city[j-1]; n2=group[i].city[j]; sumdistance+=distance[n1][n2]; } group[i].adapt=sumdistance; //每條染色體的路徑總和 biggestsum+=sumdistance; //種羣的總路徑 } //計算染色體的倖存能力,路勁越短生存機率越大 for(i=0;i<num;i++) { group[i].p=1-(double)group[i].adapt/(double)biggestsum; biggestp+=group[i].p; } for(i=0;i<num;i++) group[i].p=group[i].p/biggestp; //在種羣中的倖存機率,總和爲1 //求最佳路勁 bestsolution=0; for(i=0;i<num;i++) if(group[i].p>group[bestsolution].p) bestsolution=i; //打印適應度 for(i=0;i<num;i++) printf("染色體%d的路徑之和與生存機率分別爲%4d %.4f\n",i,group[i].adapt,group[i].p); printf("當前種羣的最優染色體是%d號染色體\n",bestsolution); } //選擇 void xuanze() { int i,j,temp; double gradient[num];//梯度機率 double xuanze[num];//選擇染色體的隨機機率 int xuan[num];//選擇了的染色體 //初始化梯度機率 for(i=0;i<num;i++) { gradient[i]=0.0; xuanze[i]=0.0; } gradient[0]=group[0].p; for(i=1;i<num;i++) gradient[i]=gradient[i-1]+group[i].p; srand((unsigned)time(NULL)); //隨機產生染色體的存活機率 for(i=0;i<num;i++) { xuanze[i]=(rand()%100); xuanze[i]/=100; } //選擇能生存的染色體 for(i=0;i<num;i++) { for(j=0;j<num;j++) { if(xuanze[i]<gradient[j]) { xuan[i]=j; //第i個位置存放第j個染色體 break; } } } //拷貝種羣 for(i=0;i<num;i++) { grouptemp[i].adapt=group[i].adapt; grouptemp[i].p=group[i].p; for(j=0;j<cities;j++) grouptemp[i].city[j]=group[i].city[j]; } //數據更新 for(i=0;i<num;i++) { temp=xuan[i]; group[i].adapt=grouptemp[temp].adapt; group[i].p=grouptemp[temp].p; for(j=0;j<cities;j++) group[i].city[j]=grouptemp[temp].city[j]; } //用於測試 /* printf("<------------------------------->\n"); for(i=0;i<num;i++) { for(j=0;j<cities;j++) printf("%4d",group[i].city[j]); printf("\n"); printf("染色體%d的路徑之和與生存機率分別爲%4d %.4f\n",i,group[i].adapt,group[i].p); } */ } //交配,對每一個染色體產生交配機率,知足交配率的染色體進行交配 void jiaopei() { int i,j,k,kk; int t;//參與交配的染色體的個數 int point1,point2,temp;//交配斷點 int pointnum; int temp1,temp2; int map1[cities],map2[cities]; double jiaopeip[num];//染色體的交配機率 int jiaopeiflag[num];//染色體的可交配狀況 for(i=0;i<num;i++)//初始化 jiaopeiflag[i]=0; //隨機產生交配機率 srand((unsigned)time(NULL)); for(i=0;i<num;i++) { jiaopeip[i]=(rand()%100); jiaopeip[i]/=100; } //肯定能夠交配的染色體 t=0; for(i=0;i<num;i++) { if(jiaopeip[i]<pc) { jiaopeiflag[i]=1; t++; } } t=t/2*2;//t必須爲偶數 //產生t/2個0-9交配斷點 srand((unsigned)time(NULL)); temp1=0; //temp1號染色體和temp2染色體交配 for(i=0;i<t/2;i++) { point1=rand()%cities; point2=rand()%cities; for(j=temp1;j<num;j++) if(jiaopeiflag[j]==1) { temp1=j; break; } for(j=temp1+1;j<num;j++) if(jiaopeiflag[j]==1) { temp2=j; break; } //進行基因交配 if(point1>point2) //保證point1<=point2 { temp=point1; point1=point2; point2=temp; } memset(map1,-1,sizeof(map1)); memset(map2,-1,sizeof(map2)); //斷點之間的基因產生映射 for(k=point1;k<=point2;k++) { map1[group[temp1].city[k]]=group[temp2].city[k]; map2[group[temp2].city[k]]=group[temp1].city[k]; } //斷點兩邊的基因互換 for(k=0;k<point1;k++) { temp=group[temp1].city[k]; group[temp1].city[k]=group[temp2].city[k]; group[temp2].city[k]=temp; } for(k=point2+1;k<cities;k++) { temp=group[temp1].city[k]; group[temp1].city[k]=group[temp2].city[k]; group[temp2].city[k]=temp; } //處理產生的衝突基因 for(k=0;k<point1;k++) { for(kk=point1;kk<=point2;kk++) if(group[temp1].city[k]==group[temp1].city[kk]) { group[temp1].city[k]=map1[group[temp1].city[k]]; break; } } for(k=point2+1;k<cities;k++) { for(kk=point1;kk<=point2;kk++) if(group[temp1].city[k]==group[temp1].city[kk]) { group[temp1].city[k]=map1[group[temp1].city[k]]; break; } } for(k=0;k<point1;k++) { for(kk=point1;kk<=point2;kk++) if(group[temp2].city[k]==group[temp2].city[kk]) { group[temp2].city[k]=map2[group[temp2].city[k]]; break; } } for(k=point2+1;k<cities;k++) { for(kk=point1;kk<=point2;kk++) if(group[temp2].city[k]==group[temp2].city[kk]) { group[temp2].city[k]=map2[group[temp2].city[k]]; break; } } temp1=temp2+1; } } //變異 void bianyi() { int i,j; int t; int temp1,temp2,point; double bianyip[num]; //染色體的變異機率 int bianyiflag[num];//染色體的變異狀況 for(i=0;i<num;i++)//初始化 bianyiflag[i]=0; //隨機產生變異機率 srand((unsigned)time(NULL)); for(i=0;i<num;i++) { bianyip[i]=(rand()%100); bianyip[i]/=100; } //肯定能夠變異的染色體 t=0; for(i=0;i<num;i++) { if(bianyip[i]<pm) { bianyiflag[i]=1; t++; } } //變異操做,即交換染色體的兩個節點 srand((unsigned)time(NULL)); for(i=0;i<num;i++) { if(bianyiflag[i]==1) { temp1=rand()%10; temp2=rand()%10; point=group[i].city[temp1]; group[i].city[temp1]=group[i].city[temp2]; group[i].city[temp2]=point; } } } int main() { int i,j,t; init(); groupproduce(); //初始種羣評價 pingjia(); t=0; while(t++<MAXX) { xuanze(); //jiaopei(); bianyi(); pingjia(); } //最終種羣的評價 printf("\n輸出最終的種羣評價\n"); for(i=0;i<num;i++) { for(j=0;j<cities;j++) { printf("%4d",group[i].city[j]); } printf(" adapt:%4d, p:%.4f\n",group[i].adapt,group[i].p); } printf("最優解爲%d號染色體\n",bestsolution); return 0; }
結果: