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

📄 wsgenalogrith.cpp

📁 开发环境:Visual C++ .net2003 功能:利用遗传算法求解TSP问题。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "StdAfx.h"
#include ".\wsgenalogrith.h"
#include <fstream>
using namespace std;
#define CITENUM_RATE 2
#define FITNESS_ALPHA 0.5
#define MODENUM 3
//#define ALPHA 0.8//被m_CrossProbability取代
WSGeneticAlogrith::WSGeneticAlogrith(void)
{
}

WSGeneticAlogrith::~WSGeneticAlogrith(void)
{
}
/*
功能:比较A、B中两组子排列是否相同
输入:A、B的子排列和排列的长度
输出:TURE-->相同 FALSE-->不同
*/
BOOL WSGeneticAlogrith::EqualVector(PINT _A, PINT _B, INT _VertorLen)
{
	for(int i = 0; i < _VertorLen; ++i)
	{
		if(_A[i] != _B[i]) return FALSE;
	}

	return TRUE;
}

BOOL WSGeneticAlogrith::Initial(PCHAR _FileName, PCHAR _oFileName, INT _MemberNum, INT _ComputeTime, BOOL _EndInNature,
								INT _ComputeGenerates, INT _TimesOfNatureEnd, FLOAT _CrossProbability, FLOAT _VarProbability)
{
	if( !MakeBaseCityInfo(_FileName) ) return FALSE;//先生成城市的基本信息
	//设定群大小
	if(_MemberNum == 0)
		m_MemberNum = CITENUM_RATE*m_BaseCityInfo.m_CityNum;
	else m_MemberNum = _MemberNum;

	m_oFileName = _oFileName;

	//设定交叉概率
	if(_CrossProbability == 0)
		_CrossProbability = 0.8;
	else
		m_CrossProbability = _CrossProbability, 

	//设定变异概率
	m_VarProbability = _VarProbability;

	GenInitialCityInfoOfMembers();
	//for(INT i = 0; i < m_MemberNum; ++i) Show(m_pCityInfoOfMembers[i].m_pCityOrder);

	m_EndInNature = _EndInNature;

	//设定终止准则
	if(_ComputeTime == 0)//ComputeTime的单位是秒
	{
		if(!_EndInNature) m_ComputeGenerates = _ComputeGenerates;
		else
		{
			if(_TimesOfNatureEnd == 0) m_TimesOfNatureEnd = 500;
			else m_TimesOfNatureEnd = _TimesOfNatureEnd;
		}
	}
	else
	{
		m_TimesOfNatureEnd = 0;
		m_ComputeGenerates = 0;
		m_ComputeTime = _ComputeTime;
	}

	return TRUE;
}

//MODE=1:限定计算代数
//MODE=2:限定计算时间
//MODE=3:自然终止
BOOL WSGeneticAlogrith::Initial(INT _Mode, PCHAR _FileName, PCHAR _oFileName, INT _Compute_GeneratesORTimeORNatureTimes, INT _MemberNum, FLOAT _CrossProbability, FLOAT _VarProbability)
{
	WSRandom::Initial();
	switch(_Mode)
	{
	case 1:	return Initial(_FileName, _oFileName, _MemberNum, 0, FALSE, _Compute_GeneratesORTimeORNatureTimes, 0,_CrossProbability, _VarProbability);
	case 2: return Initial(_FileName, _oFileName, _MemberNum, _Compute_GeneratesORTimeORNatureTimes, FALSE, 0, 0,_CrossProbability, _VarProbability);
	case 3: return Initial(_FileName, _oFileName, _MemberNum, 0, TRUE, 0, _Compute_GeneratesORTimeORNatureTimes,_CrossProbability, _VarProbability);
	default:return FALSE;
	}
	return TRUE;
}

BOOL WSGeneticAlogrith::MakeBaseCityInfo(PCHAR _FileName)
{
	return WSTSP::ReadCityInfoFromFile(_FileName, m_BaseCityInfo);
}
/*
注:该函数只能在得到m_BaseCityInfo后使用
用于种群的初始化工作
*/
VOID WSGeneticAlogrith::GenInitialCityInfoOfMembers()
{
	CityInfo l_TmpCityInfo;
	INT i;
	INT **l_ppCitySerial;
	INT _ShortestCityNum = MODENUM;
	l_ppCitySerial = new INT*[m_BaseCityInfo.m_CityNum];
	for(i = 0; i < m_BaseCityInfo.m_CityNum; ++i)
	{
		l_ppCitySerial[i] = new INT[_ShortestCityNum];
	}
	WSTSP::MakeCityDistStyle(m_BaseCityInfo, l_ppCitySerial, _ShortestCityNum);

	//for(i = 0; i < m_BaseCityInfo.m_CityNum; ++i)
	//{
	//	for(int k = 0; k < _ShortestCityNum; ++k)
	//	{
	//		printf("%d--->%d \t", i, l_ppCitySerial[i][k]);
	//	}
	//	printf("\n*************************************************\n");
	//}


	for(i = 0; i < m_MemberNum; ++i) m_pCityInfoOfMembers.push_back(l_TmpCityInfo);   
	//为适配函数分配地址
	m_pAdaptInfo = (PAdaptInfo)malloc(sizeof(AdaptInfo)*m_MemberNum);
	for(i = 0; i < m_MemberNum; ++i) 
	{
		m_pCityInfoOfMembers[i].m_CityNum = m_BaseCityInfo.m_CityNum;
		m_pCityInfoOfMembers[i].m_pCities = m_BaseCityInfo.m_pCities;
		m_pCityInfoOfMembers[i].m_pCityOrder = m_BaseCityInfo.m_pCityOrder;
		if(i < m_BaseCityInfo.m_CityNum) WSTSP::MakeStyleCityOrder(m_pCityInfoOfMembers[i], l_ppCitySerial, _ShortestCityNum);
		else WSTSP::GenRandCityOrder(m_pCityInfoOfMembers[i].m_pCityOrder);		
	}
}

VOID WSGeneticAlogrith::CalculateAdapt(INT _Mode)
{
	switch( _Mode )
	{
	case 0:
		{
			CalculateAdapt_CutTrai();
			return ;
		}
	case 1:
		{
			CalculateAdapt_WSBetRing();
			return ;
		}
	case 2:
		{
			CalculateAdapt_BetRing();
			return ;
		}
	case 3:
		{
			CalculateAdapt_Immigrant();
			return ;
		}
	default: return ;
	}
}

/*
注:该函数只能在得到m_BaseCityInfo后使用
用于计算适配值/率
规则:大于平均适配率的全部去掉;相当于取小适配率
*/
VOID WSGeneticAlogrith::CalculateAdapt_CutTrai()
{	
	INT i;
	FLOAT l_TotalValue = 0.0;

	//相当于增加了记忆装置
	FLOAT l_MinDist = WSTSP::TSPTotalDistance(&(m_pCityInfoOfMembers[0]));
	INT l_OptOrder = 0;

	
	for(i = 0; i < m_MemberNum; ++i)
	{
		m_pAdaptInfo[i].m_DestFunctionValue = WSTSP::TSPTotalDistance(&(m_pCityInfoOfMembers[i]));
		l_TotalValue += m_pAdaptInfo[i].m_DestFunctionValue;
		if(l_MinDist > m_pAdaptInfo[i].m_DestFunctionValue)
		{
			l_MinDist = m_pAdaptInfo[i].m_DestFunctionValue;
			l_OptOrder = i;
		}
	}

	//排序
	//保存最优解
	if(l_OptOrder != 0)
	{
		AdaptInfo l_TmpAdapt = m_pAdaptInfo[0];
		m_pAdaptInfo[0] = m_pAdaptInfo[l_OptOrder];
		m_pAdaptInfo[l_OptOrder] = l_TmpAdapt;

		CityInfo l_TmpCityInfo = m_pCityInfoOfMembers[0];
		m_pCityInfoOfMembers[0] = m_pCityInfoOfMembers[l_OptOrder];
		m_pCityInfoOfMembers[l_OptOrder] = l_TmpCityInfo;
	}

	//计算适配率
	for(i = 0; i < m_MemberNum; ++i)  m_pAdaptInfo[i].m_AdaptProbability =  m_pAdaptInfo[i].m_DestFunctionValue/l_TotalValue;
	//除掉小于目标的方案
	INT j = 0;
	for(i = 0; i < m_MemberNum; ++i)
	{
		if(m_pAdaptInfo[i].m_AdaptProbability > 1.0/m_MemberNum)
		{
			if(WSRandom::JudgeEven(0.8))	m_pCityInfoOfMembers.erase( m_pCityInfoOfMembers.begin() + j);
			else ++j;
		}
		else ++j;
	}
}

/*
CalculateAdapt之模式1:执行自己定义的所谓轮赌法;
采用轮赌法重新选取个体产生新的群体,选取后的种群大小不变.
*/
VOID WSGeneticAlogrith::CalculateAdapt_WSBetRing()
{
	INT i, j;
	FLOAT l_MinDist;
	INT l_OptOrder;	

	for(i = 0; i < m_MemberNum; ++i)
	{
		m_pAdaptInfo[i].m_DestFunctionValue = WSTSP::TSPTotalDistance(&(m_pCityInfoOfMembers[i]));
	}

	//排序:按距离,从小到大
	//相当于增加了记忆装置
	AdaptInfo l_TmpAdapt;
	CityInfo l_TmpCityInfo;
	for(i = 0; i < m_MemberNum; ++i)
	{
		l_MinDist = m_pAdaptInfo[i].m_DestFunctionValue;
		l_OptOrder = i;

		for(j = i; j < m_MemberNum; ++j)
		{
			if(l_MinDist > m_pAdaptInfo[j].m_DestFunctionValue)
			{
				l_MinDist = m_pAdaptInfo[j].m_DestFunctionValue;
				l_OptOrder = j;
			}
		}
		//m_pAdaptInfo只是中介作用,故不用严格调整次序
		m_pAdaptInfo[l_OptOrder] = m_pAdaptInfo[i];

		l_TmpCityInfo = m_pCityInfoOfMembers[i];
		m_pCityInfoOfMembers[i] = m_pCityInfoOfMembers[l_OptOrder];
		m_pCityInfoOfMembers[l_OptOrder] = l_TmpCityInfo;
	}

	//保护第一个序列,作为记忆单元
	i = 1;	
	j = 0;
	CityInfoOfMembersVector m_TmpVector;
	m_TmpVector.push_back(m_pCityInfoOfMembers[0]);

	while(j < m_MemberNum)
	{
		if(WSRandom::JudgeEven( 0.5*m_CrossProbability + 0.5 - 1.0*i/m_MemberNum ) ) 
		{
			m_TmpVector.push_back(m_pCityInfoOfMembers[i]);
			j ++;
		}
		i++;
		i %= m_MemberNum;
	}		

	m_pCityInfoOfMembers.clear();
	m_pCityInfoOfMembers = m_TmpVector;
	m_TmpVector.clear();
	return ;
}

/*
CalculateAdapt之模式2:执行比较标准的轮赌法;
采用轮赌法重新选取个体产生新的群体,选取后的种群大小不变.
*/
VOID WSGeneticAlogrith::CalculateAdapt_BetRing()
{
	INT i, j;
	FLOAT l_MinDist;
	INT l_OptOrder;	

	for(i = 0; i < m_MemberNum; ++i)
	{
		m_pAdaptInfo[i].m_DestFunctionValue = WSTSP::TSPTotalDistance(&(m_pCityInfoOfMembers[i]));
	}

	//排序:按距离,从小到大
	//相当于增加了记忆装置
	AdaptInfo l_TmpAdapt;
	CityInfo l_TmpCityInfo;
	for(i = 0; i < m_MemberNum; ++i)
	{
		l_MinDist = m_pAdaptInfo[i].m_DestFunctionValue;
		l_OptOrder = i;

		for(j = i; j < m_MemberNum; ++j)
		{
			if(l_MinDist > m_pAdaptInfo[j].m_DestFunctionValue)
			{
				l_MinDist = m_pAdaptInfo[j].m_DestFunctionValue;
				l_OptOrder = j;
			}
		}
		//m_pAdaptInfo只是中介作用,故不用严格调整次序
		m_pAdaptInfo[l_OptOrder] = m_pAdaptInfo[i];

		l_TmpCityInfo = m_pCityInfoOfMembers[i];
		m_pCityInfoOfMembers[i] = m_pCityInfoOfMembers[l_OptOrder];
		m_pCityInfoOfMembers[l_OptOrder] = l_TmpCityInfo;
	}

	//保护第一个序列,作为记忆单元
	i = 1;	
	j = 0;
	CityInfoOfMembersVector m_TmpVector;
	m_TmpVector.push_back(m_pCityInfoOfMembers[0]);

	std::vector<double> l_FitnessVect;
	for(i = 0; i < m_MemberNum; i ++)
	{
		l_FitnessVect.push_back(FITNESS_ALPHA*pow(FITNESS_ALPHA,i));
	}
	l_FitnessVect[0] *= 10000;
	for(i = 1; i < m_MemberNum; i ++)
	{
		l_FitnessVect[i] = l_FitnessVect[i]*10000 + l_FitnessVect[i - 1];
	}

	int l_RollRange = l_FitnessVect[m_MemberNum -1], l_RollNumber;

	for( i = 1; i < m_MemberNum; i++ )
	{
		l_RollNumber = WSRandom::GenRand(0, l_RollRange);
		for( j = 0; j < m_MemberNum; j++)
		{
			if( l_RollNumber <= l_FitnessVect[j] )
			{
				m_TmpVector.push_back( m_pCityInfoOfMembers[j]);
				break;
			}
		}
	}

	m_pCityInfoOfMembers.clear();
	m_pCityInfoOfMembers = m_TmpVector;
	m_TmpVector.clear();
	return ;
}
/*
CalculateAdapt之模式3:加入移民,防止早熟
采用标准轮赌法重新选取个体产生新的群体(限制选取的数目),然后将不足部分用移民替代;选取后的种群大小不变.
*/
VOID WSGeneticAlogrith::CalculateAdapt_Immigrant()
{
	INT i, j;
	FLOAT l_MinDist;
	INT l_OptOrder;	

	for(i = 0; i < m_MemberNum; ++i)
	{
		m_pAdaptInfo[i].m_DestFunctionValue = WSTSP::TSPTotalDistance(&(m_pCityInfoOfMembers[i]));
	}

	//排序:按距离,从小到大
	//相当于增加了记忆装置
	AdaptInfo l_TmpAdapt;
	CityInfo l_TmpCityInfo;
	for(i = 0; i < m_MemberNum; ++i)
	{
		l_MinDist = m_pAdaptInfo[i].m_DestFunctionValue;
		l_OptOrder = i;

		for(j = i; j < m_MemberNum; ++j)
		{
			if(l_MinDist > m_pAdaptInfo[j].m_DestFunctionValue)
			{
				l_MinDist = m_pAdaptInfo[j].m_DestFunctionValue;
				l_OptOrder = j;
			}
		}
		//m_pAdaptInfo只是中介作用,故不用严格调整次序
		m_pAdaptInfo[l_OptOrder] = m_pAdaptInfo[i];

		l_TmpCityInfo = m_pCityInfoOfMembers[i];
		m_pCityInfoOfMembers[i] = m_pCityInfoOfMembers[l_OptOrder];
		m_pCityInfoOfMembers[l_OptOrder] = l_TmpCityInfo;
	}

	//保护第一个序列,作为记忆单元
	i = 1;	
	j = 0;
	CityInfoOfMembersVector m_TmpVector;
	m_TmpVector.push_back(m_pCityInfoOfMembers[0]);

	std::vector<double> l_FitnessVect;
	for(i = 0; i < m_MemberNum; i ++)
	{
		l_FitnessVect.push_back(FITNESS_ALPHA*pow(FITNESS_ALPHA,i));
	}
	l_FitnessVect[0] *= 10000;
	for(i = 1; i < m_MemberNum; i ++)
	{
		l_FitnessVect[i] = l_FitnessVect[i]*10000 + l_FitnessVect[i - 1];
	}

	int l_RollRange = l_FitnessVect[m_MemberNum -1], l_RollNumber;

	// 2/3的个体由轮赌法决定;1/3的个体由移民组成
	INT l_MemberNum = 2.0*m_MemberNum / 3.0;
	for( i = 1; i < l_MemberNum; i++ )
	{
		l_RollNumber = WSRandom::GenRand(0, l_RollRange);
		for( j = 0; j < m_MemberNum; j++)
		{
			if( l_RollNumber <= l_FitnessVect[j] )
			{
				m_TmpVector.push_back( m_pCityInfoOfMembers[j]);
				break;
			}
		}
	}
	//////////////////////////////////////////////////////////////////////////////////////
	//移民进入
	l_TmpCityInfo.m_CityNum = m_BaseCityInfo.m_CityNum;
	l_TmpCityInfo.m_pCities = m_BaseCityInfo.m_pCities;

⌨️ 快捷键说明

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