⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpi_ga.c

📁 MPI实现遗传算法
💻 C
字号:
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define POPSIZE		500
#define NVARS		6
#define MAXGENS		2000 
#define PXOVER		0.8             /* 杂交概率 */
#define PMUTATION	0.15            /* 变异概率 */

#define TASK_NUM(i)	((POPSIZE+pnum-1)/pnum)
//#define TASK_NUM(i)	((i)==pnum-1 && POPSIZE%((POPSIZE+pnum-1)/pnum)? POPSIZE%((POPSIZE+pnum-1)/pnum):(POPSIZE+pnum-1)/pnum)
#define EX_NUM		3

struct genotype
{
	double gene[NVARS]; 
	double fitness;            /* 适应度 */
	double rfitness;           /* 相对适应度 */
	double cfitness;           /* 累积适应度 */
} *population, *newpopulation;

double lowerbound[NVARS]; 
double upperbound[NVARS]; 
double local_best_individual[NVARS+1];	/* 局部最优解 */
double best_individual[NVARS+1];		/* 全局最优解 */

int generation;
double lower_fitness;
FILE *galog;               

int pid, pnum;

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

void initialize(void)
{
	FILE *infile;
	int i, j, r;
	double lbound, ubound;
	MPI_Status status;

	population = malloc(sizeof(struct genotype)*(TASK_NUM(pid)+1));
	newpopulation = malloc(sizeof(struct genotype)*(TASK_NUM(pid)+1));

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

		srand(time(0));
		for (i=0; i<pnum; i++) {
			r = rand();
			MPI_Send(&r, 1, MPI_INT, i, 1, MPI_COMM_WORLD);
		}

		for (i = 0; i < NVARS; i++) {
			fscanf(infile, "%lf",&lowerbound[i]);
			fscanf(infile, "%lf",&upperbound[i]);
		}
	}
	else {
		MPI_Recv(&r, 1, MPI_INT, pnum-1, 1, MPI_COMM_WORLD, &status);
		srand(r);
	}

	MPI_Bcast(lowerbound, NVARS, MPI_DOUBLE, pnum-1, MPI_COMM_WORLD);
	MPI_Bcast(upperbound, NVARS, MPI_DOUBLE, pnum-1, MPI_COMM_WORLD);

	for (j = 0; j < TASK_NUM(pid); j++) {
		population[j].fitness  = 0;
		population[j].rfitness = 0;
		population[j].cfitness = 0;
		
		//printf("\nGene of member %d in %d is:\n", j, pid);
		for (i = 0; i < NVARS; i++) {
			population[j].gene[i] = randval(lowerbound[i], upperbound[i]);
			//printf("  %lf   ", population[j].gene[i]);
		}
	}
	if (pid == pnum - 1) fclose(infile);
}

void evaluate(void)
{
	int mem;
	int i;
	double x[NVARS+1];

	lower_fitness = 0.0;

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

		population[mem].fitness = (x[1]*x[1]*x[1]*x[1]*x[1]*x[1])
			- (x[1]*x[2]*x[3]*x[4]*x[4]*x[6]) + (x[3]*x[3]*x[3]*x[3]*x[3]*x[5]*x[6])
			- (x[2]*x[4]*x[5]*x[5]*x[6]) - (x[1]*x[1]*x[3]*x[3]*x[5]*x[5])
			+ (x[2]*x[2]*x[3]*x[5]*x[6]) + (x[1]*x[2]*x[4]*x[4]*x[4]*x[5]);
		//printf(" The fitness of %d at %lf, %lf, %lf, %lf, %lf, %lf is %lf\n", mem, x[0], x[1], x[2], x[3], x[4], x[5], population[mem].fitness);
		if (population[mem].fitness < lower_fitness) lower_fitness = population[mem].fitness;
	}
}

void keep_the_best()
{
	int mem, i, cur_best = 0;

	for (mem = 0; mem < TASK_NUM(pid); mem++) {
		if (population[mem].fitness > population[TASK_NUM(pid)].fitness) {
			cur_best = mem;
			population[TASK_NUM(pid)].fitness = population[mem].fitness;
		}
	}
	//printf("\nG%4d: the best individual in Process %d is %d, the fitness is %lf.\n", generation, pid, cur_best, population[cur_best].fitness);
	for (i = 0; i < NVARS; i++) {
		population[TASK_NUM(pid)].gene[i] = population[cur_best].gene[i];
		local_best_individual[i+1] = population[cur_best].gene[i];
	}
	local_best_individual[0] = population[cur_best].fitness;
}

void pop_select(void)
{
	MPI_Status status;
	MPI_Request handle;
	int mem, i, j, k;
	double sum = 0;
	double p;
	static struct genotype ex_member[EX_NUM];

	for (mem = 0; mem < TASK_NUM(pid); mem++) {
		sum += (population[mem].fitness - lower_fitness);
		//printf(" Sum %d is %lf\n", mem, sum);
	}

	for (mem = 0; mem < TASK_NUM(pid); mem++) {
		population[mem].rfitness =  (population[mem].fitness - lower_fitness)/sum;
		//printf("The fitness of %d is %lf, the rfitness is %lf\n", mem, population[mem].fitness, population[mem].rfitness);
	}
	population[0].cfitness = population[0].rfitness;

	for (mem = 1; mem < TASK_NUM(pid); mem++) {
		population[mem].cfitness =  population[mem-1].cfitness + population[mem].rfitness;
	}

	for (i = 1; i <= EX_NUM; i++) {
		p = rand()%1000/1000.0;
		//printf("  p = %lf", p);
		//for (j=0; j<=TASK_NUM(pid); j++) printf(" %lf ", population[j].cfitness);
		//printf("\n");
		if (p < population[0].cfitness) {
			//printf("  %d send to %d: %lf, %lf, %lf, %lf, %lf, %lf: %lf\n", pid, (pid+i*generation)%pnum, 
			//	population[0].gene[0], population[0].gene[1], population[0].gene[2], population[0].gene[3],
			//	population[0].gene[4], population[0].gene[5], population[0].fitness);
			MPI_Isend(&population[0], sizeof(struct genotype)/sizeof(char), 
				MPI_CHAR, (pid+i*generation)%pnum, 0, MPI_COMM_WORLD, &handle);
		}
		else {
			for (j = 0; j < TASK_NUM(pid);j++)     
				if (p >= population[j].cfitness && p <  population[j+1].cfitness) {
					//printf("  %d send to %d: %lf, %lf, %lf, %lf, %lf, %lf: %lf\n", pid, (pid+i*generation)%pnum, 
					//	population[j+1].gene[0], population[j+1].gene[1], population[j+1].gene[2], population[j+1].gene[3],
					//	population[j+1].gene[4], population[j+1].gene[5], population[j+1].fitness);
					MPI_Isend(&population[j+1], sizeof(struct genotype)/sizeof(char), 
						MPI_CHAR, (pid+i*generation)%pnum, 0, MPI_COMM_WORLD, &handle);
					break;
				}
		}

		//printf("  %d receive from %d\n", pid, (pid+(pnum-i)*generation)%pnum);
		MPI_Recv (&ex_member[i-1], sizeof(struct genotype)/sizeof(char), MPI_CHAR, 
			(pid+(pnum-i)*generation)%pnum, 0, MPI_COMM_WORLD, &status);
		//printf("  %d receive from %d: %lf, %lf, %lf, %lf, %lf, %lf: %lf\n", pid, (pid+(pnum-i)*generation)%pnum, 
		//	ex_member[i-1].gene[0], ex_member[i-1].gene[1], ex_member[i-1].gene[2], ex_member[i-1].gene[3],
		//	ex_member[i-1].gene[4], ex_member[i-1].gene[5], ex_member[i-1].fitness);
	}

	for (i = 0; i < TASK_NUM(pid); i++)
	{
		p = rand()%1000/1000.0;
		if (p < population[0].cfitness)
			newpopulation[i] = population[0];     
		else {
			for (j = 0; j < TASK_NUM(pid); j++)     
				if (p >= population[j].cfitness &&
					p <  population[j+1].cfitness)
					newpopulation[i] = population[j+1];
		}
	}

	/* once a new population is created, copy it back */
	for (i = 0; i < TASK_NUM(pid); i++)
		population[i] = newpopulation[i];

	for (i = 0; i < EX_NUM; i++) {
		j = rand()%TASK_NUM(pid);
		if (population[j].fitness < ex_member[i].fitness) {
			for (k = 0; k < NVARS; k++) {
				population[j].gene[k] = ex_member[i].gene[k];
			}
			population[j].rfitness = 0;
			population[j].cfitness = 0;
			population[j].fitness = ex_member[i].fitness;
			//printf("  Update member %d: %lf, %lf, %lf, %lf, %lf, %lf: %lf\n", j, 
			//	population[j].gene[0], population[j].gene[1], population[j].gene[2], population[j].gene[3],
			//	population[j].gene[4], population[j].gene[5], population[j].fitness);
		}
	}
}

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

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

}

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

	if(NVARS > 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]);
	}
}

void crossover(void)
{
	int i, mem, one;
	int first  =  0; /* count of the number of members chosen */
	double x;

	for (mem = 0; mem < TASK_NUM(pid); mem++) {
		x = rand()%1000/1000.0;
		if (x < PXOVER) {
			first++;
			if (first % 2 == 0)
				Xover(one, mem);
			else
				one = mem;
		}
	}
}

void mutate(void)
{
	int i, j;

	for (i = 0; i < TASK_NUM(pid); i++)
		for (j = 0; j < NVARS; j++)	{
			if (rand()%1000/1000.0 < PMUTATION) {
				/* find the bounds on the variable to be mutated */
				population[i].gene[j] = randval(lowerbound[j], upperbound[j]);
			}
		}
}

void elitist(void)
{
	int i;
	double best, worst; 
	int best_mem, worst_mem; 

	best = population[0].fitness;
	worst = population[0].fitness;
	for (i = 0; i < TASK_NUM(pid) - 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;
			}
		}
	}

	if (best >= population[TASK_NUM(pid)].fitness)
	{
		for (i = 0; i < NVARS; i++) {
			population[TASK_NUM(pid)].gene[i] = population[best_mem].gene[i];
			local_best_individual[i+1] = population[best_mem].gene[i];
		}
		population[TASK_NUM(pid)].fitness = population[best_mem].fitness;
		local_best_individual[0] = population[best_mem].fitness;
	}
	else
	{
		for (i = 0; i < NVARS; i++)
			population[worst_mem].gene[i] = population[TASK_NUM(pid)].gene[i];
		population[worst_mem].fitness = population[TASK_NUM(pid)].fitness;
	}
	//printf(" Generation %d in Process %d: best = %lf, worst =%lf\n", generation, pid, local_best_individual[0], worst);
	//printf("\nG%4d: the best individual in Process %d is %d, the fitness is %lf.\n", generation, pid, best_mem, population[best_mem].fitness);
}

void report(void)
{
	int i, j;

	fprintf(galog, "\nGene data in %d for generation %d is:\n", pid, generation);
	for (j = 0; j < TASK_NUM(pid); j++) {
		fprintf(galog, "%4d  :", j);

		for (i = 0; i < NVARS; i++) {
			fprintf(galog, "\t%10.6lf  ", population[j].gene[i]);
		}
		fprintf(galog, ":   %20.6lf\n", population[j].fitness);
	}
}

void gene_max(double *in, double *inout, int *len, MPI_Datatype *dptr)
{
	int i;

	if (inout[0] < in[0]) {
		for (i=0; i < *len; ++i) {
			inout[i] = in[i];
		}
	}
}

int main(int argc, char **argv)
{
	double startwtime = 0.0, endwtime;
	int i, j, flag;
	int n = 0;
    MPI_Op my_op;

	MPI_Init(&argc, &argv);
	MPI_Comm_size(MPI_COMM_WORLD, &pnum);
	MPI_Comm_rank(MPI_COMM_WORLD, &pid);

	fprintf(stdout, "Process %d of %d start ....\n",pid, pnum);

	//if ((galog = fopen("ga_log.txt","w"))==NULL)
	//{
	//	exit(1);
	//}
	galog = stdout;

	generation = 0;

	if (pid == pnum - 1) {
		srand(time(0));
	    startwtime = MPI_Wtime();
	}

	initialize();
	evaluate();
	keep_the_best();
	//report();
	while(generation<MAXGENS)
	{
		generation++;
		pop_select();
		crossover();
		mutate();
		//report();
		evaluate();
		elitist();
	}

    MPI_Op_create((MPI_User_function *)gene_max, 1, &my_op);
    MPI_Reduce(local_best_individual, best_individual, NVARS+1, MPI_DOUBLE, my_op, pnum-1, MPI_COMM_WORLD);

/*
	for (i = 0; i < NVARS; i++)
	{
		fprintf (galog,"\n var(%d) = %3.3f",i,population[POPSIZE].gene[i]);
	}
	fprintf(galog,"\n\n Best fitness = %3.3f",population[POPSIZE].fitness);
*/
	if (pid == pnum - 1) {
		fprintf(galog, "\n The solution is (population size = %d, # of generations = %d):\n", TASK_NUM(0)*pnum, generation);
		for (i=0; i<NVARS; i++) fprintf(galog, "    x[%d]   ", i);
		fprintf(galog, "        fitness   \n");
		for (i=0; i<NVARS; i++) fprintf(galog, "%10.6lf ", best_individual[i+1]);
		fprintf(galog, "%20.6lf\n", best_individual[0]);

		endwtime = MPI_Wtime();
		fprintf(galog, "\n Wall clock time =  %lf\n ", endwtime-startwtime);

		//fclose(galog);
	}

	//printf("\nProcess %d of %d Done ....\n", pid, pnum);
	fflush(stdout);

	MPI_Finalize();

	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -