一、实验目的
1.掌握遗传算法的基本原理和步骤。
2. 复习VB、VC的基本概念、基本语法和编程方法,并熟练使用VB或VC编写遗传算法程序。
二、实验内容
1. 上机编写程序,解决以下函数优化问题:
2. 调试程序。
3. 根据实验结果,撰写实验报告。
三、实验原理
遗传算法是一类随机优化算法,但它不是简单的随机比较搜索,而是通过对染色体的评价和对染色体中基因的作用,有效地利用已有信息来指导搜索有希望改善优化质量的状态。
标准遗传算法流程图如下图所示,主要步骤可描述如下:
① 随机产生一组初始个体构成初始种群。
② 计算每一个体的适配值(fitness value,也称为适应度)。适应度值是对染色体(个体)进行评价的一种指标,是GA进行优化所用的主要信息,它与个体的目标值存在一种对应关系。
③ 判断算法收敛准则是否满足,若满足,则输出搜索结果;否则执行以下步骤。
④ 根据适应度值大小以一定方式执行复制操作(也称为选择操作)。
⑤ 按交叉概率pc执行交叉操作。
⑥ 按变异概率pm执行变异操作。
⑦ 返回步骤②。
图1.1 标准遗传算法流程图
代码实现::::::
#include
#include
#include
#include
#define byte unsigned char
#define step 200 //步长
#define MAX 50
#define N 10 //随机数个数
#define Pc 0.74 //被选择到下一代的概率,个数=Pc*N,小于N 下一代数=上一代,不用处理
#define Pt 0.25 //交叉的概率,个数=Pt*N 舍,小于N 0~(n2+1)随机数,之后部分开始交叉
#define Pm 0.01 //变异的概率,个数=Pm*N*n2 入,小于N 0~(N*(n2+1))随机数/(n2+1)=个体,0~(N*(n2+1))随机数%(n2+1)=该个体基因位置
#define n2 15//2的15次方,共16位
#define next_t (int)(Pt*N)//交叉个数
#define next_m (int)(Pm*N+1)//变异个数 向后约等于
#define e 0.001//次数限制阈值
/*
int N=10; //随机数个数
float Pc=0.74; //被选择到下一代的概率,个数=Pc*N,小于N 下一代数=上一代,不用处理
float Pt=0.25; //交叉的概率,个数=Pt*N 舍,小于N 0~(n2+1)随机数,之后部分开始交叉
float Pm=0.01; //变异的概率,个数=Pm*N*n2 入,小于N 0~(N*(n2+1))随机数/(n2+1)=个体,0~(N*(n2+1))随机数%(n2+1)=该个体基因位置
*/
byte bitary[N][n2+1],bitary0[N][n2+1];//二进制
int src1[N];
float ShowType(int a);//表现型
void BinNum(int a);//二进制位数n2
float fit_func(float a);//适应度
void DecToBin (int src,int num);//十进制转二进制
void BinToDec (void);//十进制转二进制
int selectT(float a,float b[10]);//选择交叉个体
int selectM(float a,float b[10]);//选择变异个体
void main(void)
{
//范围是[-100,100]***************************
int src[N],i=0,j=0,k=0,count=0;//十进制
float show[N];//表现型
float fit[N],sumfit=0;//适应度
float pcopy[N];//优胜劣汰,遗传到下一代的概率fit[i]/总和(fit[i])
float pacc[N];//pcopy[i]累加概率值
float prand[N];//随机产生N个0~1的下一代概率
int iselect;//根据概率选择到的个体序号
int new_select[N];//根据概率选择到的个体
int new_T[next_t],new_M[next_m];
float min,min1;
printf("随机数(原始母体),表现型, 适配值\n");
srand( (unsigned)time(NULL) );
for(i=0;i-100~100的十进制随机数 随时间递增
show[i]=ShowType(src[i]);//转化成表现型
fit[i]=fit_func(show[i]);//计算各个适配值(适应度)
sumfit=sumfit+fit[i]; //种群的适应度总和
printf("%5d, %f, %f\n",src[i],show[i],fit[i]);
}
printf("\n第%d代适配总值\n%f\n",count,sumfit);//第0代
count++;
min=sumfit;
printf("\n遗传到下一代的概率\n");
for(i=0;isumfit)
{
min1=min;
min=sumfit;
}
while(fabs(min-min1)>e&&count0)//两个不同个体交叉
while(new_T[i]==new_T[i-1])
new_T[i]=rand()%N;
printf("%d, ",new_T[i]);
}
srand( (unsigned)time(NULL) );//随机产生交叉位置
k=rand()%n2;//0~14的十进制数
printf("\n随机产生交叉位置 %d\n",k);
printf("\n原编码\n");
for(j=n2;j>=0;j--)
printf("%c",bitary[new_T[0]][j]);
printf("\n");
for(j=n2;j>=0;j--)
printf("%c",bitary[new_T[1]][j]);
printf("\n位置%d后交叉编码\n",k);
char temp;
for(i=k+1;i=0;j--)
printf("%c",bitary[new_T[0]][j]);
printf("\n");
for(j=n2;j>=0;j--)
printf("%c",bitary[new_T[1]][j]);
//从新一代选择个体变异
printf("\n随机产生变异个体号 ");
srand( (unsigned)time(NULL) );
for(i=0;i<1;i++) //简单起见变异数设为1个
{
new_M[i]=rand()%N;//0~9的十进制数 产生的变异个体
k=rand()%(n2+1);//0~15的十进制数
printf("%d\n编码位置 %d\n原编码\n",new_M[i],k);
for(j=n2;j>=0;j--)
printf("%c",bitary[new_M[i]][j]);
if (bitary[new_M[i]][k]=='0')//变异取反
bitary[new_M[i]][k]='1';
else bitary[new_M[i]][k]='0';
printf("\n位置%d变异后编码\n",k);
for(j=n2;j>=0;j--)
printf("%c",bitary[new_M[i]][j]);
}
printf("\n");
count++;
//新的bitary即产生第二代
printf("\n新产生的第%d代\n",count);
for(i=0;i=0;j--)
printf("%c",bitary[i][j]);
printf("\n");
}
BinToDec ();//二进制转十进制
for(i=0;i