C++实现遗传算法
本文实例讲述了C++实现简单遗传算法。分享给大家供大家参考。具体实现方法如下:
//CMVSOGA.h:mainheaderfilefortheCMVSOGA.cpp
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
#if!defined(AFX_CMVSOGA_H__45BECA_61EB_4A0E_9746_9A94D1CCF767__INCLUDED_)
#defineAFX_CMVSOGA_H__45BECA_61EB_4A0E_9746_9A94D1CCF767__INCLUDED_
#if_MSC_VER>1000
#pragmaonce
#endif//_MSC_VER>1000
#include"Afxtempl.h"
#definevariablenum14
classCMVSOGA
{
public:
CMVSOGA();
~CMVSOGA();
voidselectionoperator();
voidcrossoveroperator();
voidmutationoperator();
voidinitialpopulation(int,int,double,double,double*,double*);//种群初始化
voidgeneratenextpopulation();//生成下一代种群
voidevaluatepopulation();//评价个体,求最佳个体
voidcalculateobjectvalue();//计算目标函数值
voidcalculatefitnessvalue();//计算适应度函数值
voidfindbestandworstindividual();//寻找最佳个体和最差个体
voidperformevolution();
voidGetResult(double*);
voidGetPopData(CList<double,double>&);
voidSetFitnessData(CList<double,double>&,CList<double,double>&,CList<double,double>&);
private:
structindividual
{
doublechromosome[variablenum];//染色体编码长度应该为变量的个数
doublevalue;
doublefitness;//适应度
};
doublevariabletop[variablenum];//变量值
doublevariablebottom[variablenum];//变量值
intpopsize;//种群大小
//intgeneration;//世代数
intbest_index;
intworst_index;
doublecrossoverrate;//交叉率
doublemutationrate;//变异率
intmaxgeneration;//最大世代数
structindividualbestindividual;//最佳个体
structindividualworstindividual;//最差个体
structindividualcurrent;//当前个体
structindividualcurrent1;//当前个体
structindividualcurrentbest;//当前最佳个体
CList<structindividual,structindividual&>population;//种群
CList<structindividual,structindividual&>newpopulation;//新种群
CList<double,double>cfitness;//存储适应度值
//怎样使链表的数据是一个结构体????主要是想把种群作成链表。节省空间。
};
#endif
执行文件:
//CMVSOGA.cpp:implementationfile
//
#include"stdafx.h"
//#include"vld.h"
#include"CMVSOGA.h"
#include"math.h"
#include"stdlib.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
//CMVSOGA.cpp
CMVSOGA::CMVSOGA()
{
best_index=0;
worst_index=0;
crossoverrate=0;//交叉率
mutationrate=0;//变异率
maxgeneration=0;
}
CMVSOGA::~CMVSOGA()
{
best_index=0;
worst_index=0;
crossoverrate=0;//交叉率
mutationrate=0;//变异率
maxgeneration=0;
population.RemoveAll();//种群
newpopulation.RemoveAll();//新种群
cfitness.RemoveAll();
}
voidCMVSOGA::initialpopulation(intps,intgen,doublecr,doublemr,double*xtop,double*xbottom)//第一步,初始化。
{
//应该采用一定的策略来保证遗传算法的初始化合理,采用产生正态分布随机数初始化?选定中心点为多少?
inti,j;
popsize=ps;
maxgeneration=gen;
crossoverrate=cr;
mutationrate=mr;
for(i=0;i<variablenum;i++)
{
variabletop[i]=xtop[i];
variablebottom[i]=xbottom[i];
}
//srand((unsigned)time(NULL));//寻找一个真正的随机数生成函数。
for(i=0;i<popsize;i++)
{
for(j=0;j<variablenum;j++)
{
current.chromosome[j]=double(rand()%10000)/10000*(variabletop[j]-variablebottom[j])+variablebottom[j];
}
current.fitness=0;
current.value=0;
population.InsertAfter(population.FindIndex(i),current);//除了初始化使用insertafter外,其他的用setat命令。
}
}
voidCMVSOGA::generatenextpopulation()//第三步,生成下一代。
{
//srand((unsigned)time(NULL));
selectionoperator();
crossoveroperator();
mutationoperator();
}
//voidCMVSOGA::evaluatepopulation()//第二步,评价个体,求最佳个体
//{
//calculateobjectvalue();
//calculatefitnessvalue();//在此步中因该按适应度值进行排序.链表的排序.
//findbestandworstindividual();
//}
voidCMVSOGA::calculateobjectvalue()//计算函数值,应该由外部函数实现。主要因为目标函数很复杂。
{
inti,j;
doublex[variablenum];
for(i=0;i<popsize;i++)
{
current=population.GetAt(population.FindIndex(i));
current.value=0;
//使用外部函数进行,在此只做结果的传递。
for(j=0;j<variablenum;j++)
{
x[j]=current.chromosome[j];
current.value=current.value+(j+1)*pow(x[j],4);
}
////使用外部函数进行,在此只做结果的传递。
population.SetAt(population.FindIndex(i),current);
}
}
voidCMVSOGA::mutationoperator()//对于浮点数编码,变异算子的选择具有决定意义。
//需要guass正态分布函数,生成方差为sigma,均值为浮点数编码值c。
{
//srand((unsignedint)time(NULL));
inti,j;
doubler1,r2,p,sigma;//sigma高斯变异参数
for(i=0;i<popsize;i++)
{
current=population.GetAt(population.FindIndex(i));
//生成均值为current.chromosome,方差为sigma的高斯分布数
for(j=0;j<variablenum;j++)
{
r1=double(rand()%10001)/10000;
r2=double(rand()%10001)/10000;
p=double(rand()%10000)/10000;
if(p<mutationrate)
{
doublesign;
sign=rand()%2;
sigma=0.01*(variabletop[j]-variablebottom[j]);
//高斯变异
if(sign)
{
current.chromosome[j]=(current.chromosome[j]
+sigma*sqrt(-2*log(r1)/0.4323)*sin(2*3.1415926*r2));
}
else
{
current.chromosome[j]=(current.chromosome[j]
-sigma*sqrt(-2*log(r1)/0.4323)*sin(2*3.1415926*r2));
}
if(current.chromosome[j]>variabletop[j])
{
current.chromosome[j]=double(rand()%10000)/10000*(variabletop[j]-variablebottom[j])+variablebottom[j];
}
if(current.chromosome[j]<variablebottom[j])
{
current.chromosome[j]=double(rand()%10000)/10000*(variabletop[j]-variablebottom[j])+variablebottom[j];
}
}
}
population.SetAt(population.FindIndex(i),current);
}
}
voidCMVSOGA::selectionoperator()//从当前个体中按概率选择新种群,应该加一个复制选择,提高种群的平均适应度
{
inti,j,pindex=0;
doublep,pc,sum;
i=0;
j=0;
pindex=0;
p=0;
pc=0;
sum=0.001;
newpopulation.RemoveAll();
cfitness.RemoveAll();
//链表排序
//population.SetAt(population.FindIndex(0),current);//多余代码
for(i=1;i<popsize;i++)
{
current=population.GetAt(population.FindIndex(i));
for(j=0;j<i;j++)//从小到大用before排列。
{
current1=population.GetAt(population.FindIndex(j));//临时借用变量
if(current.fitness<=current1.fitness)
{
population.InsertBefore(population.FindIndex(j),current);
population.RemoveAt(population.FindIndex(i+1));
break;
}
}
//m=population.GetCount();
}
//链表排序
for(i=0;i<popsize;i++)//求适应度总值,以便归一化,是已经排序好的链。
{
current=population.GetAt(population.FindIndex(i));//取出来的值出现问题.
sum+=current.fitness;
}
for(i=0;i<popsize;i++)//归一化
{
current=population.GetAt(population.FindIndex(i));//population有值,为什么取出来的不正确呢??
current.fitness=current.fitness/sum;
cfitness.InsertAfter(cfitness.FindIndex(i),current.fitness);
}
for(i=1;i<popsize;i++)//概率值从小到大;
{
current.fitness=cfitness.GetAt(cfitness.FindIndex(i-1))
+cfitness.GetAt(cfitness.FindIndex(i));//归一化
cfitness.SetAt(cfitness.FindIndex(i),current.fitness);
population.SetAt(population.FindIndex(i),current);
}
for(i=0;i<popsize;)//轮盘赌概率选择。本段还有问题。
{
p=double(rand()%999)/1000+0.0001;//随机生成概率
pindex=0;//遍历索引
pc=cfitness.GetAt(cfitness.FindIndex(1));//为什么取不到数值???20060910
while(p>=pc&&pindex<popsize)//问题所在。
{
pc=cfitness.GetAt(cfitness.FindIndex(pindex));
pindex++;
}
//必须是从index~popsize,选择高概率的数。即大于概率p的数应该被选择,选择不满则进行下次选择。
for(j=popsize-1;j<pindex&&i<popsize;j--)
{
newpopulation.InsertAfter(newpopulation.FindIndex(0),
population.GetAt(population.FindIndex(j)));
i++;
}
}
for(i=0;i<popsize;i++)
{
population.SetAt(population.FindIndex(i),
newpopulation.GetAt(newpopulation.FindIndex(i)));
}
//j=newpopulation.GetCount();
//j=population.GetCount();
newpopulation.RemoveAll();
}
//current变化后,以上没有问题了。
voidCMVSOGA::crossoveroperator()//非均匀算术线性交叉,浮点数适用,alpha,beta是(0,1)之间的随机数
//对种群中两两交叉的个体选择也是随机选择的。也可取beta=1-alpha;
//current的变化会有一些改变。
{
inti,j;
doublealpha,beta;
CList<int,int>index;
intpoint,temp;
doublep;
//srand((unsigned)time(NULL));
for(i=0;i<popsize;i++)//生成序号
{
index.InsertAfter(index.FindIndex(i),i);
}
for(i=0;i<popsize;i++)//打乱序号
{
point=rand()%(popsize-1);
temp=index.GetAt(index.FindIndex(i));
index.SetAt(index.FindIndex(i),
index.GetAt(index.FindIndex(point)));
index.SetAt(index.FindIndex(point),temp);
}
for(i=0;i<popsize-1;i+=2)
{//按顺序序号,按序号选择两个母体进行交叉操作。
p=double(rand()%10000)/10000.0;
if(p<crossoverrate)
{
alpha=double(rand()%10000)/10000.0;
beta=double(rand()%10000)/10000.0;
current=population.GetAt(population.FindIndex(index.GetAt(index.FindIndex(i))));
current1=population.GetAt(population.FindIndex(index.GetAt(index.FindIndex(i+1))));//临时使用current1代替
for(j=0;j<variablenum;j++)
{
//交叉
doublesign;
sign=rand()%2;
if(sign)
{
current.chromosome[j]=(1-alpha)*current.chromosome[j]+
beta*current1.chromosome[j];
}
else
{
current.chromosome[j]=(1-alpha)*current.chromosome[j]-
beta*current1.chromosome[j];
}
if(current.chromosome[j]>variabletop[j])//判断是否超界.
{
current.chromosome[j]=double(rand()%10000)/10000*(variabletop[j]-variablebottom[j])+variablebottom[j];
}
if(current.chromosome[j]<variablebottom[j])
{
current.chromosome[j]=double(rand()%10000)/10000*(variabletop[j]-variablebottom[j])+variablebottom[j];
}
if(sign)
{
current1.chromosome[j]=alpha*current.chromosome[j]+
(1-beta)*current1.chromosome[j];
}
else
{
current1.chromosome[j]=alpha*current.chromosome[j]-
(1-beta)*current1.chromosome[j];
}
if(current1.chromosome[j]>variabletop[j])
{
current1.chromosome[j]=double(rand()%10000)/10000*(variabletop[j]-variablebottom[j])+variablebottom[j];
}
if(current1.chromosome[j]<variablebottom[j])
{
current1.chromosome[j]=double(rand()%10000)/10000*(variabletop[j]-variablebottom[j])+variablebottom[j];
}
}
//回代
}
newpopulation.InsertAfter(newpopulation.FindIndex(i),current);
newpopulation.InsertAfter(newpopulation.FindIndex(i),current1);
}
ASSERT(newpopulation.GetCount()==popsize);
for(i=0;i<popsize;i++)
{
population.SetAt(population.FindIndex(i),
newpopulation.GetAt(newpopulation.FindIndex(i)));
}
newpopulation.RemoveAll();
index.RemoveAll();
}
voidCMVSOGA::findbestandworstindividual()
{
inti;
bestindividual=population.GetAt(population.FindIndex(best_index));
worstindividual=population.GetAt(population.FindIndex(worst_index));
for(i=1;i<popsize;i++)
{
current=population.GetAt(population.FindIndex(i));
if(current.fitness>bestindividual.fitness)
{
bestindividual=current;
best_index=i;
}
elseif(current.fitness<worstindividual.fitness)
{
worstindividual=current;
worst_index=i;
}
}
population.SetAt(population.FindIndex(worst_index),
population.GetAt(population.FindIndex(best_index)));
//用最好的替代最差的。
if(maxgeneration==0)
{
currentbest=bestindividual;
}
else
{
if(bestindividual.fitness>=currentbest.fitness)
{
currentbest=bestindividual;
}
}
}
voidCMVSOGA::calculatefitnessvalue()//适应度函数值计算,关键是适应度函数的设计
//current变化,这段程序变化较大,特别是排序。
{
inti;
doubletemp;//alpha,beta;//适应度函数的尺度变化系数
doublecmax=100;
for(i=0;i<popsize;i++)
{
current=population.GetAt(population.FindIndex(i));
if(current.value<cmax)
{
temp=cmax-current.value;
}
else
{
temp=0.0;
}
/*
if((population[i].value+cmin)>0.0)
{temp=cmin+population[i].value;}
else
{temp=0.0;
}
*/
current.fitness=temp;
population.SetAt(population.FindIndex(i),current);
}
}
voidCMVSOGA::performevolution()//演示评价结果,有冗余代码,current变化,程序应该改变较大
{
if(bestindividual.fitness>currentbest.fitness)
{
currentbest=population.GetAt(population.FindIndex(best_index));
}
else
{
population.SetAt(population.FindIndex(worst_index),currentbest);
}
}
voidCMVSOGA::GetResult(double*Result)
{
inti;
for(i=0;i<variablenum;i++)
{
Result[i]=currentbest.chromosome[i];
}
Result[i]=currentbest.value;
}
voidCMVSOGA::GetPopData(CList<double,double>&PopData)
{
PopData.RemoveAll();
inti,j;
for(i=0;i<popsize;i++)
{
current=population.GetAt(population.FindIndex(i));
for(j=0;j<variablenum;j++)
{
PopData.AddTail(current.chromosome[j]);
}
}
}
voidCMVSOGA::SetFitnessData(CList<double,double>&PopData,CList<double,double>&FitnessData,CList<double,double>&ValueData)
{
inti,j;
for(i=0;i<popsize;i++)
{
current=population.GetAt(population.FindIndex(i));//就因为这一句,出现了很大的问题。
for(j=0;j<variablenum;j++)
{
current.chromosome[j]=PopData.GetAt(PopData.FindIndex(i*variablenum+j));
}
current.fitness=FitnessData.GetAt(FitnessData.FindIndex(i));
current.value=ValueData.GetAt(ValueData.FindIndex(i));
population.SetAt(population.FindIndex(i),current);
}
FitnessData.RemoveAll();
PopData.RemoveAll();
ValueData.RemoveAll();
}
#re:C++遗传算法源程序
/********************************************************************
Filename:aiWorld.h
Purpose:遗传算法,花朵演化。
Id:
Copyright:
Licence:
*********************************************************************/
#ifndefAIWORLD_H_
#defineAIWORLD_H_
#include<iostream>
#include<ctime>
#include<cstdlib>
#include<cmath>
#definekMaxFlowers10
usingstd::cout;
usingstd::endl;
classai_World
{
public:
ai_World()
{
srand(time(0));
}
~ai_World(){}
inttemperature[kMaxFlowers];//温度
intwater[kMaxFlowers];//水质
intsunlight[kMaxFlowers];//阳光
intnutrient[kMaxFlowers];//养分
intbeneficialInsect[kMaxFlowers];//益虫
intharmfulInsect[kMaxFlowers];//害虫
intcurrentTemperature;
intcurrentWater;
intcurrentSunlight;
intcurrentNutrient;
intcurrentBeneficialInsect;
intcurrentHarmfulInsect;
/**
第一代花朵
*/
voidEncode();
/**
花朵适合函数
*/
intFitness(intflower);
/**
花朵演化
*/
voidEvolve();
/**
返回区间[start,end]的随机数
*/
inlineinttb_Rnd(intstart,intend)
{
if(start>end)
return0;
else
{
//srand(time(0));
return(rand()%(end+1)+start);
}
}
/**
显示数值
*/
voidshow();
};
//-----------------------------------------------------------------//
voidai_World::Encode()
//-----------------------------------------------------------------//
{
inti;
for(i=0;i<kMaxFlowers;i++)
{
temperature[i]=tb_Rnd(1,75);
water[i]=tb_Rnd(1,75);
sunlight[i]=tb_Rnd(1,75);
nutrient[i]=tb_Rnd(1,75);
beneficialInsect[i]=tb_Rnd(1,75);
harmfulInsect[i]=tb_Rnd(1,75);
}
currentTemperature=tb_Rnd(1,75);
currentWater=tb_Rnd(1,75);
currentSunlight=tb_Rnd(1,75);
currentNutrient=tb_Rnd(1,75);
currentBeneficialInsect=tb_Rnd(1,75);
currentHarmfulInsect=tb_Rnd(1,75);
currentTemperature=tb_Rnd(1,75);
currentWater=tb_Rnd(1,75);
currentSunlight=tb_Rnd(1,75);
currentNutrient=tb_Rnd(1,75);
currentBeneficialInsect=tb_Rnd(1,75);
currentHarmfulInsect=tb_Rnd(1,75);
}
//-----------------------------------------------------------------//
intai_World::Fitness(intflower)
//-----------------------------------------------------------------//
{
inttheFitness;
theFitness=abs(temperature[flower]-currentTemperature);
theFitness=theFitness+abs(water[flower]-currentWater);
theFitness=theFitness+abs(sunlight[flower]-currentSunlight);
theFitness=theFitness+abs(nutrient[flower]-currentNutrient);
theFitness=theFitness+abs(beneficialInsect[flower]-currentBeneficialInsect);
theFitness=theFitness+abs(harmfulInsect[flower]-currentHarmfulInsect);
return(theFitness);
}
//-----------------------------------------------------------------//
voidai_World::Evolve()
//-----------------------------------------------------------------//
{
intfitTemperature[kMaxFlowers];
intfitWater[kMaxFlowers];
intfitSunlight[kMaxFlowers];
intfitNutrient[kMaxFlowers];
intfitBeneficialInsect[kMaxFlowers];
intfitHarmfulInsect[kMaxFlowers];
intfitness[kMaxFlowers];
inti;
intleastFit=0;
intleastFitIndex;
for(i=0;i<kMaxFlowers;i++)
if(Fitness(i)>leastFit)
{
leastFit=Fitness(i);
leastFitIndex=i;
}
temperature[leastFitIndex]=temperature[tb_Rnd(0,kMaxFlowers-1)];
water[leastFitIndex]=water[tb_Rnd(0,kMaxFlowers-1)];
sunlight[leastFitIndex]=sunlight[tb_Rnd(0,kMaxFlowers-1)];
nutrient[leastFitIndex]=nutrient[tb_Rnd(0,kMaxFlowers-1)];
beneficialInsect[leastFitIndex]=beneficialInsect[tb_Rnd(0,kMaxFlowers-1)];
harmfulInsect[leastFitIndex]=harmfulInsect[tb_Rnd(0,kMaxFlowers-1)];
for(i=0;i<kMaxFlowers;i++)
{
fitTemperature[i]=temperature[tb_Rnd(0,kMaxFlowers-1)];
fitWater[i]=water[tb_Rnd(0,kMaxFlowers-1)];
fitSunlight[i]=sunlight[tb_Rnd(0,kMaxFlowers-1)];
fitNutrient[i]=nutrient[tb_Rnd(0,kMaxFlowers-1)];
fitBeneficialInsect[i]=beneficialInsect[tb_Rnd(0,kMaxFlowers-1)];
fitHarmfulInsect[i]=harmfulInsect[tb_Rnd(0,kMaxFlowers-1)];
}
for(i=0;i<kMaxFlowers;i++)
{
temperature[i]=fitTemperature[i];
water[i]=fitWater[i];
sunlight[i]=fitSunlight[i];
nutrient[i]=fitNutrient[i];
beneficialInsect[i]=fitBeneficialInsect[i];
harmfulInsect[i]=fitHarmfulInsect[i];
}
for(i=0;i<kMaxFlowers;i++)
{
if(tb_Rnd(1,100)==1)
temperature[i]=tb_Rnd(1,75);
if(tb_Rnd(1,100)==1)
water[i]=tb_Rnd(1,75);
if(tb_Rnd(1,100)==1)
sunlight[i]=tb_Rnd(1,75);
if(tb_Rnd(1,100)==1)
nutrient[i]=tb_Rnd(1,75);
if(tb_Rnd(1,100)==1)
beneficialInsect[i]=tb_Rnd(1,75);
if(tb_Rnd(1,100)==1)
harmfulInsect[i]=tb_Rnd(1,75);
}
}
voidai_World::show()
{
//cout<<"/ttemperaturewatersunlightnutrientbeneficialInsectharmfulInsect/n";
cout<<"current/t"<<currentTemperature<<"/t"<<currentWater<<"/t";
cout<<currentSunlight<<"/t"<<currentNutrient<<"/t";
cout<<currentBeneficialInsect<<"/t"<<currentHarmfulInsect<<"/n";
for(inti=0;i<kMaxFlowers;i++)
{
cout<<"Flower"<<i<<":";
cout<<temperature[i]<<"/t";
cout<<water[i]<<"/t";
cout<<sunlight[i]<<"/t";
cout<<nutrient[i]<<"/t";
cout<<beneficialInsect[i]<<"/t";
cout<<harmfulInsect[i]<<"/t";
cout<<endl;
}
}
#endif//AIWORLD_H_
//test.cpp
#include<iostream>
#include"ai_World.h"
usingnamespacestd;
intmain()
{
ai_Worlda;
a.Encode();
//a.show();
for(inti=0;i<10;i++)
{
cout<<"Generation"<<i<<endl;
a.Evolve();
a.show();
}
system("PAUSE");
return0;
}
希望本文所述对大家的C++程序设计有所帮助。