c++ 遗传算法

这周完成了一个遗传算法的大作业,记录学习过程。

这里是一个遗传算法详细介绍的链接:

我的理解 :遗传算法就是给你一个函数F(x,y),让你在x,y的定义域内找出函数F(x,y)的全局最优解
它通过不断改变x,y的值来得出新的F(x,y),然后保留F(x,y)中比较满意的一部分,剩余部分直接淘汰。
每次改变,保留,淘汰都是一次迭代的过程,直到得到F(x,y)的全局最优(理论上无限次迭代的结果,实际可能陷入局部最优,如基因码多个连续的0或多个连续的1)

题目:


我第一次实现的版本:它的时间效率比较低,因为每一次迭代的每一个个体都要进行一次基因码解码为表现型。而解码一次需要23ms,太费时间。

第二个版本我就把基因型和表现型做了一个映射,把解码过的基因和x1,x2,表现型记录下来,每次解码时首先去映射表查找有没有解码过,解码过就直接赋值,省去解码的过程,效率飞升。

我用的是visual studio2019

第一代版本:

#include<iostream>
#include<cmath>
#include<vector>
#include<time.h>
#include <stdlib.h>
#include<iomanip>
using namespace std;
//声明全局变量
//种群数量N,精英数量E,迭代次数Times,两点交叉概率Pc,单点变异概率Pm;
int N = 100, E = 5, Times = 500;
double Pc = 0.6, Pm = 0.06, PI = 3.1415926;

//初始化,随机创建N个个体的初始基因型:int Individual[N][33]
void Initialize(vector<vector<int>> &Individual)
{
	//随机创建N个个体的初始基因型
	for (int i = 0; i < N; i++)  //遍历每个个体v
	{
		for (int j = 0; j < 33; j++)	//每个个体随机33位01基因序列
		{
			Individual[i][j] = (rand() % 2);
		}
	}
}
//改进测试:不使用库函数是否加快函数运算速度;结论:无明显变化
int Pow(int k)
{
	int r=1;
	for (int i = 0; i < k; i++)
		r = r * 2;
	return r;
}

//解码,返回第i个个体的表现型
double Decode(vector<vector<int>> Indivisual, int i)
{
	//声明解码值x1,x2
	double x1 = 0, x2 = 0;
	//解码x1
	int TempSum = 0;
	for (int j = 17, k = 0; j >= 0; j--, k++)
	{
		TempSum += Pow( k) * Indivisual[i][j];
	}
	x1 = TempSum * 15.1 / 262143 - 3;
	//解码x2
	TempSum = 0;
	for (int j = 32, k = 0; j >= 18; j--, k++)
	{
		TempSum += Pow( k) * Indivisual[i][j];
	}
	x2 = TempSum * 1.7 / 32767 + 4.1;
	//返回fit值
	return  21.5 + x1 * sin(4 * PI * x1) + x2 * sin(20 * PI * x2);
}
//计算个体的表现型
void ComFit(vector<vector<int>>& Individual, double Fit[])
{
	for (int i = 0; i < N; i++)
	{
		//个体i的基因型解码为表现型
		Fit[i] = Decode(Individual, i);
	}
}
//精英保留
void Save(vector<vector<int>>& Individual, int EliteNum[], vector<vector<int>>& EliteGene,double Fit[],double EliteValue[])
{
	//精英保留E个最优个体直接进入下一代种群
	for (int i = 0; i < E; i++)  //循环找出E个精英交叉池编号  i表示第i个精英
	{
		double MaxFit = 0;
		for (int j = 0; j < N; j++)  //遍历所有个体适应值,找出第i个精英   j表示当前个体
		{
			//  <=更改为<
			if (MaxFit < Fit[j])   //判断当前最大适应值是否小于等于当前个体适应值
			{
				int repeat = 0;
				for (int k = 0; k < E; k++)  //遍历所有精英,判断当前精英是否重复
				{
					if (j == EliteNum[k])  //
					{
						repeat = 1;
						break;
					}

				}
				if (repeat == 0)   //当前精英未重复
				{
					MaxFit = Fit[j];
					EliteValue[i] = MaxFit;
					EliteNum[i] = j;
					for (int ii = 0; ii < 33; ii++)
					{
						EliteGene[i][ii] = Individual[j][ii];
					}

				}
				else
					continue;
			}
		}
	}
}
//把父代Individual[][]中第i个体放入交叉池pool中,
void CopyIn(vector<vector<int>>& Pool, vector<vector<int>>& Individual, int i, int j)
{
	for (int k = 0; k < 33; k++)
		Pool[i][k] = Individual[j][k];
	return;
}
//建立交叉池
void CreatePool(vector<vector<int>>& Individual, vector<vector<int>>& Pool, double Fit[])
{
	//首先,计算个体的适应度占总适应度的比值pi,然后,计算个体的累计适应度qi。
	double* pi = new double[N];
	double* qi = new double[N];
	//求总适应度sum_fit
	double sum_fit = 0;
	for (int i = 0; i < N; i++)
		sum_fit += Fit[i];
	//遍历所有个体适应度,求每个个体/比值pi,每个个体累计适应度qi
	for (int i = 0; i < N; i++)
	{
		pi[i] = Fit[i] / sum_fit;
		if (i == 0)
			qi[i] = pi[i];
		else
			qi[i] = qi[i - 1] + pi[i];
	}
	for (int i = 0; i < N; i++)
	{
		//轮盘赌选择概率p
		double p = (rand() % 10000 / 10001.0);
		for (int j = 0; j < N; j++)
			if (qi[j] > p)
			{
				// 把N个体放入交叉池
				CopyIn(Pool, Individual, i, j);
				break;
			}

	}
	delete[]pi;
	delete[]qi;
}
//在交叉池内进行两点交叉
void TwoPointCross(vector<vector<int>>& Pool, int i)
{
	int left = rand() % 33, right = rand() % 33;
	if (left > right)
	{
		int t = left;
		left = right;
		right = t;
	}
	for (int j = left; j <= right; j++)
	{
		int temp = Pool[i][j];
		Pool[i][j] = Pool[i + 1][j];
		Pool[i + 1][j] = temp;
	}
}
//单点变异
void SinglePointVariation(vector<vector<int>>& Pool, int i, double Pm)
{
	for (int j = 0; j < 33; j++)
	{
		if (Pm > (rand() % 10000 / 10001.0))
		{
			Pool[i][j] = (Pool[i][j] + 1) % 2;
		}
	}
}
//两点交叉,单点变异
void IndiCrossVariation(vector<vector<int>>& Pool)
{
	for (int i = 0; i < N / 2; i++)
	{	
		//随机值小于交叉概率则进行两点交叉
		if (Pc > (rand() % 10000 / 10001.0))  
		{
			//在交叉池内进行两点交叉
			TwoPointCross(Pool, i);
			//对交叉的个体的两个后代进行单点变异
			SinglePointVariation(Pool, i, Pm);
		}
	}
}
//计算交叉池个体的表现型
void CalculationFit(vector<vector<int>>& DoubleIndi, double DoubleFit[])
{
	//计算表现型
	for (int i = 0; i < N*2; i++)
	{
		//个体i的基因型解码为表现型
		DoubleFit[i] = Decode(DoubleIndi, i);
	}
}
//计算累计适应度
void CalculationDoubleQi(double DoubleFit[], double DoublePi [] , double DoubleQi[])
{
	//求总适应度sum_fit
	double SumFitAll = 0;
	int i;
	for (i = 0; i < N*2; i++)
		SumFitAll += DoubleFit[i];
	//遍历所有个体适应度,求每个个体/比值,每个个体累计适应度
	for (i = 0; i < N*2; i++)
	{
		DoublePi[i] = DoubleFit[i] / SumFitAll;
		if (i == 0)
			DoubleQi[i] = DoublePi[i];
		else
			DoubleQi[i] = DoubleQi[i - 1] + DoublePi[i];
	}
}
void UpdataPopulation(vector<vector<int>>& Individual, vector<vector<int>>& Pool, vector<vector<int>>& EliteGene)
{
	//把父代和子代放入种群池DoubleIndi
	vector<vector<int>> DoubleIndi(2 * N, vector<int>(33));
	int i, j;
	for (i = 0; i < N; i++)
	{
		for (j = 0; j < 33; j++)
		{
			DoubleIndi[i][j] = Individual[i][j];
		}
	}
	for (i = N; i < 2 * N; i++)
		for (j = 0; j < 33; j++)
		{
			DoubleIndi[i][j] = Pool[i - N][j];
		}

	//创建适应度数组
	double* DoubleFit = new double[2 * N];
	//创建个体的适应度占总适应度的比值
	double* DoublePi = new double[2 * N];
	//创建累计适应度数组
	double* DoubleQi = new double[2 * N];

	//计算所有个体适应度,返回 DoubleFit
	CalculationFit(DoubleIndi, DoubleFit);

	//计算累计适应度,返回DoubleQi
	CalculationDoubleQi(DoubleFit, DoublePi, DoubleQi);
	
	//从种群 DoubleIndi中轮盘赌选择 N-E 个个体进入下一代 Individual[N][33]
	for (i = 0; i < N - E; i++)
	{
		double p2 = rand() % 10000 / 10001.0;
		//cout << p2 << endl;
		for (j = 0; j < N * 2; j++)
		{
			if (DoubleQi[j] > p2)
			{
				CopyIn(Individual, DoubleIndi, i, j);
				break;
			}
		}
	}
	//精英个体EliteGene[E][33]直接加入下一代 Individual[N][33]
	for (j = 0; j < E; j++, i++)
	{
		for (int k = 0; k < 33; k++)
			Individual[i][k] = EliteGene[j][k];
	}
	delete[]DoubleFit;
	delete[]DoublePi;
	delete[]DoubleQi;
}
void Decodex1(vector<vector<int>>& EliteGene, double x1[])
{
	//解码x1
	for (int i = 0; i < E; i++)
	{
		int TempSum = 0;
		for (int j = 17, k = 0; j >= 0; j--, k++)
		{
			TempSum += (int)pow(2, k) * EliteGene[i][j];
		}
		x1[i] = TempSum * 15.1 / 262143 - 3;
	}
	
}
void Decodex2(vector<vector<int>>& EliteGene, double x2[])
{
	//解码x2
	for (int i = 0; i < E; i++)
	{
		int TempSum = 0;
		for (int j = 32, k = 0; j >= 18; j--, k++)
		{
			TempSum += (int)pow(2, k) * EliteGene[i][j];
		}
		x2[i] = TempSum * 1.7 / 32767 + 4.1;
	}
}

//输出精英的适应值和基因码
void OutputElite(double EliteValue[], vector<vector<int>>& EliteGene,int Current_t,double x1[],double x2[])
{

	Decodex1(EliteGene, x1);
	Decodex2(EliteGene, x2);
	//输出精英的适应值
	for (int i = 0; i < E; i++)
	{
		cout << "种群第" << Current_t << "代第" << i << "个精英个体的精英适应值:" <<fixed<<setprecision(15)<< EliteValue[i];
		cout << "    它的f(x1,x2)=(" << x1[i] << "," << x2[i] << ") " << "   它的基因码:";
		for (int j = 0; j < 33; j++)
		{
			cout << EliteGene[i][j];
		}
		cout << endl;
	}
	cout << endl;
}


int main()
{
	//创建随机数种子
	srand((unsigned)time(NULL));
	//创建N个个体 Individual[N][33]
	vector<vector<int>> Individual(N, vector<int>(33));
	//对应个体的表现型 Fit[N]
	double* Fit = new double[N]();
	//声明精英个体编号,寻找适应值最大的E个个体的种群编号EliteNum[E]
	int* EliteNum = new int[E]();
	//声明精英保存数组
	vector<vector<int>> EliteGene(E,vector<int>(33));
	//定义E个精英的适应值EliteValue[],并初始化
	double* EliteValue = new double[E]();
	//初始化,随机创建N个个体的初始基因型:int Individual[N][33]
	Initialize(Individual);
	
	//迭代Times次
	for (int Current_t = 0; Current_t < Times; Current_t++)
	{
		//计算个体的表现型
		ComFit(Individual, Fit);
		//保留E个适应度最高的精英:double Elite[E] ,以及它的基因型 int EliteGene[E][33]
		Save(Individual, EliteNum, EliteGene, Fit, EliteValue);
		//轮盘赌选择创建交叉池 int Pool[N][33]
		vector<vector<int>> Pool(N, vector<int>(33));
		CreatePool(Individual, Pool, Fit);
		//种群个体间基因在交叉池两点交叉以及单点变异 产生在交叉池中的子代 int Pool[N][33]
		IndiCrossVariation(Pool);
		//把父代和子代合并,进行轮盘赌选择N-E个个体,更新种群个体 Individual[N-E][33]
		UpdataPopulation(Individual, Pool,EliteGene);
		//输出当前代的精英表现形(适应值)以及基因型
		//
		double* x1 = new double[E];
		double* x2 = new double[E];
		OutputElite(EliteValue, EliteGene,Current_t,x1,x2);
		delete[] x1;
		delete[] x2;
	}
	cout << "OK" << endl;
	delete[]Fit;
	delete[]EliteNum;
	delete[]EliteValue;
	return 0;
}

第二代优化版:

#include<iostream>
#include<cmath>
#include<vector>
#include<time.h>
#include <stdlib.h>
#include<iomanip>
using namespace std;
//声明全局变量
//种群数量N,精英数量E,迭代次数Times,两点交叉概率Pc,单点变异概率Pm,纪元T;映射表指针GMFnum
int N = 100, E = 10, Times = 2000, T = 100,GMFnum=0;
double Pc = 0.6, Pm = 0.06, PI = 3.1415926;

//种群
class Population
{
public:
	int gene[33],fitChange;
	double x1, x2, fit;
	//随机初始化个体基因
	void Initialize()
	{
		for (int i = 0; i < 33; i++)
			gene[i] = (rand() % 2);
		fitChange = 1;
		fit = 100; x1 = 100; x2 = 100;
	}
};
//精英
class Elite
{
public:
	int num;
	int gene[33];
	double x1, x2, fit;
	//初始化精英在种群中的序号全为0
	Elite()
	{
		num = 0;
	}
};
//映射表
class GeneMappingFit
{
public:
	int gene[33];
	double x1, x2, fit;
	//初始化基因全为0
	GeneMappingFit()
	{
		x1 = 100; x2 = 100; fit = 0;
		for (int i = 0; i < 33; i++)
			gene[i] = 0;
	}
};
//判断个体i是否在映射表中,是则返回映射表序号,否则返回-1;
int GeneInGMF(Population Individual[], int i, GeneMappingFit gmf[])
{
	int j, same = 1;
	//遍历映射表gmf
	for (j=0; j < N; j++)   
	{
		for (int k = 0; k < 33; k++)
		{
			if (Individual[i].gene[k] == gmf[j].gene[k])
				;
			else
			{
				same = 0;
				break;
			}
		}
		if (same == 1)
		{
			return j;
		}
	}
	//判断个体i在映射表中,返回j
	return -1;
}

//个体i不在映射表中,计算个体i表现型;  更新Indivisual[i].fitChange = 0;  更新映射表;
void DecodeAndUpdata(Population Indivisual[],int i, GeneMappingFit gmf[])
{
	//解码x1
	int TempSum = 0;
	for (int j = 17, k = 0; j >= 0; j--, k++)
	{
		TempSum += (int)pow(2, k) * Indivisual[i].gene[j];
	}
	Indivisual[i].x1 = TempSum * 15.1 / 262143 - 3;
	//解码x2
	TempSum = 0;
	for (int j = 32, k = 0; j >= 18; j--, k++)
	{
		TempSum += (int)pow(2, k) * Indivisual[i].gene[j];
	}
	Indivisual[i].x2 = TempSum * 1.7 / 32767 + 4.1;
	Indivisual[i].fit=21.5 + Indivisual[i].x1 * sin(4 * PI * Indivisual[i].x1) + Indivisual[i].x2 * sin(20 * PI * Indivisual[i].x2);
	Indivisual[i].fitChange = 0;

	//更新映射表
	if (GMFnum < N)
	{
		gmf[GMFnum].fit = Indivisual[i].fit;
		gmf[GMFnum].x1 = Indivisual[i].x1;
		gmf[GMFnum].x2 = Indivisual[i].x2;
		for (int k = 0; k < 33; k++)
			gmf[GMFnum].gene[k] = Indivisual[i].gene[k];
		GMFnum++;
	}
	else
	{
		GMFnum -= N;
		gmf[GMFnum].fit = Indivisual[i].fit;
		gmf[GMFnum].x1 = Indivisual[i].x1;
		gmf[GMFnum].x2 = Indivisual[i].x2;
		for (int k = 0; k < 33; k++)
			gmf[GMFnum].gene[k] = Indivisual[i].gene[k];
	}
}
//个体i在映射表中,映射表直接赋值,fitChange=0
void CopyIn(Population Individual[], int i, GeneMappingFit gmf[], int g)
{
	Individual[i].fit = gmf[g].fit;
	Individual[i].x1 = gmf[g].x1;
	Individual[i].x2 = gmf[g].x2;
	for (int k = 0; k < N; k++)
		Individual[i].gene[k]= gmf[g].gene[k];
	Individual[i].fitChange = 0;

}

//计算个体的表现型:判断个体fitChange是否为1(表示基因型与表现型不符)
void ComputeFit(Population Individual[],GeneMappingFit gmf[])
{
	for (int i = 0; i < N; i++)		//遍历所有个体
	{
		if (Individual[i].fitChange == 1)  //当前个体基因型与表现型不符
		{
			//判断基因是否在映射表中,在g=映射表序号,反之g=-1
			int g = GeneInGMF(Individual, i,gmf);
			if (g == -1)
			{
				//个体i不在映射表中,计算个体表现型;更新Individual[i].fitChange = 0; 更新映射表;
				DecodeAndUpdata(Individual, i,gmf);
			}
			else
			{
				//个体i在映射表中,映射表直接赋值,fitChange=0
				CopyIn(Individual,i, gmf, g);
			}
			
		}
	}
}
//精英保留
void Save(Population Individual[], Elite elite[])
{
	//精英保留E个最优个体直接进入下一代种群
	for (int i = 0; i < E; i++)  //循环找出E个精英交叉池编号  i表示第i个精英
	{
		double MaxFit = 0;
		for (int j = 0; j < N; j++)  //遍历所有个体适应值,找出第i个精英   j表示当前个体
		{
			//  <=更改为<
			if (MaxFit < Individual[j].fit)   //判断当前最大适应值是否小于等于当前个体适应值
			{
				int repeat = 0;
				for (int k = 0; k < E; k++)  //遍历所有精英,判断当前精英是否重复
				{
					if (j == elite[k].num)  //
					{
						repeat = 1;
						break;
					}

				}
				if (repeat == 0)   //当前精英未重复
				{
					MaxFit = Individual[j].fit;
					elite[i].fit = MaxFit;
					elite[i].num = j;
					elite[i].x1= Individual[j].x1;
					elite[i].x2 = Individual[j].x2;
					for (int ii = 0; ii < 33; ii++)
					{
						elite[i].gene[ii] = Individual[j].gene[ii];
					}

				}
				else
					continue;
			}
		}
	}
}
//建立交叉池
void CreatePool(Population Individual[], Population pool[])
{
	//首先,计算个体的适应度占总适应度的比值pi,然后,计算个体的累计适应度qi。
	double* pi = new double[N];
	double* qi = new double[N];
	//求总适应度sum_fit
	double sum_fit = 0;
	for (int i = 0; i < N; i++)
		sum_fit += Individual[i].fit;
	//遍历所有个体适应度,求每个个体/比值pi,每个个体累计适应度qi
	for (int i = 0; i < N; i++)
	{
		pi[i] = Individual[i].fit / sum_fit;
		if (i == 0)
			qi[i] = pi[i];
		else
			qi[i] = qi[i - 1] + pi[i];
	}
	for (int i = 0; i < N; i++)
	{
		//轮盘赌选择概率p
		double p = (rand() % 10000 / 10001.0);
		for (int j = 0; j < N; j++)
			if (qi[j] > p)
			{
				// 把N个体放入交叉池
				pool[i].fit = Individual[j].fit;
				pool[i].x1 = Individual[j].x1;
				pool[i].x2 = Individual[j].x2;
				pool[i].fitChange= Individual[j].fitChange;
				for (int k = 0; k < 33; k++)
					pool[i].gene[k] = Individual[j].gene[k];
				break;
			}

	}
	delete[]pi;
	delete[]qi;
}
//在交叉池内进行两点交叉,交叉后不一样pool[i].fitChange = 1;
void TwoPointCross(Population pool[], int i)
{
	int left = rand() % 33, right = rand() % 33;
	if (left > right)
	{
		int t = left;
		left = right;
		right = t;
	}
	//判断两点交叉部分是否一样
	int same = 1;
	for (int j = left; j <= right; j++)
	{
		if (pool[i].gene[j] = pool[i + 1].gene[j])
			;
		else
		{
			same = 0;
			break;
		}
	}
	if (same == 1)
		;
	else
	{
		for (int k = left; k <= right; k++)
		{
			int temp = pool[i].gene[k];
			pool[i].gene[k] = pool[i + 1].gene[k];
			pool[i + 1].gene[k] = temp;
		}
		pool[i].fitChange = 1;
	}
	

}
//单点变异,若变异成功pool[i].fitChange = 1;
void SinglePointVariation(Population pool[], int i, double Pm)
{
	for (int j = 0; j < 33; j++)
	{
		if (Pm > (rand() % 10000 / 10001.0))
		{
			pool[i].gene[j] = (pool[i].gene[j] + 1) % 2;
			pool[i].fitChange = 1;
		}
	}
}
//两点交叉,单点变异
void IndiCrossVariation(Population pool[])
{
	for (int i = 0; i < N / 2; i++)
	{
		//随机值小于交叉概率则进行两点交叉
		if (Pc > (rand() % 10000 / 10001.0))
		{
			//在交叉池内进行两点交叉
			TwoPointCross(pool, i);
			//对交叉的个体的两个后代进行单点变异 ,若变异成功pool[i].fitChange = 1;
			SinglePointVariation(pool, i, Pm);
		}
	}
}


//计算个体的表现型:判断个体fitChange是否为1(表示基因型与表现型不符),是则
void ComputeDoubleFit(Population Individual[], GeneMappingFit gmf[])
{
	for (int i = 0; i < 2 * N; i++)		//遍历所有个体
	{
		if (Individual[i].fitChange == 1)  //当前个体基因型与表现型不符
		{
			//判断基因是否在映射表中,在g=映射表序号,反之g=-1
			int g = GeneInGMF(Individual, i, gmf);
			if (g == -1)
			{
				//个体i不在映射表中,计算个体表现型;更新Individual[i].fitChange = 0; 更新映射表;
				DecodeAndUpdata(Individual, i, gmf);
			}
			else
			{
				//个体i在映射表中,映射表直接赋值,fitChange=0
				CopyIn(Individual, i, gmf, g);
			}

		}
	}
}
//计算累计适应度
void CalculationDoubleQi(Population DoubleIndi[], double DoublePi[], double DoubleQi[])
{
	//求总适应度sum_fit
	double SumFitAll = 0;
	int i;
	for (i = 0; i < N * 2; i++)
		SumFitAll += DoubleIndi[i].fit;
	//遍历所有个体适应度,求每个个体/比值,每个个体累计适应度
	for (i = 0; i < N * 2; i++)
	{
		DoublePi[i] = DoubleIndi[i].fit / SumFitAll;
		if (i == 0)
			DoubleQi[i] = DoublePi[i];
		else
			DoubleQi[i] = DoubleQi[i - 1] + DoublePi[i];
	}
}
void UpdataPopulation(Population Individual[], Population pool[], Elite elite[], GeneMappingFit gmf[])
{
	//把父代和子代放入种群池DoubleIndi
	Population* DoubleIndi = new Population[N * 2];
	int i, j;
	for (i = 0; i < N; i++)
	{
		DoubleIndi[i].fit = Individual[i].fit;
		DoubleIndi[i].x1 = Individual[i].x1;
		DoubleIndi[i].x2 = Individual[i].x2;
		DoubleIndi[i].fitChange = Individual[i].fitChange;
		for (j = 0; j < 33; j++)
			DoubleIndi[i].gene[j] = Individual[i].gene[j];
	}
	for (i = N; i < 2 * N; i++)
	{
		DoubleIndi[i].fit = pool[i - N].fit;
		DoubleIndi[i].x1 = pool[i - N].x1;
		DoubleIndi[i].x2 = pool[i - N].x2;
		DoubleIndi[i].fitChange = pool[i - N].fitChange;
		for (j = 0; j < 33; j++)
			DoubleIndi[i].gene[j] = pool[i - N].gene[j];
	}
		
	//创建个体的适应度占总适应度的比值
	double* DoublePi = new double[2 * N];
	//创建累计适应度数组
	double* DoubleQi = new double[2 * N];
	//计算所有个体适应度,返回 DoubleFit
	ComputeDoubleFit(DoubleIndi,gmf);

	//计算累计适应度,返回DoubleQi
	CalculationDoubleQi(DoubleIndi, DoublePi, DoubleQi);

	//从种群 DoubleIndi中轮盘赌选择 N-E 个个体进入下一代 Individual[N][33]
	for (i = 0; i < N - E; i++)
	{
		double p2 = rand() % 10000 / 10001.0;
		//cout << p2 << endl;
		for (j = 0; j < N * 2; j++)
		{
			if (DoubleQi[j] > p2)
			{
				Individual[i].fit = DoubleIndi[j].fit;
				Individual[i].x1 = DoubleIndi[j].x1;
				Individual[i].x2 = DoubleIndi[j].x2;
				Individual[i].fitChange = DoubleIndi[i].fitChange;
				for (int k = 0; k < 33; k++)
					Individual[i].gene[k] = DoubleIndi[j].gene[k];
				break;
			}
		}
	}
	//精英个体EliteGene[E][33]直接加入下一代 Individual[N][33]
	for (j = 0; j < E; j++, i++)
	{
		for (int k = 0; k < 33; k++)
			Individual[i].gene[k] = elite[j].gene[k];
		Individual[i].fitChange = 1;

	}
	delete[]DoublePi;
	delete[]DoubleQi;
	delete[]DoubleIndi;
	DoubleIndi = NULL;
}
//输出精英的适应值和基因码
void OutputElite(Elite elite[],  int tnow, int Current_t)
{

	cout << "种群第" << tnow << "次" << Current_t << "代最优精英个体的适应值:" << fixed << setprecision(15) << elite[0].fit;
	cout << "    它的f(x1,x2)=(" << elite[0].x1 << "," << elite[0].x2 << ")    它的基因码:";
	for (int j = 0; j < 33; j++)
	{
		cout << elite[0].gene[j];
	}
	cout << endl;
}
int main()
{
	//创建随机数种子
	srand((unsigned)time(NULL));
	//声明N个个体
	Population* Individual = new Population[N*2];
	//声明E个精英
	Elite* elite = new Elite[E];
	//声明基因到x1,x2,fit的映射关系
	GeneMappingFit* gmf = new GeneMappingFit[N*2];

	//精英值第t次收敛成功的迭代次数数组Successful[T],成功收敛次数ST
	int* Successful = new int[T]();
	int ST = 0;
	//执行T次观察遗传算法是否收敛到最佳值
	for (int tnow = 0; tnow < T; tnow++)
	{
		//初始化种群
		for (int Indi = 0; Indi < N; Indi++)
			Individual[Indi].Initialize();

		//迭代Times次
		int Current_t = 0;
		int output = 0;
		for (; Current_t < Times; Current_t++)
		{
			//计算个体的表现型:
			ComputeFit(Individual, gmf);
			//保留E个适应度最高的精英:double Elite[E] ,以及它的基因型 int EliteGene[E][33]
			Save(Individual, elite);

			//输出当前代的精英表现形(适应值)以及基因型
			//OutputElite(elite,tnow, Current_t);
			//判断精英的基因是否为最佳38.85026,是则
			if (elite[0].fit>38.8502926)
			{
				ST++;
				Successful[tnow] = Current_t;
				OutputElite(elite, tnow, Current_t);
				output = 1;
				break;
			}
			//轮盘赌选择创建交叉池 int Pool[N][33]
			Population*pool=new Population[N];
			CreatePool(Individual, pool);
			//种群个体间基因在交叉池两点交叉以及单点变异 产生在交叉池中的子代 int Pool[N][33]
			IndiCrossVariation(pool);
			//把父代和子代合并,进行轮盘赌选择N-E个个体,更新种群个体 Individual[N-E][33]
			UpdataPopulation(Individual, pool, elite, gmf);

			delete[]pool;
			pool = NULL;
		}
		if (output == 0)
			OutputElite(elite, tnow, Current_t);
	}

	//计算种群收敛到最优的概率
	cout << endl << "精英收敛到最佳值的次数:" << ST << "   概率为:" << ST * 1.0 / T << endl;
	cout << "每次收敛的迭代次数:"<<endl;
	for (int dt = 0, nt = 0; dt < T; dt++, nt++)
	{
		cout << Successful[dt] << ", ";
		if (nt == 10)
		{
			cout << endl;
			nt = 0;
		}
	}
	delete[]Successful;
	delete[]gmf;
	gmf = NULL;
	delete[]elite;
	elite = NULL;
	delete[]Individual;
	Individual = NULL;
	return 0;
}

更多推荐

c++ 遗传算法 记录