遗传算法入门简单实例
来源:互联网 发布:怎么快速成为淘宝达人 编辑:程序博客网 时间:2024/05/17 00:08
参考:
http://www.360doc.com/content/15/0309/15/13726687_453806200.shtml
http://www.cnblogs.com/liyuwang/p/5988358.html
最近在自学《演化计算》(潘正君著),了解了演化算法的基本基本步骤。在丽丽的帮助下找到了一个SGA的入门小程序,结合程序,理解演化算法中简单遗传算法的基本步骤。
一、问题描述
f(x1, x2) = x1 * x1 + x2 * x2,求解 f 的最大值(x1、x2为 0 ~ 7之间的正整数)。
二、算法实现
1、基本模块(具体遗传算法的基本步骤可以查书)
a、初始化种群(二进制编码)
b、评价种群(计算目标值、适应值、更新当前最坏个体)
c、产生下一代种群(选择——轮盘式选择、交叉——单点交叉、变异)
d、输出结果
2、具体思想
a、初始化种群(二进制编码)
x1、x2分别用3位二进制数来表示,将它们连在一起组成一个6位二进制数。用字符串来保存。
例:基因型 X = 101110,表现型 x1 = 5,x2 = 6。
种群使用一个结构体来表示,包括
b、评价种群(计算目标值、适应值)
本例中,目标值和适应值相同就采用一个整型变量来存储,fitness。
c、评价种群(更新当前最坏个体)
例中,额外定义一个历史最好个体和当前最坏个体。每次调用评价种群函数更新历史最好个体,并找到当前最坏个体,用历史最好个体更新当前最坏个体。
e、产生下一代种群(选择——轮盘式选择)
计算种群中所有个体的适应值之和sfitness。
计算每个个体相对适应值的大小 cfitness[i] += fitness / sfitness - cfitness[i - 1]。
随机生成 0 ~ 1 之间的数,来确定每个个体被选中的次数。
f、产生下一代种群(交叉——单点交叉)
打乱种群中个体的下标,重新排列种群中的个体。
循环,每次两个个体。
判断随机概率是否低于交叉概率。
是,则随机生成一个单点的下标。
将两个个体从单点下标开始到个体末端的基因位进行交换。
g、产生下一代种群(变异)
对每个个体的每一位随机生成概率。
若概率低于变异概率,则将这一位取反。
3、注意问题
a、随机数生成
由于rand()直接产生的是伪随机,所以在前面添上:
inclue <time.h>
rand((int)time(0));
b、种群中个体的个数、交叉概率和变异概率都会对算法产生影响,慎重选取
这里个体个数为:10
交叉概率为:0.6
变异概率为:0.001
#include <iostream>#include <time.h>#include <stdio.h>using namespace std;#define Popsize 10 //population size#define ChromLength 6 //length of chromosometypedef struct{char chrom[ChromLength + 1];//a chromosome of individualint fitness; //取fitness(适应值) = value(目标值)}Individual;int gen; //current generation no.int maxgen = 100; //maximum generationint bestidx; //最好个体下标int sfitness; //适应值总和double pc = 0.6; //交叉概率double pm = 0.001; //变异概率Individual pop[Popsize + 1]; //old populationIndividual hisbestind; //历史最佳个体Individual curworsind; //当前最差个体void initpop(void); //初始化种群void evaluatepop(void); //评估种群并优化void calfitness(void); //计算目标值(适应值)int decchrom(char *chrom, int l, int r); //二进制转十进制void findbestandworsind(void); ////更新历史最好和当前最坏个体,并用历史最好替换当前最坏void gennexpop(void); //产生下一代种群void selectpop(void); //选择算子,轮盘式选择void crosspop(void); //交叉算子,单点交叉void mutatepop(void); //变异算子,对每个个体每一位进行概率变异void output(void); //输出//初始化种群void initpop(void){int i, j;srand((int)time(0));for(i = 0; i < Popsize; i++){for(j = 0; j < ChromLength; j++){if(rand() % 2 == 0)pop[i].chrom[j] = '0';elsepop[i].chrom[j] = '1';}pop[i].chrom[j] = '\0';}bestidx = 0;}//评估种群并优化void evaluatepop(void){calfitness();findbestandworsind();}//计算目标值(适应值)//目标函数为f(x) = x1 * x1 + x2 * x2;void calfitness(void){int i, x1, x2;for(i = 0; i < Popsize; i++){x1 = decchrom(pop[i].chrom, 0, 2);x2 = decchrom(pop[i].chrom, 3, 5);pop[i].fitness = x1 * x1 + x2 * x2;}//求适应值总和sfitness = 0;for(i = 0; i < Popsize; i++)sfitness += pop[i].fitness;}//二进制转十进制int decchrom(char *chrom, int l, int r){int i, tmp = 1, dec = 0;for(i = r; i >= l; i--){dec += tmp * (chrom[i] - '0');tmp *= 2;}return dec;}//更新历史最好和当前最坏个体,并用历史最好替换当前最坏void findbestandworsind(void){int i, j = 0;if(gen == 0)hisbestind = pop[0];curworsind = pop[0];for(i = 0; i < Popsize; i++){if(hisbestind.fitness < pop[i].fitness)hisbestind = pop[i];else if(curworsind.fitness > pop[i].fitness){curworsind = pop[i];j = i;}}pop[j] = hisbestind; }//产生下一代种群void gennexpop(void){selectpop();crosspop();mutatepop();}//选择算子,轮盘式选择void selectpop(void){int i, j;double cfitness[Popsize + 1], p;Individual newpop[Popsize + 1];//计算轮盘分布cfitness[0] = (double)pop[0].fitness / sfitness;for(i = 1; i < Popsize; i++)cfitness[i] = (double)pop[i].fitness / sfitness + cfitness[i - 1];//用轮盘进行随机选取,产生新的种群for(i = 0; i < Popsize; i++){p = rand() % 1000 / 1000.0;j = 0;while(p > cfitness[j]) j++;newpop[i] = pop[j];}//更新种群for(i = 0; i < Popsize; i++)pop[i] = newpop[i];}//交叉算子,单点交叉void crosspop(void){int i, j, tmp, poi, idx[Popsize + 1];double p;char c;//打乱种群下标,重新排列for(i = 0; i < Popsize; i++)idx[i] = 1;for(i = 0; i < Popsize; i++){poi = rand() % (Popsize - i);tmp = idx[poi];idx[poi] = idx[i];idx[i] = tmp;}//随机选取交叉点,进行交叉for(i = 0; i < Popsize; i += 2){p = rand() % 1000 /1000.0;if(p < pc){poi = rand() % ChromLength;for(j = poi; j < ChromLength; j++){c = pop[i].chrom[j];pop[i].chrom[j] = pop[i + 1].chrom[j];pop[i + 1].chrom[j] = c;}}}}//变异算子,对每个个体每一位进行概率变异void mutatepop(void){int i, j;double p;for(i = 0; i < Popsize; i++){for(j = 0; j < ChromLength; j++){p = rand() % 1000 / 1000.0;if(p < pm){if(pop[i].chrom[j] == '0')pop[i].chrom[j] = '1';elsepop[i].chrom[j] = '0';}}}}//输出void output(void){double avg = (double)sfitness / Popsize;cout << "gen = " << gen << ", avg = " << avg << ", best = " << hisbestind.fitness << ", chrom = " << hisbestind.chrom << endl;}int main(){gen = 0;initpop();evaluatepop();while(gen < maxgen){gen++;gennexpop();evaluatepop();output();}return 0;}
- 遗传算法入门简单实例
- 遗传算法入门实例
- 遗传算法简单实例
- 遗传算法简单实例
- 遗传算法简单实例
- 遗传算法简单入门
- 简单的遗传算法实例
- 简单的遗传算法java实例
- 遗传算法实例
- 遗传算法实例
- 遗传算法实例
- MATLAB遗传算法实例
- 遗传算法入门
- 遗传算法入门
- 遗传算法入门
- 遗传算法入门
- 遗传算法入门
- 遗传算法入门
- Java虚拟机基础
- 如何卸载 sdlx
- Spring之搭建环境
- java 之前的一些配置及简单运行
- 安全框架之shrio-简介
- 遗传算法入门简单实例
- uva12105 Bigger is Better
- 奔三奶爸初学php心得记录(第三天)
- 网络检索技巧
- c++实现Cohen-Sutherlan算法(直线段剪裁)
- c语言基础知识回顾4
- 营养与维生素D
- ffmpeg学习笔记(5)
- vijos1064迎春舞会之数字舞蹈