您的位置:首页 > 其它

遗传算法解决函数优化问题

2012-11-02 20:18 99 查看
原文链接:https://www.geek-share.com/detail/2562858680.html

一、实验目的

1.掌握遗传算法的基本原理和步骤。

2. 复习VB、VC的基本概念、基本语法和编程方法,并熟练使用VB或VC编写遗传算法程序。

二、实验内容

1. 上机编写程序,解决以下函数优化问题:

 

2. 调试程序。

3. 根据实验结果,撰写实验报告。

三、实验原理

遗传算法是一类随机优化算法,但它不是简单的随机比较搜索,而是通过对染色体的评价和对染色体中基因的作用,有效地利用已有信息来指导搜索有希望改善优化质量的状态。

标准遗传算法流程图如下图所示,主要步骤可描述如下:

① 随机产生一组初始个体构成初始种群。

② 计算每一个体的适配值(fitness value,也称为适应度)。适应度值是对染色体(个体)进行评价的一种指标,是GA进行优化所用的主要信息,它与个体的目标值存在一种对应关系。

③ 判断算法收敛准则是否满足,若满足,则输出搜索结果;否则执行以下步骤。

④ 根据适应度值大小以一定方式执行复制操作(也称为选择操作)。

⑤ 按交叉概率pc执行交叉操作。

⑥ 按变异概率pm执行变异操作。

⑦ 返回步骤②。

 

图1.1 标准遗传算法流程图




代码实现::::::

 

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include<time.h>

#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
[n2+1],bitary0
[n2+1];//二进制
int src1
;

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
,i=0,j=0,k=0,count=0;//十进制
float show
;//表现型
float fit
,sumfit=0;//适应度
float pcopy
;//优胜劣汰,遗传到下一代的概率fit[i]/总和(fit[i])
float pacc
;//pcopy[i]累加概率值
float prand
;//随机产生N个0~1的下一代概率
int iselect;//根据概率选择到的个体序号
int new_select
;//根据概率选择到的个体
int new_T[next_t],new_M[next_m];
float min,min1;

printf("随机数(原始母体),表现型, 适配值\n");
srand( (unsigned)time(NULL) );
for(i=0;i<N;i++)
{
src[i]=rand()%32768; //rand()%201-100===>-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;i<N;i++)
{
pcopy[i]=fit[i]/sumfit;
printf("%f, ",pcopy[i]);
}
// 求选择(被复制)的累加概率,用于轮盘赌产生随机数区域,选择下一代个体
printf("\n遗传到下一代的累加概率\n");
pacc[0]=pcopy[0];
for(i=1;i<N;i++)
{
pacc[i]=pacc[i-1]+pcopy[i];
printf("%f, ",pacc[i]);
}

//每个src
都随机取其中一个pcopy,取得的值pcopy[i]跟pcopy概率大小有关
//模拟轮盘赌方式选择新一代
printf("\n\n新产生的第%d代,表现型, 适配值\n",count);
srand( (unsigned)time(NULL) );
for(i=0;i<N;i++)
{
prand[i]=(float)( (rand()%101)*0.01 );//0~1的十进制小数 ,精确到0.01
iselect=selectT(prand[i],pacc);
new_select[i]=src[iselect];//产生的新一代,十进制
show[i]=ShowType(new_select[i]);//转化成表现型
fit[i]=fit_func(show[i]);
DecToBin (new_select[i],i);
sumfit=sumfit+fit[i];  //种群的适应度总和
printf(" %d  %f   %f\n",new_select[i],show[i],fit[i]);
}
printf("\n第%d代适配总值\n%f\n",count,sumfit);//第1代
min1=sumfit;
if (min>sumfit)
{
min1=min;
min=sumfit;
}

while(fabs(min-min1)>e&&count<MAX)
{
//从新一代选择个体交叉
printf("\n随机产生交叉个体号   ");
srand( (unsigned)time(NULL) );

for(i=0;i<2;i++)    //简单起见交叉数设为2
{
new_T[i]=rand()%N;//0~10的十进制数	产生的交叉个体
if (i>0)//两个不同个体交叉
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<n2+1;i++)//交叉
{
temp=bitary[new_T[0]][i];
bitary[new_T[0]][i]=bitary[new_T[1]][i];
bitary[new_T[1]][i]=temp;
}
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随机产生变异个体号  ");
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<N;i++)
{
for(j=n2;j>=0;j--)
printf("%c",bitary[i][j]);
printf("\n");
}
BinToDec ();//二进制转十进制
for(i=0;i<N;i++)
{
new_select[i]=src1[i];
show[i]=ShowType(src[i]);//转化成表现型
fit[i]=fit_func(show[i]);//计算各个适配值(适应度)
sumfit=sumfit+fit[i];  //种群的适应度总和
printf("%5d,  %f,  %f\n",src1[i],show[i],fit[i]);
}
printf("\n第%d代适配总值\n%f\n",count,sumfit);
if (sumfit<min)
{
min1=min;
min=sumfit;
}
}
printf("\n\n\n*****************\n    over   \n*****************\n",sumfit);
}

//////////////////////////子函数////////////////
float ShowType(int a)
{
float temp;
temp=(float)(a*200.0/32767-100);//(2的15次方减1)=32767
return temp;
}

float fit_func(float a)
{
float temp;
temp=a*a;
return temp;
}

void DecToBin (int src,int num)
{
int i;
//注意负数的补码
if (src<0)
{
src=(int)pow(2,16)-abs(src);
}
for (i=0;i<=n2;i++)
{
bitary[num][i]='0';
bitary0[num][i]='0';
if(src)
{
bitary[num][i]=(src%2)+48;
bitary0[num][i]=(src%2)+48;
src=(int)(src/2);
}
}
}

void BinToDec (void)
{
int i,j;
for(i=0;i<N;i++)
{
src1[i]=0;
for(j=0;j<n2+1;j++)
{
src1[i]=src1[i]+(bitary[i][j]-48)*(int)pow(2,j);
}
}
}

int selectT(float a,float b[10])
{
int i;
for(i=0;i<N;i++)
{
if (a<b[i])
return i;
}
return -1;
}


 

转载于:https://www.cnblogs.com/zhujinghui/archive/2012/11/02/3369247.html

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: