遗传算法入门--连载7
2014-01-29 00:00
232 查看
连载之七 算法进化的时代 Epoch |
3.4.2 Epoch(时代) 遗传算法类中最烩灵人口的内容就是Epoch()方法。这就是我们前面3.3节讲过的遗传算法的那个循环。它是这个类的主要工作场所。这一方法与所有工作或多或少都有连系。下面就让我们来更近距离地考察它 ... void CgaBob::epoch() { UpdateFitnessScores(); 在每一个epoch循环内所要做的第一件事情,就是测试染色体群中每一个成员的适应性分数。 UpdateFitnessScores()是用来对每个基因组的二进制染色体编码进行译码的函数,而由它再把译码所得到的一系列结果,也就是由代表东、南、西、北四个方向的整数,发送给 CBobsMap::TestRoute。后者检查 Bob在地 图中游走了多远,并根据 Bob离开出口的最终距离,返回一个相应的适应性分数。让我通过很少几行源码来告诉你怎样计算 Bob的适应性分数: int DiffX = abs(posX - m_iEndX); int DiffY = abs(posY - m_iEndY); 这里,DiffX和DiffY 就是 Bob所在格子相对于迷宫出口的水平和垂直偏离值。 试考察图 3.6 的例子。灰色小格代表 Bob通过迷宫的路程,上面写着B的小格是他 最终所到达的地方。在这一位置上,Diffx = 3,而 DiffY = 0。 图 3.6 Bob尝试寻找迷宫出口 return 1/(double)(DiffX+DiffY+1); 这最后一行式子就是计算 Bob 的适应性分数。它把 DiffX与DiffY 两个数字 加起来然后求倒数。DiffX与DiffY的和数中还加了一个1,这是为了确保除法不会 出现一个分母为零的错误,如果 Bob 到达出口,Diffx + DiffY = O。 UpdateFitnessScores 也保持对每一代里适应分最高的基因组、以及与所有基 因组相关的适应性分数的跟踪。这些数值在执行轮盘赌选择时需要使用。 到此,你已经知道了函数 UpdateFitnessScores() 所做的全部工作,让我们回到Epoch函数的讨论.由于在每一Epoch中都需要创建一个新的基因组群,因此,当它们在创建出来时(每次创建2个基因组),我们需要寻找一些地方来保存它们。 //现在创建一个新的群体 int NewBabies = 0; //为婴儿基因组创建存储器 vector<SGenome> vecBabyGenomes; 现在继续讨论遗传算法循环中所处理的各种事务。 while (NewBabies < m_iPopSize) { //用轮盘赌法选择 2 个上辈(parents) SGenome mum = RouletteWheelSelection(); SGenome dad = RouletteWheelSelection(); 在每次迭代过程中,我们需要选择2个基因组来作为2个新生婴儿的染色体的上辈。我今后常喜欢把这2个上辈分别称为dad(父亲)和mum(母亲),因为他们将来就是要生孩子的)。你应该回忆得起来,一个基因组的适应性愈强,则由轮盘赌方法选择作为父母的几率也愈大。 //杂交操作 SGenome baby1, baby2; Crossover(mum.vecBits ,dad.vecBits, baby1.vecBits, baby2.vecBits); 以上2行的工作是:创建2个空白基因组,这是2个婴儿;它们与所选的上辈一起传递给杂交函数Crossover() 。这一函数执行了杂交(需要依赖于所设杂交 率m_dCrossoverRate来进行),并把新的染色体的2进制位串存放到2个新生婴儿 baby1和baby2之中。 // 变异操作 Mutate(baby1.vecBits); Mutate(baby2.vecBits); 以上这2步是对婴儿实行突变!这听起来可怕,但这对他们是有利的。一个婴儿的位的突变概率依赖于所选的参数 m_dMutationRate(突变率)。 // 把2个新生因个婴儿加入新群体 vecBabyGenomes.push_back(baby1); vecBabyGenomes.push_back(baby2); NewBabies += 2; } 这2个新生后代最终要加入到新的群体中,这样就完成了一次 Loop 的迭代过程。这一过程需要不断重复,直到创建出来的后代总量和初始群体的大小相同。 // 把所有婴儿复制到初始群体 m_vecGenomes = vecBabyGenomes; // 代的计数加1 ++m_iGeneration; } 这里,原有的那个群体由新生一代所组成的群体来代替,并把代的计数器加1, 以跟踪当前的代。就是这么一些了!呵呵,不难吧? 这一 Epoch函数将无止境地重复,直到染色体收敛到了一个解,或到用户要求 停止时为止。下面我将会向你显示上述各种操作(算子)的代码,但在此首先让我 们来聊聊,应该如何确定使用的参数值。 |