# 游戏编程中的人工智能技术-遗传算法入门（四）

834人阅读 评论(0)

struct SGenome
{
vector<int> vecBits;

double		dFitness;

SGenome():dFitness(0){}

SGenome(const int num_bits):dFitness(0)
{
//create a random bit string
for (int i=0; i<num_bits; ++i)
{
vecBits.push_back(RandInt(0, 1)); //随机的产生一个染色体，vecBits.push_back表示往vecBits向量里塞值，RandInt(0, 1)表示塞的值要么是0，要么是1

}
}
};


class CgaBob
{
private:

//the population of genomes
vector<SGenome>	m_vecGenomes; //定义一个向量m_vecGenomes，注意这个向量的每一个元素不是int型的了，是一个SGenome结构体，没错，每个元素都是一个结构体

//size of population
int             m_iPopSize;  //种群中染色体数

double          m_dCrossoverRate; //杂交率

double          m_dMutationRate; //变异率

//how many bits per chromosome
int             m_iChromoLength; //染色体的长度

//how many bits per gene
int             m_iGeneLength; //基因的长度

int             m_iFittestGenome; //染色体的适应度

double          m_dBestFitnessScore;//最佳染色体的适应度

double          m_dTotalFitnessScore;//所有染色体适应度总和

int             m_iGeneration;       //代数

//create an instance of the map class
CBobsMap        m_BobsMap;

//we use another CBobsMap object to keep a record of
//the best route each generation as an array of visited
//cells. This is only used for display purposes.
CBobsMap		m_BobsBrain;

//lets you know if the current run is in progress.
bool			m_bBusy;

void        Mutate(vector<int> &vecBits);

void        Crossover(const vector<int>	&mum,  //父类
const vector<int> &dad,<span style="white-space:pre">	</span>       //父类
vector<int>       &baby1,<span style="white-space:pre">	</span>//子类
vector<int>       &baby2);<span style="white-space:pre">	</span>//子类

SGenome&		RouletteWheelSelection(); //轮盘赌

//updates the genomes fitness with the new fitness scores and calculates
//the highest fitness and the fittest member of the population.
void			  UpdateFitnessScores();//适应度更新

//decodes a vector of bits into a vector of directions (ints)
vector<int>	Decode(const vector<int> &bits);

//converts a vector of bits into decimal. Used by Decode.
int				  BinToInt(const vector<int> &v);

//creates a start population of random bit strings
void			  CreateStartPopulation();

public:

CgaBob(double cross_rat,
double mut_rat,
int    pop_size,
int    num_bits,
int    gene_len):m_dCrossoverRate(cross_rat),
m_dMutationRate(mut_rat),
m_iPopSize(pop_size),
m_iChromoLength(num_bits),
m_dTotalFitnessScore(0.0),
m_iGeneration(0),
m_iGeneLength(gene_len),
m_bBusy(false)

{
CreateStartPopulation();
}

void			Run(HWND hwnd);

void			Render(int cxClient, int cyClient, HDC surface);

void			Epoch();

//accessor methods
int				Generation(){return m_iGeneration;}
int				GetFittest(){return m_iFittestGenome;}
bool      Started(){return m_bBusy;}
void			Stop(){m_bBusy = false;}
};

#endif

void CgaBob::CreateStartPopulation()
{
//clear existing population
m_vecGenomes.clear();

for (int i=0; i<m_iPopSize; i++)
{
m_vecGenomes.push_back(SGenome(m_iChromoLength));
}

//reset all variables
m_iGeneration		 = 0;
m_iFittestGenome	 = 0;
m_dBestFitnessScore  = 0;
m_dTotalFitnessScore = 0;
}

CreateStartPopulation()：产生初始种群。

for (int i=0; i<m_iPopSize; i++)

m_vecGenomes：这个就是上述那个vector<SGenome> m_vecGenomes，所以里面存放的都是一个一个的SGenome。

m_vecGenomes.push_back(SGenome(m_iChromoLength)); 把一个一个的SGenome储存到m_vecGenomes中去，SGenome(m_iChromoLength)对应的是SGenome结构体定义中的

	SGenome(const int num_bits):dFitness(0)
{
//create a random bit string
for (int i=0; i<num_bits; ++i)
{
vecBits.push_back(RandInt(0, 1));
}
}

void CgaBob::Crossover( const vector<int> &mum,//父代1
vector<int>		  &baby1,//子代1
vector<int>		  &baby2)//子代2
{
//just return parents as offspring dependent on the rate
//or if parents are the same
if ( (RandFloat() > m_dCrossoverRate) || (mum == dad)) //如果两个父代相同
{
baby1 = mum;//那么也就没有交叉的必要

return;
}

//determine a crossover point
int cp = RandInt(0, m_iChromoLength - 1);//如果两个父代不相同，那么随机选择一个位。

//swap the bits
for (int i=0; i<cp; ++i)
{
baby1.push_back(mum[i]);//cp位之前，不变化
}

for (i=cp; i<mum.size(); ++i)
{
baby2.push_back(mum[i]);
}
}

void CgaBob::Mutate(vector<int> &vecBits)
{
for (int curBit=0; curBit<vecBits.size(); curBit++) 遍历染色体中的每个位
{
//do we flip this bit?
if (RandFloat() < m_dMutationRate)//随机选一个数，若这个数小于变异率的话（变异率通常很低很低）
{
//flip the bit
vecBits[curBit] = !vecBits[curBit]; 将该位取反
}
}//next bit
}

SGenome& CgaBob::RouletteWheelSelection()
{
double fSlice	= RandFloat() * m_dTotalFitnessScore; //随机选一个数，当然这个数必须在适应度总和的范围之内，<span style="font-family: Arial, Helvetica, sans-serif;">RandFloat()是一个0~1之间的浮点数</span>

double cfTotal	= 0.0;

int	SelectedGenome = 0;

for (int i=0; i<m_iPopSize; ++i)//遍历种群中的每一个染色体
{

cfTotal += m_vecGenomes[i].dFitness;//适应度总和进行计算

if (cfTotal > fSlice) //轮盘赌，当总和大于随机数时
{
SelectedGenome = i;//表示这个染色体被选中
break;
}
}

return m_vecGenomes[SelectedGenome];
}

if (cfTotal > fSlice) //轮盘赌，当总和大于随机数时
{
SelectedGenome = i;//表示这个染色体被选中
break;
}

 编号 个体串 x 适应值 百分比（%） 累计百分比（%） 选中次数 S01 01101 13 169 14.30 14.30 1 S02 11001 25 625 52.88 67.18 2 S03 01000 8 64 5.41 72.59 0 S04 10010 18 324 27.41 100 1

void CgaBob::UpdateFitnessScores()
{
m_iFittestGenome		= 0;
m_dBestFitnessScore		= 0;
m_dTotalFitnessScore	= 0;

CBobsMap TempMemory;

//update the fitness scores and keep a check on fittest so far
for (int i=0; i<m_iPopSize; ++i)
{
//decode each genomes chromosome into a vector of directions
vector<int> vecDirections = Decode(m_vecGenomes[i].vecBits);

//get it's fitness score
m_vecGenomes[i].dFitness = m_BobsMap.TestRoute(vecDirections, TempMemory);

//update total
m_dTotalFitnessScore += m_vecGenomes[i].dFitness;

//if this is the fittest genome found so far, store results
if (m_vecGenomes[i].dFitness > m_dBestFitnessScore)
{
m_dBestFitnessScore = m_vecGenomes[i].dFitness;

m_iFittestGenome = i;

m_BobsBrain = TempMemory;

//Has Bob found the exit?
if (m_vecGenomes[i].dFitness == 1)
{
//is so, stop the run
float a = m_vecGenomes[i].dFitness;
vector<int> b = m_vecGenomes[i].vecBits;
m_bBusy = false;
}
}

TempMemory.ResetMemory();

}//next genome
}

if (m_vecGenomes[i].dFitness > m_dBestFitnessScore)//如果当前的适应度值为最优值，则将最优值替换，并且记录此染色体用作画图用
{
m_dBestFitnessScore = m_vecGenomes[i].dFitness;

m_iFittestGenome = i;

m_BobsBrain = TempMemory;//<span style="font-family: Arial, Helvetica, sans-serif;">记录此染色体用作画图用</span>

//Has Bob found the exit?
if (m_vecGenomes[i].dFitness == 1)//若适应度值到1了，就表示到终点了
{
//is so, stop the run
float a = m_vecGenomes[i].dFitness;//这个是我加的用来调试的（by qixing)
vector<int> b = m_vecGenomes[i].vecBits;//同样用来调试的（qx）
m_bBusy = false;//搞定
}
}

void CgaBob::Epoch()
{

UpdateFitnessScores();//适应值更新，这个放最后我感觉也可以吧

//Now to create a new population
int NewBabies = 0;

//create some storage for the baby genomes
vector<SGenome> vecBabyGenomes;

while (NewBabies < m_iPopSize)
{
//select 2 parents
SGenome mum = RouletteWheelSelection();//轮盘赌，选择父代1
SGenome dad = RouletteWheelSelection();<span style="font-family: Arial, Helvetica, sans-serif;">//轮盘赌，选择父代2</span>

//operator - crossover
SGenome baby1, baby2;

//operator - mutate
Mutate(baby1.vecBits);//变异
Mutate(baby2.vecBits);

vecBabyGenomes.push_back(baby1); //产生子代1
vecBabyGenomes.push_back(baby2);//产生子代2

NewBabies += 2; //+2后继续进行上述操作，依次结束后产生新的种群。
}

//copy babies back into starter population
m_vecGenomes = vecBabyGenomes;

//increment the generation counter
++m_iGeneration;
}

个人资料
等级：
访问量： 1万+
积分： 232
排名： 32万+
文章分类
文章存档