⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 1.cpp

📁 基本遗传算法
💻 CPP
字号:
#define MAX 10000.0

#include <iostream.h>
#include <malloc.h>
#include <stdlib.h>
#include <math.h>

//定义一个个体的结构体变量
struct individual
{
	char chrom[16];     // 染色体,用字符串来表示
	double fitness;     // 个体适应度
	double varible1;    // 个体对应的变量1值
	double varible2;    // 个体对应的变量2值
	int xsite1;         // 交叉位置1
	int xsite2;         // 交叉位置2
};

//定义一个最佳个体的结构体变量
struct bestever
{
	char chrom[16];     // 最佳个体染色体,用字符串来表示
	double fitness;     // 最佳个体适应度
	double varible1;    // 最佳个体对应的变量值
	double varible2;    // 个体对应的变量2值
	int generation;     // 最佳个体生成代
};

//定义一个表示一个染色体中交叉位置的结构体变量
struct CrossPos
{
	int xsite1;
	int xsite2;
};

/*定义一些在程序中需要用到的全局变量*/

individual * oldpop;    // 当前代种群
individual * newpop;    // 新一代种群
bestever bestfit;       // 最佳个体
double sumfitness;      // 种群中个体适应度累加值
double max;             // 种群中个体最大适应度
double avg;             // 种群中个体平均适应度
double min;             // 种群中个体最小适应度
float pcross;           // 交叉概率
float pmutation;        // 变异概率
int popsize;            // 种群大小
int lchrom=16;          // 染色体长度固定,为16个字节
int chromsize=2;        // 存储一个染色体所需要的字节数
int gen=0;              // 当前世代数,刚开始应该是0,代表初始种群
int maxgen;             // 最大世代数
int run;                // 当前运行次数
int maxruns;            // 总运行次数
int nmutation;          // 当前代变异发生次数
int ncross;             // 当前代交叉发生次数

///////////////////////////////////////

/*随机数发生器使用的变量*/
double oldrand[55];
int jrand;

void initdata()
{  // 键盘输入遗传算法参数
   cout<<"请输入种群大小(20-100):"<<endl;
   cin>>popsize;

   if((popsize%2)!=0)
   {  // 将种群大小设置为偶数
	  popsize++;
   }

   cout<<"请输入最大世代数(100-300):"<<endl;
   cin>>maxgen;

   cout<<"请输入交叉率(0.2-0.9):"<<endl;
   cin>>pcross;

   cout<<"请输入变异率(0.01-0.1):"<<endl;
   cin>>pmutation;
}

void initmalloc()
{  // 分配给全局数据结构空间 

   // 分配给当前代和新一代种群内存空间
   oldpop=(struct individual *)malloc(popsize*sizeof(struct individual));
   newpop=(struct individual *)malloc(popsize*sizeof(struct individual));
}

void objfunc(individual * unit)
{   // 计算初始适应度值
    
	// 初始化两个自变量的值
	unit->varible1=0.0;
	unit->varible2=0.0;

	// 一个中间变量值,用来求出自变量的值
    double temp=0.0;

	// 循环变量
	int i,j;

	// 首先,要把两个自变量从染色体字符串分离出来

	// 计算自变量1
    for(i=0,j=7;i<8;i++,j--)
	{
		char cbit=unit->chrom[i];
		if(cbit=='1')
		{
			temp+=pow(2.0,j);
		}
	}

	unit->varible1=-2.048+temp*4.096/(pow(2.0,8)-1);

    // 将temp清0
    temp=0.0;

	// 计算自变量2
	for(i=8,j=7;i<16;i++,j--)
	{
		char cbit=unit->chrom[i];
		if(cbit=='1')
		{
			temp+=pow(2.0,j);
		}
	}

	unit->varible2=-2.048+temp*4.096/(pow(2.0,8)-1);

	// 计算染色体的自适应值

	double x1=unit->varible1;
	double x2=unit->varible2;

	unit->fitness=100*(x1*x1-x2)*(x1*x1-x2)+(1-x1)*(1-x1);
}

void advance_random()
{  // 产生55个随机数
   int j1;
   double new_random;
   for(j1=0;j1<24;j1++)
   {
	   new_random=oldrand[j1]-oldrand[j1+31];
	   if(new_random<0.0) new_random=new_random+1.0;
	   oldrand[j1]=new_random;
   }

   for(j1=24;j1<55;j1++)
   {
	   new_random=oldrand[j1]-oldrand[j1-24];
	   if(new_random<0.0) new_random=new_random+1.0;
	   oldrand[j1]=new_random;
   }
}

float randomperc()
{  // 产生[0,1]之间的一个随机数
   jrand++;
   if(jrand>=55)
   {
	   jrand=1;
	   advance_random();
   }
   return (float)oldrand[jrand];
}

void initpop()
{  // 初始化种群

   // 循环变量
   int i,j;

   // 将每个个体的染色体以及个体的交叉位置均初始化为0
   for(i=0;i<popsize;i++)
   {
	   for(j=0;j<16;j++)
	   {
		   oldpop[i].chrom[j]='0';
	   }

	   oldpop[i].xsite1=0;
	   oldpop[i].xsite2=8;
   }

   // 接收随机函数返回值
   double temp=0.0;

   // 利用随机函数完成初始化种群工作
   for(i=0;i<popsize;i++)
   {
	   for(j=0;j<lchrom;j++)
	   {
		   if(randomperc()>=0.5)
		   {
			   oldpop[i].chrom[j]='1';
		   }
	   }

	   objfunc(&(oldpop[i]));  //计算初始适应度值
   }
}

void statistics(individual * oldpop)
{  // 统计计算结果
   
   // 循环变量
   int i,j;

   // 一些初始化工作
   sumfitness=0.0;
   min=oldpop[0].fitness;
   max=oldpop[0].fitness;

   // 计算最大、最小和累计适应度
   for(i=0;i<popsize;i++)
   {
	   sumfitness+=oldpop[i].fitness;
	   if(oldpop[i].fitness>max)   max=oldpop[i].fitness;
	   if(oldpop[i].fitness<min)   min=oldpop[i].fitness;

	   // 计算最佳个体的相应参数,并假定
	   // 取得最小值的个体为最佳个体
	   if(oldpop[i].fitness<bestfit.fitness)
	   {
		   // 传递染色体的字符串变量
		   for(j=0;j<16;j++)
		   {
			   bestfit.chrom[j]=oldpop[i].chrom[j];
		   }

		   bestfit.fitness=oldpop[i].fitness;
		   bestfit.varible1=oldpop[i].varible1;
		   bestfit.varible2=oldpop[i].varible2;
		   bestfit.generation=gen;
	   }
   }

   // 计算平均适应度值
   avg=sumfitness/popsize;
}

void warmup_random(float random_seed)
{   // 初始化随机数发生器
	int j1,ii;
    double new_random,prev_random;

	oldrand[54]=random_seed;
	new_random=0.000000001;
	prev_random=random_seed;
	for(j1=1;j1<=54;j1++)
	{
		ii=(21*j1)%24;
		oldrand[ii]=new_random;
		new_random=prev_random-new_random;
		if(new_random<0.0) new_random=new_random+1.0;
		prev_random=oldrand[ii];
	}
	advance_random();
	advance_random();
	advance_random();
	jrand=0;
}

void randomize()
{   //设定随机数种子并初始化随机数发生器
	float randomseed;
	int j1;
	for(j1=0;j1<55;j1++)
		oldrand[j1]=0.0;
	jrand=0;
	cout<<"请输入一个随机数种子(0,1):"<<endl;
	cin>>randomseed;
	warmup_random(randomseed);
}

void initialize()
{  // 遗传算法初始化
   initdata();  // 键盘输入遗传算法参数

   initmalloc(); // 分配给全局数据结构空间 

   randomize();  // 初始化随机数发生器

   // 初始化全局计数变量和一些数值
   nmutation=0;   // 初始化当前代变异发生次数为0
   ncross=0;      // 初始化当前代交叉发生次数为0
   bestfit.fitness=MAX;  //初始化最佳个体适应值
   bestfit.generation=0; //初始化最佳个体生成代

   // 初始化种群
   initpop();

   // 统计计算结果
   statistics(oldpop);

}

int rnd(int low,int high)
{  // 在整数low和high之间产生一个随机整数
   int i;
   if(low>=high)
	   i=low;
   else
   {
	   i=int((randomperc()*(high-low+1))+low);
	   if(i>high)  i=high;
   }
   return i;
}

int select()
{  // 赌轮选择
   return int(randomperc()*(popsize-1));
}

CrossPos crossover(char * parent1,char * parent2,
			  char * child1,char * child2)
{   // 由两个父个体交叉产生两个子个体

	// 循环变量
	int i;

	// 标识进行交叉的位置
	CrossPos jcross;

	// 用赌轮法判断是否进行进行交叉
	if(randomperc()<=pcross)
	{   // 若进行交叉运算

		// 随机产生个体中的两个交叉位置
		jcross.xsite1=rnd(1,7);
		jcross.xsite2=rnd(9,15);
        
		// 更新交叉次数
		ncross++;

		// 按照交叉位置进行交叉运算并产生子代

		// 更新子代1和2的染色体
		for(i=0;i<16;i++)
		{
			if(i<jcross.xsite1)
			{
				child1[i]=parent1[i];
				child2[i]=parent2[i];
			}
			else if(i>=jcross.xsite1 && i<=7)
			{
				child1[i]=parent2[i];
				child2[i]=parent1[i];
			}
			else if(i>7 && i<jcross.xsite2)
			{
				child1[i]=parent1[i];
				child2[i]=parent2[i];
			}
			else 
			{
				child1[i]=parent2[i];
				child2[i]=parent1[i];
			}
		}
	}
	else
	{   // 如果没有进行交叉运算
		for(i=0;i<16;i++)
		{   // 保持原样
			child1[i]=parent1[i];
			child2[i]=parent2[i];
		}
		// 此时交叉位置固定
		jcross.xsite1=0;
		jcross.xsite2=8;
	}
	return jcross;
}

void mutation(char * child)
{  // 变异操作

   // 循环变量
   int i;

   bool flag=false;

   for(i=0;i<16;i++)
   {   // 判断染色体中每一位是否发生变异

	   if(randomperc()<=pmutation)
	   {   // 若发生变异
		   if(child[i]='0')   child[i]='1';
		   else    child[i]='0';
		   flag=true;
	   }
   }
   if(true==flag)  nmutation++;
}

void preselect()
{  // 每代运算前进行预选
   int i;
   sumfitness=0.0;
   for(i=0;i<popsize;i++)
	   sumfitness+=oldpop[i].fitness;
}

void generation()
{  // 产生新的一代
   
   // 标识要进行交叉运算的两个个体的序号
   int mate1,mate2;

   // 每代运算前进行预选
   preselect();

   // 标识要进行交叉运算的位置
   CrossPos jcross;

   // 循环变量
   int i=0;

   do
   {
	   // 挑选交叉配对
	   mate1=select();
	   mate2=select();
       // 交叉和变异
	   jcross=crossover(oldpop[mate1].chrom,oldpop[mate2].chrom,
		   newpop[i].chrom,newpop[i+1].chrom);

	   mutation(newpop[i].chrom);
	   mutation(newpop[i+1].chrom);

	   // 解码,计算适应度
       objfunc(&(newpop[i]));

	   objfunc(&(newpop[i+1]));

	   // 记录交叉位置
	   newpop[i].xsite1=jcross.xsite1;
	   newpop[i].xsite2=jcross.xsite2;

       newpop[i+1].xsite1=jcross.xsite1;
	   newpop[i+1].xsite2=jcross.xsite2;

	   i=i+2;
   }
   while(i<(popsize-1));
}

void report()
{   // 输出新一代统计数据
	cout<<"第"<<gen<<"代统计:"<<endl;
	cout<<"总交叉次数="<<ncross<<",";
	cout<<"总变异次数="<<nmutation<<endl;
	cout<<"最小适应度:"<<min<<"最大适应度:"<<max<<"平均适应度:"<<avg<<endl;
	cout<<"迄今发现最佳个体=>所在代数:"<<bestfit.generation;
	cout<<"最佳个体的适应度:"<<bestfit.fitness;
	cout<<"最佳个体对应的变量值:"<<bestfit.varible1<<"  "<<bestfit.varible2;
	cout<<endl;
}

void freeall()
{   // 释放动态申请的内存空间
    free(oldpop);
	free(newpop);
}

void main()
{   // 主函数
	cout<<"/***************欢迎进入基本遗传算法系统:***************/"<<endl;
    cout<<"/*本例子中,测试函数是:"<<endl;
	cout<<"F=100(x1*x1-x2)(x1*x1-x2)+(1-x1)(1-x1)"<<endl;
	cout<<"/*自变量范围:-2.048=<x1<=2.048,-2.048=<x2<=2.048"<<endl;
	cout<<"问题是:求函数的最小值问题!"<<endl;
	cout<<"请输入一些参数:"<<endl;

    cout<<"请输入遗传算法执行次数(1-10):"<<endl;
    cin>>maxruns;

	// 一个用于交换的变量
    individual * temp;

	for(run=1;run<=maxruns;run++)
	{
		initialize(); // 遗传算法初始化
        for(gen=1;gen<=maxgen;gen++)
		{
			cout<<"第"<<run<<"/"<<maxruns<<"次运行:当前代为";
			cout<<gen<<"共"<<maxgen<<"代"<<endl;

			// 产生新的一代
			generation();

			// 计算新的一代的统计数据
			statistics(newpop);

			// 输出新一代统计数据
			report();

			// 交换
			temp=oldpop;
			oldpop=newpop;
			newpop=temp;
		}
		freeall();
		gen=0;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -