/*------------------*/
/*这是遗传算法的文件*/
/*------------------*/

#ifndef GENALG_H
#define GENALG_H

#include "Defines.h"
#include "Params.h"
#include "Utils.h"
#include "File.h"


//基因组结构体
struct SGenome
{
	//染色体的序列
	vector <DataType>	vecDatas;
	//适应度
	double  dFitness;
	//距离
	double  dDistance;
	//构造函数
	SGenome():dFitness(0),dDistance(0){}
	//带参构造
	SGenome(vector<DataType> w, double f): vecDatas(w), dFitness(f), dDistance(0){}
	//重载'<'的排序方法
	friend bool operator<(const SGenome& lhs, const SGenome& rhs)
	{
		return (lhs.dFitness < rhs.dFitness);
	}
};

//遗传算法类
class CGenAlg
{
	private:
		//基因组群体
		vector <SGenome>	m_vecPop;
		//当前最优秀的基因
		SGenome m_sFittestGenome;
		//群体的数量
		int	m_iPopSize;
		//每代最长距离
		double m_dMaxDistance;
		//全局最短距离
		double m_dMinDistance;
		//整个群体的总适应度
		double	m_dTotalFitness;
		//整个群体的最好适应度
		double	m_dBestFitness;
		//整个群体的平均适应度
		double	m_dAverageFitness;
		//整个群体的最坏的适应度
		double	m_dWorstFitness;
		//记录当前进化了几代
		int	m_cGeneration;
		//杂交函数
		void Crossover(	const	vector<DataType> &,
						const	vector<DataType> &,
								vector<DataType> &,
								vector<DataType> &);
		//变异函数
		void Mutate(vector<DataType> &);
		//用转盘法
		SGenome GetChromoRoulette();
		//选择最优的一部分直接进入下一代
		void GrabNBest(int, const int, vector<SGenome> &);
		//适合度排序
		//void FitnessScaleRank();
		//计算各种适合度
		void CalculateBestWorstAvTot();
		//计算基因组适应度
		void CalculateDistance(SGenome &);
		//重置
		void Reset();

	public:
		//构造函数
		CGenAlg();
		//每一代进化一次
		vector<SGenome> Epoch();
		//重置基因
		inline void             SetChromos(vector<SGenome> Pop)	{m_vecPop = Pop;}
		//得到基因
		inline vector<SGenome>  GetChromos()        const {return m_vecPop;}
		//得到最佳基因
		inline SGenome          GetFittestGenome()  const {return m_sFittestGenome;}
		//返回本次最小距离
		inline double MaxDistance()		const	{return m_dMaxDistance;}
		//返回本次最小距离
		inline double MinDistance()		const	{return m_dMinDistance;}
		//返回平均适应度
		inline double AverageFitness()  const	{return m_dTotalFitness / CParams::iPopSize;}
		//返回总适应度
		inline double BestFitness()		const	{return m_dBestFitness;}
		//返回总适应度
		inline double TotalFitness()    const	{return m_dTotalFitness;}
};

#endif
