700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 启发式算法之遗传算法--求解组合优化问题

启发式算法之遗传算法--求解组合优化问题

时间:2020-11-07 07:07:27

相关推荐

启发式算法之遗传算法--求解组合优化问题

本文为原创文章,如有任何疑问请留言

遗传算法是一种全局、概率搜索算法,主要用于求解大规模旅行商问题、路径规划问题、任务调度等NP-hard问题。

遗传算法属于进化算法,首先将需要求解的自变量通过编码形成染色体,在遗传过程中通过交叉、变异等操作产生新个体,选择种群中较优的个体遗传到下一代,不断进化,直到达到遗传终止条件为止。

本文以一个小规模的两两组合优化问题为例对遗传算法的流程进行简要介绍。问题:一个仓库有5个包裹需要运输至5个不同的目的地,每辆运输车最多运输两件包裹,求解最佳的组合运输方案。

(1)遗传编码。问题属于路径规划组合优化问题,每个问题当且仅当执行一次,因此,选择任务序号作为基因进行编码产生染色体。

(2)初始解生成。启发式算法初始解的质量直接影响算法收敛速度,因此一般使用一些简单优化方法产生初始解,种群大小一般取经验值20-100。本文使用随机方法产生初始解,种群大小20,例如:个体1:23415,个体2:13245………………个体20:54321.

(3)选择。选择较优个体遗传到下一代,一般使用轮盘赌的方法,多目标时可能选择帕累托法等。选择时需要计算个体的适应值,路径规划问题一般为距离最短或时间最短,使用轮盘赌时需要将最小化问题转换为最大化问题,因此需要引入常数计算适值。

(4)交叉。常用交叉方法有单点交叉、多点交叉和部分映射交叉等。本文使用单点交叉,交叉后可能会产生非法解,需要将个体染色体合法化。

(5)变异。变异一般使用单点变异或交换变异,同样在变异后需要合法化个体染色体。

下面为遗传算法详细C语言代码,编程技术有限,仅供初学者参考,也可在matlab等软件中直接调用算法包实现问题求解。

#include<stdio.h>#include<math.h>#include<stdlib.h>#include<time.h>#define s 5 /* 随机数个数 */ #define c 10 /* 染色体长度 */#define add 5 /* 节点数 */void quchong(); //合法化函数int maxgen;/* 最大遗传代数 */ int maxruns;/* 最大运行次数 */ float Pc; /* 交叉概率 */ float Pm; /* 变异概率 */ float rf; /* 随机浮点数 */ int ri; /* 随机整数 */ int nc; /* 交叉次数 */ int nm; /* 变异次数 */ int a[add]; /* 初始序列12345 */ int b[s]; /* 随机数数列 */FILE *fp; //文件指针int road[6][6]={{0,738,749,710,520,712}, /* 路径地图 */ {738,0,790,772,870,583},{749,790,0,885,598,615},{710,772,885,0,513,607},{520,870,598,513,0,508},{712,583,615,607,508,0}};int ncar=4; /* 车数量 */ struct individual /* 父代0-1,子代2-3 */{int chrom[c];int fitness;}father[4];struct best /* 最佳个体 */{int chrom[c];int fitness;int generation; }bestfit;void random()/* 随机数生成函数 */{ int i;for(i=0;i<s;i++)b[i]=rand()%(add-1);}void change()/* 数列随机调换顺序函数 */ {int i,temp,j;for(i=0;i<s;i++)a[i]=i+1;for(i=0;i<s;i++){temp=a[b[i]]; /* 与后一位交换位置 */a[b[i]]=a[b[i]+1];a[b[i]+1]=temp;}}void initial()/* 父代染色体生成函数 */{int i,j;for(i=0;i<c;i++){father[0].chrom[i]=0;father[1].chrom[i]=0;father[2].chrom[i]=0;father[3].chrom[i]=0;}change();random();for(j=1,i=0;j<c-1;j=j+2,i++)father[0].chrom[j]=a[i];father[0].chrom[c-2]=a[s-1];change();random();for(j=1,i=0;j<c-1;j=j+2,i++)father[1].chrom[j]=a[i];father[1].chrom[c-2]=a[s-1];}void fitness(){int i,j,k;int sum;for(i=0;i<4;i++)father[i].fitness=0;for(j=0;j<4;j++){sum=0;for(i=1;i<c-2;i++){if(father[j].chrom[i]!=0){if(father[j].chrom[i-1]==0&&father[j].chrom[i+1]==0)sum=sum+2*road[father[j].chrom[i]][0];if(father[j].chrom[i-1]==0&&father[j].chrom[i+1]!=0) {sum=sum+road[0][father[j].chrom[i]]+road[father[j].chrom[i]][father[j].chrom[i+1]]+road[0][father[j].chrom[i+1]];i++;}}} father[j].fitness=sum;}} void randomf()/* 浮点数生成函数 */{int rn;rn=rand()%100;rf=rn;rf=rf/100;} void cross(){int i,j,k,temp; randomf();if(rf<=Pc){for(i=0;i<2;i++) /* 复制 */ {for(j=0;j<c;j++)father[i+2].chrom[j]=father[i].chrom[j];} nc++; ri=rand()%5+4; for(j=ri;j<9;j++) /* 交叉父代染色体 */ {temp=father[2].chrom[j];father[2].chrom[j]=father[3].chrom[j];father[3].chrom[j]=temp;} quchong();quchong();}}void quchong(){int i,j,k,q,temp;int flagg;int flag[2][add]={{0,0,0,0,0},{0,0,0,0,0}};int com[add]={1,2,3,4,5}; for(q=2;q<4;q++){for(i=0;i<c;i++)/* 统计flag1 */ {for(j=0;j<add;j++){if(father[q].chrom[i]==com[j])flag[q-2][j]++;}}for(i=0;i<add;i++)/* 去重子代1 */ {flagg=0; if(flag[q-2][i]==0){for(j=0;j<add;j++){if(flag[q-2][j]==2){for(k=0;k<c;k++){if(father[q].chrom[k]==com[j]){father[q].chrom[k]=com[i];flagg=1;break; } } }if(flagg==1)break;}}if(flagg==1)break; }} } void quchong1(int dai,int point){int i,j;int flagg;int flag[5]={0,0,0,0,0};int com[5]={1,2,3,4,5};for(i=0;i<c;i++)/* 统计flag */ {for(j=0;j<add;j++){if(father[dai].chrom[i]==com[j])flag[j]++;}}for(i=0;i<add;i++) /* 去重 */ {flagg=0;if(flag[i]==0){for(j=0;j<c;j++){if(j!=point){if(father[dai].chrom[j]==father[dai].chrom[point]){father[dai].chrom[j]=com[i];flagg=1;break;}}}}if(flagg==1)break;}}void mutation(){int i,j,k;int mp;/* 变异点 */ int mn; /* 变异数 */ for(i=2;i<4;i++){randomf();if(father[2].chrom[1]!=0){if(rf<Pm){nm++;mp=rand()%2+7;mn=rand()%5+1;father[i].chrom[mp]=mn;} }if(father[2].chrom[1]!=0) quchong1(i,mp);} } void select(){int i,j; for(i=2;i<4;i++){if(father[2].chrom[1]!=0){if(father[i].fitness<father[0].fitness||father[i].fitness<father[1].fitness){bestfit.generation++;if(father[0].fitness>father[1].fitness){for(j=1;j<c-1;j++)father[0].chrom[j]=father[i].chrom[j];father[0].fitness=father[i].fitness;}else{for(j=1;j<c-1;j++)father[1].chrom[j]=father[i].chrom[j];father[1].fitness=father[i].fitness;}}}}}void fselect(){int i;if(father[0].fitness<father[1].fitness){for(i=0;i<c;i++)bestfit.chrom[i]=father[0].chrom[i];bestfit.fitness=father[0].fitness;}else{for(i=0;i<c;i++)bestfit.chrom[i]=father[1].chrom[i];bestfit.fitness=father[1].fitness;}}void enter(){printf("请输入运行次数:"); scanf("%d",&maxruns);printf("请输入遗传代数:"); scanf("%d",&maxgen);printf("请输入交叉概率:"); scanf("%f",&Pc);printf("请输入变异概率:"); scanf("%f",&Pm);}void totaltime(){int i,j,k;int sum;int temp;sum=0;for(i=1;i<c-2;i++){if(bestfit.chrom[i]!=0){if(bestfit.chrom[i-1]==0&&bestfit.chrom[i+1]==0)sum=sum+2*timemap[bestfit.chrom[i]][0];if(bestfit.chrom[i-1]==0&&bestfit.chrom[i+1]!=0) {sum=sum+timemap[0][bestfit.chrom[i]]+timemap[bestfit.chrom[i]][bestfit.chrom[i+1]]+timemap[0][bestfit.chrom[i+1]];i++;}}} for(i=1;i<7;i=i+2){for(j=i+2;j<7;j=j+2){if(bestfit.chrom[j]<bestfit.chrom[i]){temp=bestfit.chrom[j];bestfit.chrom[j]=bestfit.chrom[i];bestfit.chrom[i]=temp;}}}fprintf(fp,"%d,",bestfit.fitness);fprintf(fp,"%d\n",sum);} void run(){int i,j,k;if((fp=fopen("shortestroadreport1.txt","w"))==NULL){printf("cannot open\n");exit(0);}enter(); for(i=1;i<=maxruns;i++){nc=0;nm=0;initial();for(j=1;j<=maxgen;j++){cross();mutation();fitness();select();fselect();}totaltime();}fclose(fp);} int main(){srand((unsigned)time(NULL));run();}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。