?? ga.cpp
字號(hào):
//本程序利用直接編碼,用于漸近衰減模型
//f(x,y)=0.5-(pow(sin(sqrt(x*x+y*y)),2)-0.5)/pow((1+0.001*(x*x+y*y)),2)參數(shù)的估算
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <ctype.h>
//#include <values.h>
#include <string.h>
//定義控制參數(shù)
#define POPSIZE 150 //定義種群的大小
#define NVARS 2 //定義參數(shù)的個(gè)數(shù)
//#define PXOVER 0.9 //定義交叉率
//#define PMUTATION 0.15 //定義突變率
typedef struct //定義基因,種群中的一個(gè)個(gè)體
{
double chrom[NVARS]; //變量串(本例中是a,b,c三參數(shù))
double lsquare; //個(gè)體的評(píng)價(jià)度,存放的是評(píng)價(jià)函數(shù)的返回值,即誤差平方和的大小
double r; //個(gè)體的相關(guān)系數(shù)
int fitness; //相關(guān)適應(yīng)度
}individual;
static double pc,pm1,pm2;
static individual newpop[POPSIZE+1]; //新種群
static individual oldpop[POPSIZE+1]; //老種群
static int location[POPSIZE+1]; //排序后的個(gè)體的位置
static int gen; //當(dāng)前代數(shù)
static int maxgen; //最大代數(shù)
static int change=0; //適應(yīng)性沒有改進(jìn)的代數(shù)
static double a[NVARS],b[NVARS]; //變量的上下限 a[]下限,b[]上限
static double maxlsquare=-1.0e10,minlsquare=1.0e50;//,fx;
//隨機(jī)數(shù)發(fā)生器的宏定義
#define rdint(i) (rand()%(int)(i))
#define rdft() ((double)rdint(16384)/(16383.0))
#define rnd(a,b) (rdint((int)(b)-(int)(a)+1)+(int)(a))
//評(píng)估函數(shù):使用到用戶定義的衰減模型,每次如果被改變則要重新編譯,當(dāng)前所用的模型是f(x)=a-b*c^x
//返回值是誤差的平方和,顯然返回值越大則表示評(píng)價(jià)的結(jié)果越差
double evaluate(double *prms) //參數(shù)為個(gè)體基因中的參數(shù)串charm[]
{
//int i;
double x, serr=0.0;
x=sqrt(prms[0]*prms[0]+prms[1]*prms[1]);
serr=0.5-(pow(sin(x),2)-0.5)/pow((1+0.001*(prms[0]*prms[0]+prms[1]*prms[1])),2);
return (serr);
}
//用于確定數(shù)組選擇區(qū)域函數(shù),通過快速排序法實(shí)現(xiàn),(二分法排序,升序)
void quick_sort(double *item,int left,int right,int *locat)
//item:需排序的數(shù)組,left:數(shù)組的下標(biāo)下界,
//right:數(shù)組的下標(biāo)上界,locat:數(shù)組中各元素在原數(shù)組中的位置
{
double fa,fb;
int i,j,k;
i=left;j=right;
fa=item[(left+right)/2];
do{
while((item[i]<fa)&&(i<right))i++;
while((fa<item[j])&&(j>left))j--;
if(i<=j)
{
fb=item[i];
item[i]=item[j];
item[j]=fb;
k=locat[i];
locat[i]=locat[j];
locat[j]=k;
i++;j--;
}
}while(i<=j);
if(left<j) quick_sort(item,left,j,locat);
if(i<right)quick_sort(item,i,right,locat);
}
//用于確定在種群中的個(gè)體選擇位置和規(guī)格化適應(yīng)度的函數(shù)
void normalfitness(individual *pop) //參數(shù)是種群數(shù)組newpop[]等
{
double fit[POPSIZE];
int i;
for(i=0;i<POPSIZE;i++)
{
fit[i]=pop[i].lsquare; //個(gè)體的適應(yīng)性
location[i]=i;
}
quick_sort(fit,0,POPSIZE-1,location); //按適應(yīng)度由小到大排序
for(i=0;i<POPSIZE;i++)
pop[location[i]].fitness=2*(i+1); //重新計(jì)算適應(yīng)度,計(jì)算后原先適應(yīng)度大的將變小
//因初始適應(yīng)度是用評(píng)價(jià)函數(shù)的返回值表示的,而評(píng)價(jià)函數(shù)返回的是誤差,
//故原先的適應(yīng)度大的表示實(shí)際誤差大,實(shí)際的適應(yīng)性較差
//規(guī)格化運(yùn)算后,適應(yīng)度的值正比地 反映了該個(gè)體的適應(yīng)程度
}
//初始化種群的函數(shù),用隨機(jī)生成的數(shù)初始化參數(shù)a,b,c;
//用評(píng)估函數(shù)的返回值作為個(gè)體的適應(yīng)度,同時(shí)規(guī)格化適應(yīng)度確定個(gè)體的選擇位置
void initpop(void)
{
int i,j;
//double fx,bt;
double m;
for(i=0;i<POPSIZE;i++)
{
for(j=0;j<NVARS;j++)
{
m=rdft();
oldpop[i].chrom[j]=a[j]+m*(b[j]-a[j]); //個(gè)體中的參數(shù)a,b,c隨即生成
// printf("\nmmmmmmm=%lf\n",m);
}
oldpop[i].lsquare=evaluate(oldpop[i].chrom);//用評(píng)估函數(shù)的返回值作為個(gè)體的適應(yīng)度
oldpop[i].fitness=0;
//oldpop[i].r=cal_coeff(oldpop[i].chrom);//
}
normalfitness(oldpop);//確定個(gè)體的選擇位置和規(guī)格化適應(yīng)度
oldpop[POPSIZE]=oldpop[location[POPSIZE-1]];
}
//選擇函數(shù):采用賭盤選擇方法
int select(individual *pop)
{
double rand1;
int partsum=0;
int i=0;
rand1=rdft()*POPSIZE*(POPSIZE+1);
//printf("rand1=%lf\n",rand1);
for(i=0;(rand1>=partsum);i++)
partsum+=pop[i].fitness;//部分和是基因適應(yīng)度的和
// printf("sum=%d",partsum);
return (i-1);
}
//突變:
double mutate(int i)
{
return a[i]+rdft()*(b[i]-a[i]);//產(chǎn)生參數(shù)上下限內(nèi)的隨機(jī)數(shù)
}
//交叉和突變函數(shù):數(shù)學(xué)交叉
void xover(double *parent1,double *parent2,double *child1,double *child2)
//參數(shù)為個(gè)體基因中的參數(shù)串charm[]
{
double alpha;
// double bt;
int i;
for(i=0;i<NVARS;i++)
{
alpha=rdft();
child1[i]=alpha*parent1[i]+(1-alpha)*parent2[i];
child2[i]=alpha*parent2[i]+(1-alpha)*parent1[i];
if(rdft()<pm1)
child1[i]=mutate(i);
if(rdft()<pm2)
child2[i]=mutate(i);
}
//printf("\nbt=%lf,pm=%lf\n",bt,pm);
// printf("\nalpha=%lf",alpha);
}
//初始化函數(shù):
void initialize(void) //void initialize(int argc,char *argv[])
{
// int i;
// FILE * datafp; //實(shí)驗(yàn)參數(shù)文件指針
srand(time(NULL)); //初始化隨機(jī)函數(shù)發(fā)生器
printf("非線性參數(shù)進(jìn)化評(píng)估器\n");
// printf("\n輸入最大代數(shù):");
// scanf("%d",&maxgen);
printf("G-代數(shù) U-沒有改變的代數(shù)");
printf("ERR-最小平方誤差 r-相關(guān)系數(shù)\n\n");
printf("輸入?yún)?shù)的下限和上限\n");
/* for(i=0;i<NVARS;i++)
{
printf("\r 參數(shù)%d下限=",i);
scanf("%lf",&a[i]);
printf("\r 參數(shù)%d上限=",i);
scanf("%lf",&b[i]);
}*/
a[0]=-100;
a[1]=-100;
b[0]=100;
b[1]=100;
location[POPSIZE]=POPSIZE;
initpop(); //初始化種群
}
//重組函數(shù):通過選擇、交叉和變異由老的一代產(chǎn)生新的一代
void recombine(void)
{
int i=0,ii;
int mate1,mate2;
double fit,fitmax,fitave,fit1,fitsum=0.0;
maxlsquare=-1.0e10;
minlsquare=1.0e50;
for(ii=0;ii<POPSIZE;ii++)
{
if(maxlsquare<oldpop[ii].lsquare) maxlsquare=oldpop[ii].lsquare;
if(minlsquare>oldpop[ii].lsquare) minlsquare=oldpop[ii].lsquare;
fitsum+=oldpop[ii].lsquare;
}
//printf("fitsum=%lf\n",fitsum);
fitmax=maxlsquare;
fitave=fitsum/POPSIZE;
//printf("fitave=%lf\n", fitave);
while(i<POPSIZE){
//從老一代中選擇兩個(gè)雙親
mate1=select(oldpop);
do
{
mate2=select(oldpop);
}while(mate1==mate2);
fit1=(oldpop[mate1].lsquare>oldpop[mate2].lsquare)
?oldpop[mate1].lsquare:oldpop[mate2].lsquare;
// printf("fit1=%lf oldpop[mate1]=%lf oldpop[mate2]=%lf\n",
// fit1,oldpop[mate1].lsquare,oldpop[mate2].lsquare);
if(fit1>=fitave)
{
pc=1.0*(fitmax-fit1)/(fitmax-fitave);
}
else
pc=1.0;
fit=oldpop[mate1].lsquare;
if(fit>=fitave)
{
pm1=0.5*(fitmax-fit)/(fitmax-fitave);
}
else
pm1=0.5;
fit=oldpop[mate2].lsquare;
if(fit>=fitave)
{
pm2=0.5*(fitmax-fit)/(fitmax-fitave);
}
else
pm2=0.5;
// printf("pc=%lf pm1=%lf pm2=%lf\n",pc,pm1,pm2);
//對(duì)選擇的個(gè)體進(jìn)行交叉和突變操作
if(rdft()<pc)
{
xover(oldpop[mate1].chrom,oldpop[mate2].chrom,
newpop[i].chrom,newpop[i+1].chrom);
newpop[i].lsquare=evaluate(newpop[i].chrom);//fx;
newpop[i+1].lsquare=evaluate(newpop[i+1].chrom);//fx;
}
else
{
newpop[i]=oldpop[mate1];
newpop[i+1]=oldpop[mate2];
}
i+=2;
//printf("\nbt=%lf\n",bt);
//printf("\npc=%lf\n",pc);
//printf("\ni=%d\n",i);
}
//在新的種群中隨機(jī)選擇一個(gè)個(gè)體,若它比原種群中最好的個(gè)體好,則替代它,否則不做改變
i=rnd(0,POPSIZE-1);
// printf("\ni=%d\n",i);
//printf( "\niiiiiiiiiii=%d\n",i);
// printf("\noldpop[POPSIZE].lsquare=%lf\n",oldpop[POPSIZE].lsquare);
if(newpop[i].lsquare<oldpop[POPSIZE].lsquare)
newpop[i]=oldpop[POPSIZE];
// printf("\n######################################################################\n");
normalfitness(newpop); //確定個(gè)體在種群中的選擇位置和規(guī)格化適應(yīng)度
//printf("\n&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\n");
//如果新的種群中的最好的個(gè)體比過去的種群中的最好的個(gè)體好,
//就從新的種群中拷貝這個(gè)最好的否則用過去的種群中的最好的個(gè)體替代當(dāng)前的最好個(gè)體
//注意:這個(gè)最好的個(gè)體不包括直接進(jìn)化產(chǎn)生的
if(newpop[location[POPSIZE-1]].lsquare>oldpop[POPSIZE].lsquare)
{
newpop[POPSIZE]=newpop[location[POPSIZE-1]];
change=0;
}
else
{
newpop[POPSIZE]=oldpop[POPSIZE];
change++;
}
}
void report(int gen) //結(jié)果報(bào)告
{
int i;
printf("\rG=%3d U=%2d ",gen,change);
printf("max=%lf min=%lf pc=%lf pm1=%lf pm2=%lf ",maxlsquare,minlsquare,pc,pm1,pm2);
for(i=0;i<NVARS;i++)
printf("par%d=%lf ",i,newpop[POPSIZE].chrom[i]);
printf("err=%lf\n",newpop[POPSIZE].lsquare);
//printf("\n************************************************************************\n");
}
//主函數(shù):
void main(void) //void main(int argc,char *argv[])
{
int i;
// long key;
gen=0;
initialize(); //initialize(argc,argv);
//printf("\n\n%lf\n\n",maxlsquare);
// for(gen=1;gen<=maxgen;gen++)
do {
gen++;
/* if(change==50)
{change=0;
pm=0.15;}*/
recombine();
report(gen);
//printf("\nbt=%lf, pc=%lf, pm=%lf\n",bt,pc,pm);
//拷貝新種群到老種群
for(i=0;i<=POPSIZE;i++)
oldpop[i]=newpop[i];
}while(maxlsquare<0.9999);
// free(datax);
// free(datay);
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -