由于《自然计算》课程布置了一道关于遗传算法的编程题,所以大概花了四天时间来学习遗传算法的基本概念、程序设计流程、c++编程实现。在学习过程中,也遇到了不少问题,通过自己不断的分析思考,查阅书籍(《c++ primer》解决一些成员函数使用的问题)和结合网上的一些已有程序(a href=”http://blog.csdn.net/ilikeprograming/article/details/25702861”),使得问题一一解决。
实现代码如下:
main.cpp
/*********************************************************
Copyright: zhangchao
Author: superman
Date: 2016-10-28
Description: 遗传算法求解最优值
Function: f(x1,x2)=21.5+x1*sin(4*Pi*x1)+x2*sin(20*Pi*x2)
Range: x1[-3,12.1],x2[4.1,5.8]
**********************************************************/
#include "geneticAlgorithm.h"
//#define MaxGen 5
int main(int argc,char *argv[])
{
multimap m_mapData;
m_mapData.insert(make_pair(-2.687969,5.361653));
m_mapData.insert(make_pair(0.474101,4.170144));
m_mapData.insert(make_pair(10.419457,4.661461));
m_mapData.insert(make_pair(6.159951,4.109598));
m_mapData.insert(make_pair(-2.301286,4.477282));
m_mapData.insert(make_pair(11.788084,4.174346));
m_mapData.insert(make_pair(9.342067,5.121702));
m_mapData.insert(make_pair(-0.330256,4.694977));
m_mapData.insert(make_pair(11.671267,4.873501));
m_mapData.insert(make_pair(11.446273,4.171908));
srand( unsigned( time(0) ) );//srand(time(NULL)); 产生随机数
cout<<"----------------------------------------------------------------------------------------------------"< fitnGloMax; //存储全局最优eval-fitness
vector get_x1fitn;
vector get_x2fitn;
int MaxGen;
cout<<"Please input the number of generations : ";
cin>>MaxGen;
int gen=1;
vector binMutVec; //定义经变异后生成的二进制序列
vector binVec;
binVec=encoding(m_mapData); //编码,保存为二进制序列,将生成的chromosome(bin) 保存到vector中
cout< evalFitness;
if(gen==1){
evalFitness=evalFit(decoding(binVec),fitnMax,x1max,x2max); //计算适应度,通过解码
}else{
evalFitness=evalFit(decoding(binMutVec),fitnMax,x1max,x2max);
}
fitnGloMax.push_back(fitnMax);
get_x1fitn.push_back(x1max);
get_x2fitn.push_back(x2max);
vector binSelVec;
binSelVec=selection(binVec,evalFitness,m_mapData.size()); //选择
vector binCroVec;
binCroVec=crossover(binSelVec);
binMutVec=mutation(binCroVec);
++gen;
}while(gen<=MaxGen);
auto biggest=max_element(fitnGloMax.begin(),fitnGloMax.end()); //搜索fitnGloMax中的最大值(最优值)的迭代器
auto sub=biggest-fitnGloMax.begin(); //sub:相对位置
auto xx1=get_x1fitn.begin()+sub; //xx1,xx2:对应的x值的迭代器
auto xx2=get_x2fitn.begin()+sub;
cout<<"The fitness of best chromosome : "<<*biggest
<<"\t [x1,x2]="<< " ["<<*xx1<<","<<*xx2<<"]"<
geneticAlgorithm.h
#include
#include
#include
#include
#include
以上是所有实现过程调用到的函数,具体的函数后面有时间再分享给大家。
以下对编程过程遇到的问题总结如下:
1、在编码过程中,要把x的范围从十进制转换到二进制,并一一对应。一般流程:2^n-1 < (xMax-xMin )* 10^4 < 2^n;n是对应所需二进制的位数。decimal=(m-aj)/(bj-aj)* (2^18-1) +0.5,让小数点四舍五入。注意不要直接把十进制数 *10^n,转化为二进制。
2、termination condition是什么?本例根据循环次数来判定。还可以根据最大适应度和种群间相同个体数与总个体数的比值来判定。
3、本例中,刚开始是采用map < double,double > 类型来存储x1,x2的值,但是在经过一轮迭代之后,种群中的优秀的染色体(二进制码)是有相同的,所以经过解码后得到的x1、x2的值会出现相同的情况。所以map显然不满足要求,mutilmap类型刚好符合这种情况。
4、轮盘赌算法。在筛选过程中很重要的选择方法。每个个体的适应度占总适应度的比值,然后按照后一个比值叠加到前一个比值上得到一个轮盘值,照此下去,直到最后轮盘值为1。就这样构成了一个完整的轮盘。