简易遗传算法(浮点数编码)

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

#define M 80				//种群数量
#define XMIN -1				//下限
#define XMAX 2				//上限
#define PI 3.1415926
#define PC 0.8				//交叉概率
#define PM 0.18				//变异概率
#define PA 0.01				//交叉因子

struct Node
{
	double Pmember;
	double Myfitness;		//Myfitness是适应度
	double Myfitsum;		//Myfitsum是适应度占总体适应度的百分比,然后从第一个个体往后累加,主要用于选择操作
	double Myfitave;
}Nownode[M],Nextnode[M];	//本代群体和下一代群体

int nodeindex[M];			//交叉时随机配对,存放配对的群体下标
int T=0;

double fx(double x)			//根据x计算fx
{
	double y;
	y=x*sin(10*PI*x)+2;
	//y=100-(x-5)*(x-5);
	return y;
}

int calfitness()			//计算适应度值
{
	int i;
	double minfitness,maxfitness,avefitness=0;
	double C=1.7,a,b;
	double temp;
	minfitness=Nownode[0].Myfitness=fx(Nownode[0].Pmember);
	maxfitness=minfitness;
	avefitness=maxfitness;
	for(i=1;i<M;i++)
	{	
		Nownode[i].Myfitness=fx(Nownode[i].Pmember);
		avefitness+=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=minfitness;
		Nownode[0].Myfitness+=-temp;
		avefitness=Nownode[0].Myfitness;
		maxfitness=Nownode[0].Myfitness;
		minfitness=Nownode[0].Myfitness;
		for(i=1;i<M;i++)
		{
			Nownode[i].Myfitness+=-temp;
			avefitness+=Nownode[i].Myfitness;
			if(minfitness>Nownode[i].Myfitness)
			{
				minfitness=Nownode[i].Myfitness;
			}
			if(maxfitness<Nownode[i].Myfitness)
			{
				maxfitness=Nownode[i].Myfitness;
			}	
		}
	}

	//适应度线性变换
	avefitness=avefitness/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].Myfitave=Nownode[M-1].Myfitsum/M;
	}
	

	for(i=0;i<M;i++)
	{
		Nownode[i].Myfitsum=Nownode[i].Myfitsum/Nownode[M-1].Myfitsum;//每一个Myfitsum除以所有适应度之和,使Myfitsum为0~1之间
	}
	return 0;
}

double randn()		//产生XMIN到XMAX之间的随机数
{
	return XMIN+1.0*rand()/RAND_MAX*(XMAX-XMIN);
}

int initpopulation()	//初始化种群
{
	int i;
	for(i=0;i<M;i++)
	{
		Nownode[i].Pmember=randn();
	}
	calfitness();		//计算适应度
	return 0;
}

int assignment(struct Node *node1,struct Node *node2)//把node2的值赋值给node1
{
	node1->Pmember=node2->Pmember;
	node1->Myfitness=node2->Myfitness;
	node1->Myfitsum=node2->Myfitsum;
	node1->Myfitave=node2->Myfitave;
	return 0;
}

int copypopulation()		//复制操作
{
	int i,num=0;
	double temp;
	while(num<M)
	{
		temp=1.0*rand()/RAND_MAX;
		for(i=1;i<M;i++)
		{
			if(temp<=Nownode[0].Myfitsum)
			{
				assignment(&Nextnode[num++],&Nownode[0]);//把第一个个体复制到下一代
				break;
			}
			if(temp>=Nownode[i-1].Myfitsum&&temp<=Nownode[i].Myfitsum)//把第i个个体复制到下一代
			{
				assignment(&Nextnode[num++],&Nownode[i]);
				break;
			}
		}
	}
	for(i=0;i<M;i++)
	{
		assignment(&Nownode[i],&Nextnode[i]);	//更新本代个体
	}
	calfitness();		//计算适应度
	return 0;
}

int isrepeat(int temp,int n)	//产生随机下标判断是否重复
{
	int i;
	for(i=0;i<n;i++)
	{
		if(nodeindex[i]==temp)
			return 1;
	}
	return 0;
}

int crossover()
{
	int i,temp;
	double temp_pc;
	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_pc=1.0*rand()/RAND_MAX;	//如果满足交叉的条件,就开始交叉
		if(temp_pc<=PC)
		{
			Nownode[nodeindex[i]].Pmember=PA*Nownode[nodeindex[i+1]].Pmember+(1-PA)*Nownode[nodeindex[i]].Pmember;
			Nownode[nodeindex[i+1]].Pmember=PA*Nownode[nodeindex[i]].Pmember+(1-PA)*Nownode[nodeindex[i+1]].Pmember;
			
		}	
	}
	calfitness();		//计算适应度
	return 0;
}


int mutation()			//变异操作
{
	int i,temp;
	double k=0.8,temp_pm;
	for(i=0;i<M;i++)
	{
		temp_pm=1.0*rand()/RAND_MAX;
		if(temp_pm<=PM)	//如果满足变异条件,就开始变异
		{
			temp=rand()%2;
			if(temp==0)
			{
				Nownode[i].Pmember=Nownode[i].Pmember+k*(XMAX-Nownode[i].Pmember)*1.0*rand()/RAND_MAX;
			}
			else
			{
				Nownode[i].Pmember=Nownode[i].Pmember-k*(Nownode[i].Pmember-XMIN)*1.0*rand()/RAND_MAX;
			}
		}
	}
	calfitness();	//计算适应度
	return 0;
}
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 main()
{
	int i=0,index;
	int num=0,num1=0,num2=0;
	srand(time(NULL));
	while(num++<1000)
	{
		T=0;
		initpopulation();
		while(T++<200)
		{
			copypopulation();
			crossover();
			mutation();
		}
		index=findmaxfit();
		if(fabs(Nownode[index].Pmember-1.85)<=0.1)
		{
			num1++;
		}
		else
		{
			num2++;
		}
	}
	printf("正确的次数有%d次\n",num1);
	printf("错误的次数有%d次\n",num2);
	return 0;
}








评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值