#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#define M 80 //种群数量
#define LEN 20 //编码长度
#define xmin -1 //下限
#define xmax 2 //上限
#define MMAX (int)pow(2,LEN)//编码长度对应的最大二进制数
#define PI 3.1415926
#define PC 0.8 //交叉概率
#define PM 0.05 //变异概率
#define PD 0.2
struct Node
{
int num,MyBinary[LEN]; //num是对应二进制编码的整数值,MyBinary存放二进制编码
double Myfitness; //Myfitness是适应度
double Myfitsum; //Myfitsum是适应度占总体适应度的百分比,然后从第一个个体往后累加,主要用于选择操作
}Nownode[M],Nextnode[M]; //本代群体和下一代群体
int nodeindex[M]; //交叉时随机配对,存放配对的群体下标
int T;
double fx(double x) //被优化函数
{
double y;
y=x*sin(10*PI*x)+2;
//y=6-pow(x+6,2);
//y=sin(0.7*x)/x;
return y;
}
int randn(int temp)//产生0~MMAX之间的随机整数
{
return (int)(1.0*rand()/RAND_MAX*temp+0.5);
}
double double2double(struct Node node)//把对应的二进制数转化为对应区间的double数
{
return xmin+node.num*(xmax-xmin)/(pow(2,LEN)-1);
}
int calfitness() //计算适应度
{
int i;
double temp,temp_sum=0,minfitness,maxfitness,avefitness;//minfitness作用是如果出现负的适应度,就做相应的变化
double a,b,C=1.5;
for(i=0;i<M;i++)
{
temp=double2double(Nownode[i]);
Nownode[i].Myfitness=fx(temp);
temp_sum+=Nownode[i].Myfitness;
if(i==0)
{
minfitness=Nownode[i].Myfitness;//i=0时,先给minfitness赋初值
maxfitness=Nownode[i].Myfitness;
}
if(minfitness>Nownode[i].Myfitness)
{
minfitness=Nownode[i].Myfitness;
}
if(maxfitness<Nownode[i].Myfitness)
{
maxfitness=Nownode[i].Myfitness;
}
}
if(minfitness<0)//如果有负的适应度值,就把所以的适应度都加上一个数,使适应度全都为正数
{
temp_sum=0;
for(i=0;i<M;i++)
{
Nownode[i].Myfitness+=-minfitness;
temp_sum+=Nownode[i].Myfitness;
}
}
//适应度线性变换
avefitness=temp_sum/M;//计算平均适应度
if(minfitness>(C*avefitness-maxfitness)/(C-1))
{
a=(C-1)*avefitness/(maxfitness-avefitness);
b=(maxfitness-C*avefitness)*avefitness/(maxfitness-avefitness);
}
else
{
a=avefitness/(avefitness-minfitness);
b=minfitness*avefitness/(avefitness-minfitness);
}
for(i=0;i<M;i++)
{
Nownode[i].Myfitness=a*Nownode[i].Myfitness+b;
}
Nownode[0].Myfitsum=Nownode[0].Myfitness;
for(i=1;i<M;i++)
{
Nownode[i].Myfitsum=Nownode[i].Myfitness+Nownode[i-1].Myfitsum;//每一个Myfitsum都是自己的适应度加上前一个的Myfitsum
}
for(i=0;i<M;i++)
{
Nownode[i].Myfitsum=Nownode[i].Myfitsum/Nownode[M-1].Myfitsum;//每一个Myfitsum除以所有适应度之和,使Myfitsum为0~1之间
}
return 0;
}
int initpopulation()//初始化种群
{
int i,j,temp;
for(i=0;i<M;i++)
{
temp=randn(MMAX); //产生0~MMAX之间的随机整数值
Nownode[i].num=temp;
//printf("%d\n",temp);
for(j=LEN-1;j>=0;j--)
{
Nownode[i].MyBinary[j]=temp%2;//给MyBinary赋值
temp=temp/2;
}
}
calfitness();//计算适应度
return 0;
}
int assignment(struct Node *node1,struct Node *node2)//两个个体之间赋值操作,所以这里必须使用指针,
{
int j;
for(j=0;j<LEN;j++)
{
node1->MyBinary[j]=node2->MyBinary[j];
}
node1->num=node2->num;
node1->Myfitness=node2->Myfitness;
node1->Myfitsum=node2->Myfitsum;
return 0;
}
int copypopulation()//选择(复制)操作
{
int i,num=0;
double temp;
while(num<M)
{
temp=1.0*rand()/RAND_MAX;//随机生成一个0~1之间的数
for(i=1;i<M;i++)
{
if(temp>=Nownode[i-1].Myfitsum&&temp<=Nownode[i].Myfitsum)
{
//Nextnode[num++]=Nownode[i];
assignment(&Nextnode[num++],&Nownode[i]);//如果满足条件就赋值给下一代
break;
}
}
}
for(i=0;i<M;i++)
{
//Nownode[i]=Nextnode[i];
assignment(&Nownode[i],&Nextnode[i]);//更新本代个体
}
calfitness();//计算适应度
return 0;
}
int isrepeat(int temp,int num)//交叉时要随机分组,防止出现重复的两个数,此函数检测是否下标重复
{
int i;
for(i=0;i<num;i++)
{
if(nodeindex[i]==temp)
return 1;
}
return 0;
}
int bin2int(struct Node *node)//把对应的编码转化为整数值
{
int j,num=0;;
for(j=0;j<LEN;j++)
{
num+=(int)(pow(2,LEN-1-j)*(node->MyBinary[j]));
}
node->num=num;
return num;
}
int crossposition(struct Node *node1,struct Node *node2,int p)//交叉操作,交叉点为p,参数必须是指针
{
int j,temp;
for(j=LEN-1;j>=LEN-1-p;j--)
{
temp=node1->MyBinary[j];
node1->MyBinary[j]=node2->MyBinary[j];//交换两个个体的编码
node2->MyBinary[j]=temp;
}
bin2int(node1);//交叉完成后更新num值
bin2int(node2);
return 1;
}
int crossover()
{
int i,temp;
double pc_temp;
for(i=0;i<M;i++)
{
do
{
temp=rand()%M;
} while(isrepeat(temp,i));
nodeindex[i]=temp;//首先产生了交叉的下标
}
for(i=0;i<M;i=i+2)
{
temp=rand()%(LEN-1);
pc_temp=1.0*rand()/RAND_MAX;
if(pc_temp<=PC)//满足交叉条件就交叉
{
crossposition(&Nownode[nodeindex[i]],&Nownode[nodeindex[i+1]],temp);
}
}
calfitness();//计算适应度
return 1;
}
int mutation()//变异操作
{
int i,j;
double pm_temp;
for(i=0;i<M;i++)
{
for(j=0;j<LEN;j++)
{
pm_temp=1.0*rand()/RAND_MAX;
if(pm_temp<=PM)//满足变异概率就进行变异操作
{
Nownode[i].MyBinary[j]=(Nownode[i].MyBinary[j]==0)?1:0;
}
}
bin2int(&Nownode[i]);//更新个体的num值
}
calfitness();//计算适应度
return 1;
}
int findmaxfit()//找到适应度最大的个体
{
int i,index=0;
double temp=0;
for(i=0;i<M;i++)
{
if(temp<Nownode[i].Myfitness)
{
index=i;
temp=Nownode[i].Myfitness;
}
}
return index;
}
int displaynode()
{
int i,j;
printf("\n\n下标\tnum值\tx值\t 编码\t\tMyfitness\tMyfitsum\n");
for(i=0;i<M;i++)
{
printf("第%d个\t%d\t%.3lf\t",i,Nownode[i].num,double2double(Nownode[i]));
for(j=0;j<LEN;j++)
{
printf("%d",Nownode[i].MyBinary[j]);
}
printf("\t%.3lf\t\t%.3lf\n",Nownode[i].Myfitness,Nownode[i].Myfitsum);
}
return 1;
}
int main()
{
int index;
int num=0,num1=0,num2=0;
srand(time(NULL));
while(num++<100)
{
T=0;
initpopulation();//初始化群体
while(T++<=100)
{
copypopulation();
crossover();
mutation();
}
index=findmaxfit();
if(fabs(double2double(Nownode[index])-1.8)<=0.1)
{
num1++;
}
else
{
num2++;
}
}
printf("正确的结果次数有%d次\n",num1);
printf("错误的结果次数有%d次\n",num2);
return 0;
}
根据结果可知,计算结果正确的概率在98%以上。