寻大牛讲解一下遗传算法的源程序

phoenixyao 2009-06-30 04:53:53
在网上找到一个遗传算法的源代码,想学习一下。遇到一个问题:

在源程序中,有个GT_Corssover(),不明白是什么意思,求大牛讲解一下。

还有,最近在用遗传算法做隐函数的数据拟合程序,有经验的兄弟能给帮下忙吗?

源程序:


/*-------------------------------------------------------------|
|求函数的最大值 : |
| f(x,y)=21.5+x*sin(4*PI*x)+y*sin(20*PI*y) |
| |
| 定义域 D: -3<=x<=12.1 , 4.1<=y<=5.8 |
| 注: 目前最好结果:f(11.6255448,5.7250441)=38.8502944790207 |
|------------------------------------------------------------*/
#include <iostream.h>
#include <stdio.h>
#include <string>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <iomanip.h>

using namespace std;

#define PCROSSOVER 0.95 // 交叉概率
// 
#define PMUTATION 0.15 // 变异概率
#define POPSIZE 100 // 和数数目
#define MAXGEN 10000 // 世代数目
#define PI 3.14159265 // PI
#define lbound1 -3 // X 上限
#define ubound1 12.1 // X 下限
#define lbound2 4.1 // Y 上限
#define ubound2 5.8 // Y 下限
//double PMUTATION=0.08;
////////////////////////////Individual Structure///////////////////////////
typedef struct Individual
{
double a1; // 改为a1进行尝试
double a2; // 改为a2进行尝试
double fitness;
double rfitness;
double cfitness;
}Individual;

Individual Population[POPSIZE+1];
Individual temp[POPSIZE];//定义一个临时存储空间存储将要放入新群体的个体

double TotalFitness=0.0f;
//int curBest=0;

double lbound[1],ubound[1];

double a;

int curGen=0;
//////////////////////////Function Prototype//////////////////////////////
void Initialize();

void EvaluateFitness();

Individual Roulette();

void Mutate(Individual *indiv);

void Crossover(Individual *dad, Individual *mom);

void GT_Crossover(int m);

int GetWorst(Individual *indiv, int size);

void Elitist();

void Report();

//////////////////////////Main()//////////////////////////////////////
int main()
{
srand((int)time(NULL));

int change=1;

clock_t start, finish;
start=clock();

Initialize();
EvaluateFitness();
while(change&&curGen<MAXGEN)
{
EvaluateFitness();
Individual dad, mom;
int i=0;
while(i<POPSIZE)
{
dad=Roulette();
do{
mom = Roulette();
}while((dad.a1==mom.a1) && (dad.a2==mom.a2));

Crossover(&dad,&mom);
Mutate(&dad);
Mutate(&mom);
temp[i++]=dad;
temp[i++]=mom;
}
GT_Crossover(rand()%3 + 7);
//将后代个体放入新群体中
for (i=0; i<POPSIZE; i++)
Population[i] = temp[i];

EvaluateFitness();

Elitist();
//Report();
// int j; // 暂时没用到的变量
// for(j=1;j<POPSIZE;j++)
// if((Population[j].x1!=Population[j-1].x1)||(Population[j].x2!=Population[j-1].x2)) break;
// if (POPSIZE==j) change=0;
curGen++;
//PMUTATION=PMUTATION-0.008;
}

finish=clock();
cout<<endl;
//for (int i=0;i<POPSIZE;i++)
// cout<<Population[i].fitness<<endl;
printf("%.13f\n",Population[POPSIZE].fitness);
// cout<<"进化"<<curGen<<"代后的最佳适应值为"<<Population[POPSIZE].fitness<<"耗时"<<(double)finish/1000<<"s"<<endl;
// if(getchar()!='\n') ;
return 0;
}//main


//////////////////////////////Function Definition//////////////////////////////////


//--------------------------------- 初始化种群 ------------------------------------------
void Initialize()
{

for(int i = 0; i < POPSIZE; i++)
{
Population[i].a1 = lbound1 + (ubound1-lbound1) * (double)rand() / RAND_MAX; // 改为a1进行尝试
Population[i].a2 = lbound2 + (ubound2-lbound2) * (double)rand() / RAND_MAX; // 改为a2进行尝试
Population[i].fitness = 0.0f;
Population[i].rfitness = 0.0f;
Population[i].cfitness = 0.0f;
}
return;
}

//---------------------------------- 适应度计算 -------------------------------------------
void EvaluateFitness()
{
double x = 0;
TotalFitness = 0;
int i;
// 计算个体的适应值
for (i = 0; i < POPSIZE; i++)
{
double x,y;
x = Population[i].a1; // 改为a1进行尝试
y = Population[i].a2; // 改为a1进行尝试
Population[i].fitness = 21.5 + x * sin(4 * PI * x) + y * sin(20 * PI * y); /////考虑加上一个数避免出现负值
}

//群体总适应值
for (i = 0; i<POPSIZE; i++)
TotalFitness += Population[i].fitness;

//计算个体相对适应值
if(0==TotalFitness)
exit(0);
else
for (i = 0; i < POPSIZE; i++)
Population[i].rfitness = Population[i].fitness / TotalFitness; //需要处理除数为0的情况

//计算个体累积适应值
Population[0].cfitness = Population[0].rfitness;

for (i=1;i<POPSIZE;i++)
Population[i].cfitness = Population[i].rfitness + Population[i-1].cfitness;
return;
}


//----------------------- 通过轮盘选择策略从旧群体中获取个体 -----------------------------
Individual Roulette()
{
if(Population[POPSIZE - 1].cfitness <= (double)rand() / RAND_MAX)
return Population[POPSIZE];
for (int i = 0; i < POPSIZE; i++)
{
if (Population[i].cfitness > (double)rand() / RAND_MAX)
return Population[i];
}
if(i == POPSIZE)
{
cout<<"ERROR";
exit(1);
}
}


//---------------------------------- 交叉 ---------------------------------------
void Crossover(Individual *dad, Individual *mom)
{
if((double)rand()/RAND_MAX<PCROSSOVER)
{
double u1,u2;
double v1,v2;
a = (double)curGen / (double)MAXGEN; //a如何取比较合适
u1 = (*dad).a1;
u2 = (*dad).a2;
v1 = (*mom).a1;
v2 = (*mom).a2;

(*dad).a1 = v1*a + u1 * (1-a);
(*dad).a2 = v2*a + u2 * (1-a);

(*mom).a1 = u1*a + v1 * (1-a);
(*mom).a2 = u2*a + v2 * (1-a);
}
return;
}

void GT_Crossover(int m)
{
Individual tempindiv;
int i, *index, *sel, select, size;
double *r, s;
index = new int[POPSIZE];
sel = new int[m];
r = new double[m];

for(i=0; i < POPSIZE; i++)
index[i] = i;
size = POPSIZE;
for(i = 0; i < m; i++)
{
select = rand()%size;
sel[i] = index[select];
index[select] = index[--size];
}

s = r[0] = -0.5 + (double)rand()/RAND_MAX * 2;
for(i = 1; i < m - 1; i++)
{
r[i] = -0.5 + (double)rand()/RAND_MAX*(1.5 - s);
s+= r[i];
}
r[m - 1] = 1 - s;

tempindiv.a1 = 0;
tempindiv.a2 = 0;

if((double)rand()/RAND_MAX < 0.1)
for(i=0; i < m; i++)
tempindiv.a1 += Population[sel[i]].a1 * r[i];
if((double)rand()/RAND_MAX < 0.1)
for(i = 0; i < m; i++)
tempindiv.a2 += Population[sel[i]].a2 * r[i];

double x=tempindiv.a1;
double y=tempindiv.a2;
tempindiv.fitness = 21.5 + x * sin(4 * PI * x) + y * sin(20 * PI * y);

int worstindex = GetWorst(Population, POPSIZE);
if(tempindiv.fitness > Population[worstindex].fitness)
Population[worstindex] = tempindiv;
delete[] index;
delete[] sel;
delete[] r;
}

//------------------------------------单点变异---------------------------------------
void Mutate(Individual *indiv)
{
if ((double)rand() / RAND_MAX < PMUTATION)
{
(*indiv).a1 = lbound1 + (ubound1-lbound1) * ((double)rand() / RAND_MAX);
(*indiv).a2 = lbound2 + (ubound2-lbound2) * ((double)rand() / RAND_MAX);
}

return;
}


//------------------------------实施精英策略-------------------------------------
void Elitist()
{
double best,worst;
int bestIndex,worstIndex;
best = Population[0].fitness;
worst = Population[0].fitness;
for (int i=0;i<POPSIZE-1; ++i)
{
if(Population[i].fitness > Population[i+1].fitness)
{
if (Population[i].fitness >= best)
{
best = Population[i].fitness;
bestIndex = i;
}
if (Population[i+1].fitness <= worst)
{
worst = Population[i+1].fitness;
worstIndex = i + 1;
}
}
else
{
if (Population[i].fitness <= worst)
{
worst = Population[i].fitness;
worstIndex = i;
}
if (Population[i+1].fitness >= best)
{
best = Population[i+1].fitness;
bestIndex = i + 1;
}
}
}

//若新群体的最好个体比前一代的最好个体还好,则新群体的个体放入POPSIZE单元中;
//否则用前一代的最佳个体置换当前群体的最坏个体
if (best >= Population[POPSIZE].fitness)
{
Population[POPSIZE] = Population[bestIndex];
}
else
{
Population[worstIndex] = Population[POPSIZE];
}
}

int GetWorst(Individual *indiv, int size)
{
int worstindex = 0;
for(int i = 1; i < size; i++)
{
if(indiv[i].fitness < indiv[worstindex].fitness)
worstindex = i;
}
return worstindex;
}

//----------------------- 显示基因编码 ------------------------

void Report()
{
cout<<"TotalFitness is "<<TotalFitness<<endl;
cout.setf(ios::left,ios::adjustfield);
cout.fill(' ');
cout<<setw(16) << "变量值";
cout<<setw(10) << "Fitness";
cout<<setw(18) << "RelativeFitness";
cout<<setw(20) << "CumulativeFitness" << endl;
cout.setf(ios::right,ios::adjustfield);
for(int i=0;i<POPSIZE;i++)
{
cout<<setw(16) << Population[i].a1 << " " << Population[i].a2;
cout<<setw(10) << Population[i].fitness;
cout<<setw(18) << Population[i].rfitness;
cout<<setw(20) << Population[i].cfitness << endl;
}
return;
}
...全文
291 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
guo2chen 2010-05-21
  • 打赏
  • 举报
回复
收藏了,有空看看。
yymt168 2010-03-01
  • 打赏
  • 举报
回复
遗传算法,,有空去了解下
V68V6 2010-03-01
  • 打赏
  • 举报
回复
别的上头都说了。遗传程序这类型的智能程序来源于计算机科学算法研究者对于自然界的仿生。。。

其实就是对于生物遗传基因杂交变异的抽象模拟,所以你可以参照生物学的杂交变异去对照理解这个算法。

主体思想清楚了,剩下的就是代码阅读的能力了。
nut799 2010-03-01
  • 打赏
  • 举报
回复
杂交的动作,最基本的杂交策略是将父母两条染色体,随即生成一个位置,按这个 位置拆开 ,将父母两条染色体 拆开重组, 生成新的两条染色体。

还有别的一些杂交策略
sqi007 2010-03-01
  • 打赏
  • 举报
回复
遗传算法的关键是如何对父代进行基因编码以及对子代进行有效的选择。
phoenixyao 2010-02-27
  • 打赏
  • 举报
回复
谢谢一楼的帮助,这个一直困扰着我,一直都没上来看看。

谢谢了。
dragonfly001 2009-07-16
  • 打赏
  • 举报
回复
顶下,先要明白遗传算法的原来 ,再看代码会容易理解些,学习了
仗剑逗二哈 2009-07-15
  • 打赏
  • 举报
回复
不行了不行了,头疼~!
sailtoyouSCU 2009-07-13
  • 打赏
  • 举报
回复
看函数名字就猜得到是杂交 而已 代码太长看不懂
丈八涯 2009-07-10
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 bottlebox 的回复:]
GT_Crossover(int m) 应该是自定义的一种杂交策略,在你的主程序中并没有用,除非调下顺序
//将后代个体放入新群体中
for (i=0; i <POPSIZE; i++)
Population[i] = temp[i];
GT_Crossover(rand()%3 + 7); //放后面来

另外这个策略也不适合这个例子,得出的个体大多不合要求(x,y不在定义域内)
[/Quote]

佩服1楼的耐心,俺是看不下去.
cheng_fengming 2009-07-09
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 abcdef0966 的回复:]
看下遗传算法的原理就好了
[/Quote]
恩,先在网上看一下遗传算法相关的思想,然后在看看这个c程序,我看每一个函数前面都有程序的作用,我想知道了原理再看程序应该能懂了
abcdef0966 2009-07-03
  • 打赏
  • 举报
回复
看下遗传算法的原理就好了
  • 打赏
  • 举报
回复
以前作业做过遗传算法,现在不太记得了,你可以在上网看看大体思路,没这么难吧。
瓶盒 2009-07-01
  • 打赏
  • 举报
回复
GT_Crossover(int m) 应该是自定义的一种杂交策略,在你的主程序中并没有用,除非调下顺序
//将后代个体放入新群体中
for (i=0; i <POPSIZE; i++)
Population[i] = temp[i];
GT_Crossover(rand()%3 + 7); //放后面来

另外这个策略也不适合这个例子,得出的个体大多不合要求(x,y不在定义域内)
lanytin 2009-07-01
  • 打赏
  • 举报
回复
C看的不是很懂,而且代码这么长。
还是替楼主顶一下。

33,028

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧