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

📄 genetic.cpp

📁 遗传算法的核心实现类 C++语言编写
💻 CPP
📖 第 1 页 / 共 2 页
字号:
				//str.Format("%d",Pos);
				//if(i==1&&Pos==0)
					//AfxMessageBox(str);
				m_pNichePop[i*m_nLength+m]=m_pNichePop[Pos*m_nLength+m];
			}
		}
		else
		{
			for(int m=0;m<m_nLength;m++)
				m_pNichePop[i*m_nLength+m]=m_pPop[(Pos-m_nNicheGA)*m_nLength+m];
		}

		/////////////////
		if(Pos>=2*m_nNicheGA)
		{
			PopFitness[Pos]=old;
			for(int m=0;m<m_nLength;m++)
			{
				m_pPop[(Pos-m_nNicheGA)*m_nLength+m]=pOldNiche[m];
			}
		}
		delete pOldNiche;
		//找到一个小生境核i后--更新适应度--把核内的适应度降下来
		for(int j=0;j<m_nPopSize+m_nNicheGA;j++)
		{
			
			//判断个体位于哪个小生境
			if(j<m_nNicheGA)
			{
				if(HaimingDistance(i,m_pNichePop,j,m_pNichePop)<=m_dNichDistanceBoundary)
				{
					//惩罚j以后的小生境
					if(j>i)
					{
						m_pNicheFitness[j]=m_dPenality;
						PopFitness[j]=m_dPenality;
					}
				}
			}
			//降低种群相似群体的适应度
			else
			{
				if(HaimingDistance(i,m_pNichePop,j-m_nNicheGA,m_pPop)<=m_dNichDistanceBoundary)
				{
					if(PopFitness[j]<=m_pNicheFitness[i])
					{
						PopFitness[j]=m_dPenality;
						
					}
				}
				
			}
			
		}
	
		//清除已选出的最值,以免影响以后的寻优
		//PopFitness[Pos]=0;
		PopFitness[i]=0;
	}



	//将小生境核复制到种群中产生新的种群
	for(i=0;i<m_nNicheGA;i++)
	{
		for(int m=0;m<m_nLength;m++)
			m_pPop[i*m_nLength+m]=m_pNichePop[i*m_nLength+m];
		//m_pPopValue[i]=m_pNicheFitness[i];
	}

	for(i=0;i<m_nPopSize;i++)
	{
		DecodeChromosome(i*m_nLength+m_pPop,X);
		m_pPopValue[i]=Function(X);
	}
	//对m_nNicheGA以后的个体直接惩罚
	for(i=0;i<m_nNicheGA;i++)
	{
		for(int j=m_nNicheGA;j<m_nPopSize;j++)
		{	
			if(HaimingDistance(i,m_pNichePop,j,m_pPop)<=m_dNichDistanceBoundary)
			{
				m_pPopValue[j]=m_dPenality;
			}
		}
	}
	//计算平均适应度

	double sum=0;
	m_struct.Index[0]=m_struct.Index[1]=0;
	m_struct.dMin=m_struct.dMax=m_pPopValue[0];

	for(i=0;i<m_nPopSize;i++)
	{
		//指针后移i*m_nLength个长度
		sum+=m_pPopValue[i];
		if(m_pPopValue[i]>m_struct.dMax)
		{
			m_struct.dMax=m_pPopValue[i];
			m_struct.Index[1]=i;
		}
		if(m_pPopValue[i]<m_struct.dMin)
		{
			m_struct.dMin=m_pPopValue[i];
			m_struct.Index[0]=i;
		}

	}
	////////////////////////////////////////////////
	//计算适应度
	for( i=0;i<m_nPopSize;i++)
		m_pPopFitness[i]=m_pPopValue[i]/sum;
	/////////////////////////////////////////////
	m_struct.dAverage=sum/m_nPopSize;


	
	delete[] PopFitness;
	delete []X;
}


//////////////////////////////////////////////////////////////////////////////////////
//功能:选择算子。按轮盘赌注,从种群中选择优良品种改良后代,好的种子可能会被多次选中
//返回:函数运行过程中需要动态分配内存,分配成功返回true,否则false;
/////////////////////////////////////////////////////////////////////////////////////
BOOL CGenetic::SelectionOperator()
{
	char *pPop=new char[m_nLength*m_nPopSize];//存储新种群
	double *sumfit=new double[m_nPopSize+1];//存储积累轮盘数据,以备产生随机数看落在哪个区间。一定要加一

	if (pPop == NULL)
	{
		AfxMessageBox("内存分配失败");
		return FALSE;
	}// 内存分配失败
	if (IsBadReadPtr(pPop, sizeof(char) *m_nLength*m_nPopSize))
	{
		AfxMessageBox("IsBadReadPtr failed");
		return FALSE;
	}// 内存分配失败
	memset(pPop, 0, sizeof(char) *m_nLength*m_nPopSize);// 将各元素值置0
	
	if (sumfit == NULL)
	{
		AfxMessageBox("内存分配失败");
		return FALSE;
	}// 内存分配失败
	if (IsBadReadPtr(sumfit, sizeof(double) *(m_nPopSize+1)))
	{
		AfxMessageBox("IsBadReadPtr failed");
		return FALSE;
	}// 内存分配失败
	memset(sumfit, 0, sizeof(double) *(m_nPopSize+1));// 将各元素值置0


	sumfit[0]=0;
	sumfit[m_nPopSize]=1;//积累之和当然是1

	double sum=0;
	//sum为适应度之和
	for(int i=1;i<m_nPopSize;i++)
	{	
		sum+=m_pPopFitness[i-1];
		sumfit[i]=sum;
	}

    srand((unsigned)time(NULL));
	double datarand;//产生随机数
	//轮盘选择--复制个体
	for(i=0;i<m_nPopSize;i++)
	{
		datarand=(double)rand()/RAND_MAX;
		for(int j=0;j<m_nPopSize;j++)
		{
			if((datarand>sumfit[j])&&(datarand<=sumfit[j+1]))
				memcpy(pPop+i*m_nLength,m_pPop+j*m_nLength,sizeof(char)*m_nLength);
		
		}
	}
	memset(m_pPop,0,sizeof(char)*m_nLength*m_nPopSize);
	memcpy(m_pPop,pPop,sizeof(char)*m_nLength*m_nPopSize);
   
	delete[] sumfit;
	delete[] pPop;
	return TRUE;
}
		

///////////////////////////////////////////////////////////////////////////
//功能:交叉算子。让种群相互结婚,本算法采用“近亲”结婚,(0,1)(2,3),,结婚,
//       书上写的是随机结婚,但种群排列本无顺序,“近亲”结婚也代表随机的意思,目的是为了计算方便
//返回:函数运行过程中需要动态分配内存,分配成功返回true,否则false;实际上可以改成void型
//      因为分配的内存大小只有m-nlength个字节
//////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CGenetic::CrossoverOperator()
{
	srand((unsigned)time(NULL));
	char *Flag=new char[m_nLength];

	if (Flag == NULL)
		return FALSE;					// 内存分配失败
	if (IsBadReadPtr(Flag, sizeof(char) *m_nLength))
		return FALSE;
	memset(Flag, 0, sizeof(char) *m_nLength);// 将各元素值置0

	int randPos;
	double isCross;
	for(int i=0;i<m_nPopSize;i+=2)
	{
		randPos=int((double)m_nLength*rand()/RAND_MAX);
		isCross=(double)rand()/RAND_MAX;
	    if(isCross<m_dPc)
		{	
			for(int j=0;j<=randPos;j++)
			{
				Flag[j]=m_pPop[i*m_nLength+j];
				m_pPop[i*m_nLength+j]=m_pPop[(i+1)*m_nLength+j];
				m_pPop[(i+1)*m_nLength+j]=Flag[j];

			}
		}
	}
	delete[] Flag;
	return TRUE;	
}


/////////////////////////////////////////////////////////////////////////
//功能:变异算子,每个位按初始设置的变异概率变异
////////////////////////////////////////////////////////////////////////////////
BOOL CGenetic::MutationOperator()
{
	double mutation;
	for(int i=0;i<m_nLength*m_nPopSize;i++)
	{
		mutation=(double)rand()/RAND_MAX;
		if(mutation<m_dPm)
		{
			if(m_pPop[i]=='0')
				m_pPop[i]='1';
			else
				m_pPop[i]='0';
		}
	}
	return TRUE;
}


///////////////////////////////////////////////////////////////////////////////////////
//功能:进化函数。
//返回值:返回最优目标函数值
//参数:
//
double CGenetic::Evolution(int nMaxStep,double Max[],double Min[],double Average[],double X[])
{
	GenerateInitialPopulation();
	for(int i=0;i<nMaxStep;i++)
	{
		ComputeValueAndFitness();
		SelectionOperator();
		CrossoverOperator();
		MutationOperator();
		Max[i]=m_struct.dMax;
		Min[i]=m_struct.dMin;
		Average[i]=m_struct.dAverage;
	}
	ComputeValueAndFitness();
	DecodeChromosome(m_pPop+m_struct.Index[1],X);

	return m_struct.dMax;
}

/////////////////////////////////////////////////////////////////
//产生下一代个体
////////////////////////////////////////////////////////////////
void CGenetic::GenerateNextPopulation()
{
	ComputeValueAndFitness();
	SelectionOperator();
	CrossoverOperator();
	MutationOperator();
}

//////////////////////////////////////////////////////////////////////////
//功能:设置变量的上下界约束
//返回值:无
//参数:
// Value[]------变量的上下界约束
////////////////////////////////////////////////////////////////////////////
void CGenetic::SetConstraint(double Value[])//Vlaue的值是2倍参数个数
{
	for(int i=0;i<m_nParameterCount;i++)
	{
		ASSERT(Value[i+m_nParameterCount]>=Value[i]);
	}
	
	memset(m_pConstraint, 0, sizeof(double) * 2*m_nParameterCount);
	memcpy(m_pConstraint, Value, sizeof(double) * 2*m_nParameterCount);
	
}


//////////////////////////////////////////////////////////////////////////////////////
//设置交叉概率,默认为0.6,构造函数里面已经指定为默认值,如需要自己设置,需要在建立对象后调用此函数
/////////////////////////////////////////////////////////////////////////////////////////////
void CGenetic::SetCrossoverPro(double dPc/*=0.6*/)
{
	m_dPc=dPc;
}


////////////////////////////////////////////////////////////////////////////////////////////////
//设置变异概率,默认为0.001,构造函数里面已经指定为默认值,如需要自己设置,需要在建立对象后调用此函数
///////////////////////////////////////////////////////////////////////////////////////////
void CGenetic::SetMutationPro(double dPm/*=0.001*/)
{
	m_dPm=dPm;
}


////////////////////////////////////////////////////////////////////////////////////
//获得编码精度
///////////////////////////////////////////////////////////////////////////////
double CGenetic::GetCodePrecision() const
{
	return m_dCodePrecision;
}


/////////////////////////////////////////////////////////////////////////////////////////
//获得交叉概率
/////////////////////////////////////////////////////////////////////////////////////////
double CGenetic::GetCrossoverPro() const
{
	return m_dPc;
}


//////////////////////////////////////////////////////////////////////////////////////////
//获得变异概率
/////////////////////////////////////////////////////////////////////////////////////////
double CGenetic::GetMutationPro() const
{
	return m_dPm;
}


//////////////////////////////////////////////////////////////////////////
//获得染色体长度
/////////////////////////////////////////////////////////////////////////
int CGenetic::GetChromosomeLength() const
{
	return m_nLength;
}

//////////////////////////////////////////////////////////////////////
//获得变量约束
double* CGenetic::GetConstraint() const
{
	return m_pConstraint;
}
//////////////////////////////////////////////////////////////////////////////
//获得种群规模
//////////////////////////////////////////////////////////////////////////////
int CGenetic::GetPopSize() const
{
	return m_nPopSize;
}


//////////////////////////////////////////////////////////////////
//获得每个变量的染色体长度
/////////////////////////////////////////////////////////////////
int* CGenetic::GetGetEachLength()const
{
	return m_pEachLength;
}


///////////////////////////////////////////////////////////////////
//获得种群数据二进制串的指针
///////////////////////////////////////////////////////////////////
char* CGenetic::GetPop() const
{
	return m_pPop;
}

//////////////////////////////////////////////////////////////////
//获得种群函数值的指针
///////////////////////////////////////////////////////////////
double* CGenetic::GetPopValue() const
{
	return m_pPopValue;
}


//////////////////////////////////////////////
//获得种群适应度的值的指针
double* CGenetic::GetPopFitness() const
{
	return m_pPopFitness;
}

///////////////////////////////////////////////////////
//获得目前种群中具有最大函数值
/////////////////////////////////////////////////////
double CGenetic::GetMaxValue() const
{
	return m_struct.dMax;
}

////////////////////////////////////////
//获得目前种群中具有最小函数值
///////////////////////////////////////
double CGenetic::GetMinValue() const
{
	return m_struct.dMin;
}

///////////////////////////////////
//获得目前种群中平均函数值
//////////////////////////////////
double CGenetic::GetAverageValue() const
{
	return m_struct.dAverage;
}


////////////////////////////////////////////////////
//获得该代中具有最大适应度个体的解码变量值
////////////////////////////////////////////////////
double CGenetic::GetSolution(double X[]) 
{
	DecodeChromosome(m_pPop+m_struct.Index[1],X);
	return m_struct.dMax;
}
/*****************************
计算小生境核参数
在GenerateInitialPopulation()和ComputeValueAndFitness()后调用此函数
******************************/
void CGenetic::InitComputeNichePop(int nNicheGA,double dNichDistanceBoundary)
{
	ASSERT(nNicheGA<=m_nPopSize);
	m_nNicheGA=nNicheGA;
	m_dNichDistanceBoundary=dNichDistanceBoundary;
	//对原种群的适应度m_pPopFitness进行排序,以初始化小生境核
	if(m_pNichePop)
	{
		delete[] m_pNichePop;
		m_pNichePop=NULL;
	}
	m_pNichePop=new char [m_nLength*m_nNicheGA];

	if(m_pNicheFitness)
	{
		delete[] m_pNicheFitness;
		m_pNicheFitness=NULL;
	}
	m_pNicheFitness=new double [m_nNicheGA];
	
    //寻找前m_nNicheGA个适应度最大值放到小生境核中
	double *PopFitness=new double [m_nPopSize];
	for(int i=0;i<m_nPopSize;i++)
		PopFitness[i]=m_pPopFitness[i];
	for(i=0;i<m_nNicheGA;i++)
	{
		double value=PopFitness[0];
		int Pos=0;
		int k=0;
		do
		{
			if(value<PopFitness[k])
			{
				Pos=k;
				value=PopFitness[k];
			}
			k++;
		}while(k<=m_nPopSize);
		//获得小生境核适应度
		m_pNicheFitness[i]=PopFitness[Pos];
		//复制编码将种群第Pos个编码复制到第i个核
		for(int m=0;m<m_nLength;m++)
				m_pNichePop[i*m_nLength+m]=m_pPop[Pos*m_nLength+m];
		//清除已选出的最值,以免影响以后的寻优
		PopFitness[Pos]=0;
	}

	delete[] PopFitness;
}

double CGenetic::HaimingDistance(int i,char *pNichePop,int j,char *pPop)
{
	double Distance=0;
	//先解码
	double* X=new double [m_nParameterCount];
	
	DecodeChromosome(j*m_nLength+pPop,X);
	
	double* Y=new double [m_nParameterCount];
	DecodeChromosome(i*m_nLength+pNichePop,Y);

	for(int k=0;k<m_nParameterCount;k++)
		Distance+=(X[k]-Y[k])*(X[k]-Y[k]);
    Distance=sqrt(Distance);
	/*
	CString str;
	str.Format("(%d,%d)=%f",i,j,Distance);
	AfxMessageBox(str);
	*/

	delete[] X;
	delete[] Y;
	
	return Distance;

}

⌨️ 快捷键说明

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