并行遗传算法源程序(主从式)

并行遗传算法源程序(主从式)最新修改2009-02-25 11:06//这是一个简单的并行遗传算法源代码,由Denis Cormier (North Carolina State University)的
//串行程序修改得到的

#define WIN32_LEAN_AND_MEAN // 从 Windows 头中排除极少使用的资料
#include
#include
#include
#include
#include
#include
#include
#include
#pragma comment(lib,"Wininet.lib")
#pragma comment(lib,"mpi.lib")
#pragma comment(lib,"cxx.lib")

#define POPSIZE 6 /* 群体大小,其实就是基因总数*/
#define MAXGENS 10 /* 进化代数 */
#define NVARS 3 /* 问题变量数,即基因的长度*/
#define PXOVER 0.8 /* 交叉概率 */
#define PMUTATION 0.15 /* 变异概率 */
#define TRUE 1
#define FALSE 0

int generation; /* 记录当前已经进化的代数 */
int cur_best; /* 最优个体 */
FILE *galog; /* 日志文件*/

struct genotype /* 基因类型*/
{
double gene[NVARS]; /* 染色体字符串*/
double upper[NVARS]; /* 每个基于的上界*/
double lower[NVARS]; /* 每个基因的下界*/
double fitness; /* 个体适应度*/
double rfitness; /* 相对适应度*/
double cfitness; /* 累积适应度*/
};

struct genotype population[POPSIZE+1]; /* 种群*/
struct genotype newpopulation[POPSIZE+1]; /* 新种群*/
void initialize(void); /* 种群初始化函数*/
double randval(double, double); /* 随机函数*/
void keep_the_best(void); /*寻找最优个体*/
void elitist(void); /* 保持最优*/
void select(void); /* 选择算子*/
void crossover(void); /* 交叉算子*/
void Xover(int,int); /* 交叉操作*/
void swap(double *, double *); /* 交换*/
void evaluate(void); /* 个体适应度评价*/
void worker(genotype *,int ) /* 从处理器操作,突变和适应度评价*/
void report(void); /* 记录*/
/**************************************************************
初始化基因值,适应值。从gadata.txt中读入每
个变量的上下限,然后随机产生。
**************************************************************/
void initialize(void)
{
FILE *infile;
int i, j;
double lbound, ubound;

if ((infile = fopen("gadata.txt","r"))==NULL)
{
fprintf(galog,"\nCannot open input file!\n");
exit(1);
}

for (i = 0; i < NVARS; i++)//nvars==3,问题变量数

{
fscanf(infile, "%lf",&lbound);
fscanf(infile, "%lf",&ubound);

for (j = 0; j < POPSIZE; j++)//50
{
population[j].fitness = 0;
population[j].rfitness = 0;
population[j].cfitness = 0;
population[j].lower[i] = lbound;
population[j].upper[i]= ubound;
population[j].gene[i] = randval(population[j].lower[i],
population[j].upper[i]);
}
}

fclose(infile);
}

/***********************************************************/
/* 在上下界间产生一个数 */
/***********************************************************/

double randval(double low, double high)
{
double val;
val = ((double)(rand()%1000)/1000.0)*(high - low) + low;
return(val);
}

/***************************************************************/
/* Keep_the_best function: 保持对最优个体的追踪 */
/***************************************************************/

void keep_the_best()//将最优的值放在最后一个空位上
{
int mem;
int i;
cur_best = 0; /* 最优个体索引 */

for (mem = 0; mem < POPSIZE; mem++)
{
if (population[mem].fitness > population[POPSIZE].fitness)
{
cur_best = mem;
population[POPSIZE].fitness = population[mem].fitness;
}
}
/* once the best member in the population is found, copy the genes */
for (i = 0; i < NVARS; i++)
population[POPSIZE].gene[i] = population[cur_best].gene[i];
}

/****************************************************************/
/* Elitist function: 如果这一代的最好值比上一代的 */
/* 差,那么用上一代的最好值替代本代的最差值 */
/****************************************************************/
void elitist()
{
int i;
double best, worst; /* best and worst fitness values */
int best_mem, worst_mem; /* indexes of the best and worst member */

best = population[0].fitness;
worst = population[0].fitness;
for (i = 0; i < POPSIZE - 1; ++i)//找出最好和最坏的适应度
{
if(population[i].fitness > population[i+1].fitness)
{
if (population[i].fitness >= best)
{
best = population[i].fitness;
best_mem = i;
}
if (population[i+1].fitness <= worst)
{
worst = population[i+1].fitness;
worst_mem = i + 1;
}
}
else
{
if (population[i].fitness <= worst)
{
worst = population[i].fitness;
worst_mem = i;
}
if (population[i+1].fitness >= best)
{
best = population[i+1].fitness;
best_mem = i + 1;
}
}
}
/* 如果新一代种群中的最优个体比前一代的最优个体好, */
/* best取此值,反之 用上一代最优个体取代当前代的最差个体。 */
if (best >= population[POPSIZE].fitness)
{
for (i = 0; i < NVARS; i++)
population[POPSIZE].gene[i] = population[best_mem].gene[i];
population[POPSIZE].fitness = population[best_mem].fitness;

}
else
{
for (i = 0; i < NVARS; i++)
population[worst_mem].gene[i] = population[POPSIZE].gene[i];
population[worst_mem].fitness = population[POPSIZE].fitness;
}
}
/*************************************************************************/
/* Selection function: 适者生存通过适应度大小筛选,适 */
/* 应度越大,出现的次数越多(会有重复) */
/*************************************************************************/

void select(void)//
{
int mem, i, j, k=0;
double sum = 0;
double p;
/* 计算适应度总和*/
for (mem = 0; mem < POPSIZE; mem++)
{
sum += population[mem].fitness;
}
/* 计算相对适应度,有点像概率密度*/
for (mem = 0; mem < POPSIZE; mem++)
{
population[mem].rfitness = population[mem].fitness/sum;
}
/* 计算累计适应度,有点像分布函数*/
population[0].cfitness = population[0].rfitness;
for (mem = 1; mem < POPSIZE; mem++)
{
population[mem].cfitness = population[mem-1].cfitness +
population[mem].rfitness;
}

/* 使用累计适应度确定幸存者,落在哪个概率区域就选择相应的概率区域上的染色体*/
for (i = 0; i < POPSIZE; i++)
{
p = rand()%1000/1000.0;
if (p < population[0].cfitness)
newpopulation[i] = population[0];//选择
else
{
for (j = 0; j < POPSIZE;j++)
if (p >= population[j].cfitness &&
pnewpopulation[i] = population[j+1];//选择
}
}
/* 确定全部的幸存者后,拷贝回population完成选择*/
for (i = 0; i < POPSIZE; i++)
population[i] = newpopulation[i];
}

/***************************************************************/
/* Crossover selection: 单随机点交叉,前后两个 */
/* 个体交叉,得到两个新的个体,原来的个体消失 */
/***************************************************************/

void crossover(void)
{
int i=0, mem, one;
int first = 0; /* count of the number of members chosen */
double x;
for (mem = 0; mem < POPSIZE; ++mem)
{
x = rand()%1000/1000.0;
if (x < PXOVER) //按交叉概率进行交叉
{
++first;
if (first % 2 == 0)
Xover(one, mem); //相邻的两个交叉
else
one = mem;
}
}
}
/**************************************************************/
/* Crossover: 交叉操作 */
/**************************************************************/

void Xover(int one, int two)
{
int i;
int point; /* crossover point */

/* select crossover point */
if(NVARS > 1) //等于1时就没有交叉的必要
{
if(NVARS == 2)
point = 1;
else
point = (rand() % (NVARS - 1)) + 1;

for (i = 0; i < point; i++)
swap(&population[one].gene[i], &population[two].gene[i]);

}
}

/**********************************************************

***/
/* Swap: 互换 */
/*************************************************************/

void swap(double *x, double *y)
{
double temp;

temp = *x;
*x = *y;
*y = temp;

}

void evaluate(void) /*个体适应度评价函数*/
{
int mem;
int i;
double x[NVARS+1];

for (mem = 0; mem < POPSIZE; mem++)
{
for (i = 0; i < NVARS; i++)
x[i+1] = population[mem].gene[i];

population[mem].fitness = x[1]*x[1] + x[2]*x[2] + x[3]*x[3];//计算得到适应度
}
}

void report(void)
{
double best_val; /* 种群中最高适应度值*/
double avg; /* 平均适应度值*/
double stddev; /* 标准方差*/
double sum_square; /* 平方的总数*/
double square_sum; /* 总数的平方*/
double sum; /* 适应度值总和*/
sum = 0.0;
sum_square = 0.0;
for (int i = 0; i < POPSIZE; i++)
{
sum += population[i].fitness;
sum_square += population[i].fitness * population[i].fitness;
}
avg = sum/(double)POPSIZE;
square_sum = avg * avg * POPSIZE;
stddev = sqrt((sum_square - square_sum)/(POPSIZE - 1));
best_val = population[POPSIZE].fitness;
fprintf(galog, "%5d \t\t %6.3f \t %6.3f \t %6.3f\n", generation, best_val, avg, stddev);
printf("%5d \t\t %6.3f \t %6.3f \t %6.3f\n", generation, best_val, avg, stddev);
}

void worker(genotype * subpopulation,int mysize) /*突变和适应度评价操作*/
{
double lbound, hbound;
double x;
for (int i = 0; i < mysize; i++)
{
for (int j = 0; j < NVARS; j++)
{
x = rand()%1000/1000.0;
if (x < PMUTATION)
{
lbound = subpopulation->lower[j];
hbound = subpopulation->upper[j];
subpopulation[i].gene[j] = randval(lbound, hbound);
}
}
}//end 变异
//适应度评价
int mem;
double xchorm[NVARS+1];
for (mem = 0; mem < mysize; mem++)
{
for (int i = 0; i < NVARS; i++)
xchorm[i+1] = subpopulation[mem].gene[i];

subpopulation[mem].fitness = (xchorm[1]*xchorm[1]) + (xchorm[1]*xchorm[2]) + xchorm[3]*xchorm[3];//计算得到适应度F1
}//end适应度评价
}

/****************************************************************/
/*主函数 */
/****************************************************************/
void main(int argc,char *argv[])
{
int myid,numprocs,mysize;
int i,j;
double starttime,endtime;
MPI_Status status;
MPI_Request request;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
if (numprocs>1)
mysize = POPSIZE/(numprocs-1);//每个从处理器上应该分配的个体数
else if (numprocs==1) mysize= POPSIZE;
genotype * subpopulation = (genotype*)malloc(mysize*sizeof(genotype));
if (!subpopulation)
{
printf("不能获得 %d 个大小的空间\n",mysize);
MPI_Abort(MPI

_COMM_WORLD,1);
}
//自定义数据类型
MPI_Datatype mystruct;
int blocklens[6];
MPI_Aint indices[6];
MPI_Datatype old_types[6];
//各块中数据个数
blocklens[0] = NVARS;
blocklens[1] = NVARS;
blocklens[2] = NVARS;
blocklens[3] = 1;
blocklens[4] = 1;
blocklens[5] = 1;
//数据类型
for (i =0;i<6;i++) old_types[i]=MPI_DOUBLE;
//求地址和相对偏移
MPI_Address(&population->gene,&indices[0]);
MPI_Address(&population->upper,&indices[1]);
MPI_Address(&population->lower,&indices[2]);
MPI_Address(&population->fitness,&indices[3]);
MPI_Address(&population->rfitness,&indices[4]);
MPI_Address(&population->cfitness,&indices[5]);
indices[5]=indices[5]-indices[0];
indices[4]=indices[4]-indices[0];
indices[3]=indices[3]-indices[0];
indices[2]=indices[2]-indices[0];
indices[1]=indices[1]-indices[0];
indices[0]=0;
MPI_Type_struct(6,blocklens,indices,old_types,&mystruct);//生成新的mpi数据类型
MPI_Type_commit(&mystruct);
//输出表头,初始化,初步测评,初步寻优
if(myid == 0)
{
starttime=MPI_Wtime();
if ((galog = fopen("galog.txt","w"))==NULL)
exit(1);
fprintf(galog, "generation \t best \t \t average \t standard\n");
fprintf(galog, "number \t value\t \t fitness \t deviation\n");
generation = 0;
initialize();//编码
evaluate();//适应度评价函数
keep_the_best();//寻找到最优的染色体,并将之放置在群体的最后一个空位上
}

//开始进化
while(generation{
generation++;
if (myid==0)//master
{
select(); //选择适应度高的个体
crossover(); //交叉,交叉率为80%

//分配数据,处理后回收数据
for (i=1;i<= numprocs -1;i++) //发送
{
for(j=0;jsubpopulation[j] = population[mysize*(i-1)+j]; /*
for(j=0;jprintf("\n发%f %f %f %f",subpopulation[j].fitness,subpopulation[j].gene[0],subpopulation[j].gene[1],subpopulation[j].gene[2]);*/
MPI_Ssend(subpopulation,mysize,mystruct,i,1,MPI_COMM_WORLD);//分配
}
for (i=1;i<= numprocs -1;i++) //接收
{
MPI_Recv(subpopulation,mysize,mystruct,i,2,MPI_COMM_WORLD,&status);//回收
for(j=0;jpopulation[mysize*(i-1)+j] = subpopulation[j];
}
report(); //输出和写下每一代中最优秀的个体的适应度值,平均适应度值以及方差等
elitist(); //如果这一代的最好值比上一代的差,那么用上一代的最好值替代本代的最差值
}//end master
else{//workers
MPI_Recv(subpopulation,mysize,mystruct,0,1,MPI_COMM_WORLD,&status);
worker(subpopulation,mysize); //mutate and value
MPI_Ssend(subpopulation,mysize,mystruct,0,2,MPI_COMM_WORLD);/*
for(j=0;jprintf("\n收%f %f %f %f",subpopulation[j].fitness,subpopulation[j].gene[0],subpopulation[j].gene[1],su

bpopulation[j].gene[2]);*/
}
MPI_Barrier(MPI_COMM_WORLD);
}
if (myid==0)
{
fprintf(galog,"Simulation completed\n");
fprintf(galog,"Best member:\n");
for (i = 0; i < NVARS; i++)
fprintf (galog," var(%d) = %3.3f\n",i,population[POPSIZE].gene[i]);
fprintf(galog,"Best fitness = %3.3f",population[POPSIZE].fitness);
printf("\nSuccess\n");
endtime=MPI_Wtime();
printf("mpi的时间: %f 秒",endtime-starttime);
fprintf(galog,"mpi的时间: %f 秒",endtime-starttime);
fclose(galog);
}
MPI_Type_free(&mystruct);
MPI_Finalize();
}

这里附上gadata.txt的内容:
-5.12 5.12 -5.12 5.12 -5.12 5.12

注:上面的值是基因值的上下限。


wangwx09 awhao Jfish5 fly_fly_higher c

相关文档
最新文档