遗传算法GA
来源:互联网 发布:联想扬天x110知乎 编辑:程序博客网 时间:2024/05/19 13:07
摘要
写华为CodeCraft的时候,尝试使用了遗传算法进行搜索,以下是模仿网上教程写的代码,我把它进行了简单的封装,常用参数都可以直接改了,可以作为一个小的Demo来使用。
使用的Qt环境,所以注意把Qt相关的内容删掉。
目标函数默认为求当前基因节点的最大和,比如当前的y_totalNodeNumber 为800,则理论上最优值为800,我用随机数初始化了一个随机值,用来测试收敛的速度,这个函数可以根据使用需要进行更改,遗传策略之类的东西也是可以自定义的。除了淘汰概率!!!!
同时,我设置了两种迭代控制,分别是规定迭代次数和迭代的时间,分别通过y_startIteration(1000000)
和y_startIterationByTime(5000)
进行控制,前者单位为次数,后者为毫秒。
这里放一张运行图片,初始值为402,跑了5秒钟,输出了762,感觉还阔以噻 :)
代码
#include <QCoreApplication>#include <iostream>#include <time.h>#include <stdlib.h>using namespace std;void y_initiateGroups();void y_travelsal();double y_fitness(int n);void y_pickChroms();void y_crossover();void y_mutation();void swapChrom(int i, int j);const int y_totalNodeNumber = 800; //每个个体中的基因节点个数,也就是节点数目const int y_totalGroupNumber = 4; //种群个体个数,如为n,表示当前种群中有n个个体参与繁衍和变异const float y_failRate = 0.5; //每一代的淘汰比率const float y_mutateRate = 0.2; //变异概率typedef struct Chrom // 结构体类型,为单个染色体的结构;{ short int bit[y_totalNodeNumber];//一共6bit来对染色体进行编码,其中1位为符号位。取值范围-64~+64 int fit ;//适应值 double rfit;//相对的fit值,即所占的百分比 double cfit;//积累概率}chrom;chrom y_groupCurrent [y_totalGroupNumber]; // 初始种群规模chrom y_groupNext [y_totalGroupNumber]; // 更新后种群规模//初始化种群void y_initiateGroups(){ double sum = 0.0; srand(clock() + (unsigned)time(NULL)); for(int i=0; i<y_totalGroupNumber; ++i){ for(int j=0; j<y_totalNodeNumber; j++){ y_groupCurrent[i].bit[j] = (short)(rand() % 2); } } for(int i=0; i<y_totalGroupNumber; ++i){ y_groupNext[i] = y_groupCurrent[i]; y_groupCurrent[i].fit = y_fitness(i); sum = sum + y_groupCurrent[i].fit; } //计算适应值得百分比,该参数是在用轮盘赌选择法时需要用到的 for (int i=0; i<y_totalGroupNumber; ++i) { y_groupCurrent[i].rfit = y_groupCurrent[i].fit/sum; y_groupCurrent[i].cfit = 0;//将其初始化为0 }}int Partition(Chrom a[], int left, int right)///7行代码{ int i = left - 1;///初始化一定要赋值好。 for (int j = left;j <= right - 1;j++) { if (a[j].fit > a[right].fit) {///把right这个作为轴了。 i++;///这个i坐标左边的值就是比a[right]小的。 swapChrom(i,j);///必须交换一下。 } } swapChrom(i+1,right);///最后把i+1和right交换,这样轴就是i+1了必须是保证i+1上当初就是作为标杆的a[right]啊。 return i + 1;}void Qsort(Chrom a[], int left, int right){ if (left < right) { int q = Partition(a, left, right); Qsort(a, left, q - 1); Qsort(a, q + 1, right); }}void swapChrom(int i, int j){ chrom temp ; temp = y_groupNext[j]; y_groupNext[j] = y_groupNext[i]; y_groupNext[i] = temp;}//从种群中选出若干个体进行交叉、变异,这里采用排序法来选择,即每次选择都选出适应度最高的两个个体void y_pickChroms(){// Qsort(y_groupNext, 0, y_totalGroupNumber); //以下为冒泡法 int i ,j; chrom temp ; // 中间变量 int top = y_totalGroupNumber-1; for(i=0; i<top; i++) // 根据个体适应度来排序;(冒泡法) { for(j=0; j<top-i; j++) { if(y_groupNext[j+1].fit > y_groupNext[j].fit) { temp = y_groupNext[j+1]; y_groupNext[j+1] = y_groupNext[j]; y_groupNext[j] = temp; } } }}void y_crossover(){ srand(clock() + (unsigned)time(NULL)); int random = rand() % y_totalNodeNumber; // 随机产生交叉点,交叉点控制在0到y_totalGroupNumber之间; int lastParentIndex = (int)((1-y_failRate)*y_totalGroupNumber); int i,k ; for(i=0; i<random; ++i) { //采取第一名和剩下的所有母节点进行繁殖的策略 k=1; for(int j=0; j<lastParentIndex; j+=2){ y_groupNext[j+lastParentIndex].bit[i] = y_groupNext[0].bit[i]; y_groupNext[j+lastParentIndex+1].bit[i] = y_groupNext[k].bit[i]; ++k; } } for(i=random; i<y_totalNodeNumber; ++i) // crossing the bits beyond the cross point index { //采取第一名和剩下的所有母节点进行繁殖的策略 k=1; for(int j=0; j<lastParentIndex; j+=2){ y_groupNext[j+lastParentIndex].bit[i] = y_groupNext[k].bit[i]; y_groupNext[j+lastParentIndex+1].bit[i] = y_groupNext[0].bit[i]; ++k; } } for(i=lastParentIndex; i<y_totalGroupNumber; ++i) { y_groupNext[i].fit= y_fitness(i); // 为新个体计算适应度值; }}void y_mutation(){ int row ,col; srand(clock() + (unsigned)time(NULL)); int random = rand()%1000; // 随机产生到之间的数; int mutate = 1000*y_mutateRate; //变异操作也要遵从一定的概率来进行,一般设置为0到0.5之间 if(random < mutate) //变异率为y_mutate,所以是以小概率进行变异!! { col=rand()%y_totalNodeNumber; // 随机产生要变异的基因位号; row=rand()%y_totalGroupNumber; // 随机产生要变异的染色体号; if(y_groupNext[row].bit[col]==0) // 1变为0; { y_groupNext[row].bit[col]=1 ; } else if (y_groupNext[row].bit[col]==1) // 0变为1; { y_groupNext[row].bit[col]=0; } y_groupNext[row].fit= y_fitness(row); // 计算变异后的适应度值; }}//输出当前的种群void y_travelsal(){ for(int i=0; i<y_totalGroupNumber; i++) { for(int j=0; j<y_totalNodeNumber; j++) { cout<<y_groupCurrent[i].bit[j]<<" "; } cout<<y_groupCurrent[i].fit<<endl; }}//输出下一代种群void y_travelsal_next(){ for(int i=0; i<y_totalGroupNumber; i++) { for(int j=0; j<y_totalNodeNumber; j++) { cout<<y_groupNext[i].bit[j]<<" "; } cout<<y_groupNext[i].fit<<endl; }}//传入行号,对y_groupCurrent的第n行进行适应度计算,返回适应度数值double y_fitness(int n){ int sum = 0; for(int i=0; i<y_totalNodeNumber; ++i) { sum += y_groupNext[n].bit[i]; } return (double)sum;}//开始迭代void y_startIteration(int num) //num为迭代次数{ for(int i=0; i<num; i++) // 开始迭代; { y_pickChroms(); // 挑选优秀个体; y_crossover(); // 交叉得到新个体; y_mutation(); // 变异得到新个体; } // 等待迭代终止;}void y_startIterationByTime(int timeLimit){ int starttime = clock(); int curtime = clock(); int itr = 0; while(1) { if(curtime - starttime >= timeLimit) break; y_pickChroms(); // 挑选优秀个体; y_crossover(); // 交叉得到新个体; y_mutation(); // 变异得到新个体; itr++; curtime = clock(); } cout<<"iter: "<<itr<<endl;}int main(int argc, char *argv[]){ QCoreApplication a(argc, argv); int starttime = clock(); y_initiateGroups(); y_pickChroms(); cout<<y_groupCurrent[0].fit<<endl; //y_startIteration(1000000); y_startIterationByTime(5000); y_pickChroms(); cout<<y_groupNext[0].fit<<" Time: "<<clock()-starttime<<endl; return a.exec();}
1 0
- 遗传算法(GA)
- GA遗传算法解析
- 遗传算法(GA)
- 遗传算法GA
- 遗传算法GA
- GA遗传算法
- 遗传算法(Genetic Algorithm,GA)
- 遗传算法(genetic algorithm, GA)
- GA遗传算法(Genetic Algorithm)
- 遗传算法(GA)干货
- GA入门:遗传算法原理与应用
- 遗传算法GA笔记之简述
- 遗传算法(GA)的matlab实现
- 机器学习笔记之遗传算法(GA)
- GA遗传算法Matlab版本实例注释
- 初识Matlab遗传算法工具箱 ga
- GA遗传算法入门到掌握
- 基于遗传算法(GA)的神经网络训练算法
- 根据用户输入数字n打印nn乘法表
- UI界面的更新
- WAV格式分析
- LeNet的C语言实现
- MySQL入门2章
- 遗传算法GA
- js实现二分查找
- 一个屌丝程序猿的人生(六十三)
- java代码通过ssh免密操作远程服务器shell
- 设计模式--MVVM
- Day2
- S3C2451_lcd 函数封装
- c++ 小数的四舍五入
- 冒泡排序&选择排序