遺傳演算法解決TSP問題
遺傳演算法(Genetic Algorithm)是模擬達爾文生物進化論的自然選擇和遺傳學機理的生物進化過程的計算模型,是一種通過模擬自然進化過程搜尋最優解的方法
遺傳演算法的基本運算過程如下:
a)初始化:設定進化代數計數器t=0,設定最大進化代數T,隨機生成M個個體作為初始群體P(0)。
b)個體評價:計算群體P(t)中各個個體的適應度。
c)選擇運算:將選擇運算元作用於群體。選擇的目的是把優化的個體直接遺傳到下一代或通過配對交叉產生新的個體再遺傳到下一代。選擇操作是建立在群體中個體的適應度評估基礎上的。
d)交叉運算:將交叉運算元作用於群體。所謂交叉是指把兩個父代個體的部分結構加以替換重組而生成新個體的操作。遺傳演算法中起核心作用的就是交叉運算元。
e)變異運算:將變異運算元作用於群體。即是對群體中的個體串的某些基因座上的基因值作變動。
群體P(t)經過選擇、交叉、變異運算之後得到下一代群體P(t 1)。
f)終止條件判斷:若t=T,則以進化過程中所得到的具有最大適應度個體作為最優解輸出,終止計算。
下面用C語言模擬遺傳演算法模擬TSP問題
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;
}
轉載:
http://blog.csdn.net/mylovestart/article/details/8977005
相關文章
- 遺傳演算法解決旅行商問題(TSP)演算法
- 遺傳演算法求解TSP問題(python版)演算法Python
- 遺傳演算法解決函式最佳化問題演算法函式
- 利用遺傳學演算法求解工作分配問題演算法
- python遺傳演算法(詳解)Python演算法
- 旅行商問題(TSP)概述
- 蟻群演算法介紹(以TSP問題為例)演算法
- 遺傳演算法演算法
- 基於免疫演算法的TSP問題求解matlab模擬演算法Matlab
- 遺傳演算法詳解與實驗演算法
- 蟻群演算法java實現以及TSP問題蟻群演算法求解演算法Java
- 元件複用傳值(待解決問題)元件
- 遺傳演算法的基本框架演算法框架
- 遺傳演算法(一):Basic GA演算法
- WannaCry兩年後捲土重來,NSA遺留問題尚未解決
- [文件教程]解決sae下文件縮圖上傳問題及外掛上傳問題
- 10分鐘搞懂遺傳演算法演算法
- 人工智慧 (13) 遺傳演算法人工智慧演算法
- 如何學習python遺傳演算法?Python演算法
- 普利姆演算法解決最短修路問題演算法
- 解決CORS跨域不能傳遞cookies的問題CORS跨域Cookie
- 解決alertmanager重複傳送訊息的問題
- 遺傳演算法組卷使用心得演算法
- 使用貪心演算法解決集合覆蓋問題演算法
- 解決jenkins 傳送郵件圖片亂碼問題Jenkins
- vue 新增axios解決post傳引數為null問題VueiOSNull
- 粒子群演算法和遺傳演算法的比較演算法
- 用遺傳演算法進行特徵選擇演算法特徵
- Unity中利用遺傳演算法訓練MLPUnity演算法
- post傳引數,但是後端無法接收問題解決後端
- 煉成爆款小遊戲-首先解決傳播問題遊戲
- 提問題比解決問題更重要
- 解決跨域問題跨域
- SERVICE問題解決方法
- 解決 Unexpectedlexicaldeclarationincaseblock的問題BloC
- 解決mapper重名問題APP
- qeephp 解決跨越問題PHP
- 解決高度塌陷問題