【并行计算】遗传算法的并行实现

一、遗传算法的基本描述

遗传算法(Genetic Algorithm,GA)是通过模拟自然界生物进化过程来求解优化问题的一类自组织、自适应的人工智能技术。它主要基于达尔文的自然进化论和孟德尔的遗传变异理论。多数遗传算法的应用是处理一个由许多个体组成的群体,其中每个个体表示问题的一个潜在解。对个体存在一个评估函数来评判其对环境的适应度。为反映适者生存的思想,算法中设计一个选择机制,使得适应度好的个体有更多的机会生存。在种群的进化过程中,主要存在两种类型的遗传算子:杂交和变异。这些算子作用于个体对应的染色体,产生新的染色体,从而构成下一代种群中的个体。该过程不断进行,直到找到满足精度要求的解,或者达到设定的进化代数。显然,这样的思想适合于现实世界中的一大类问题,因而具有广泛的应用价值。遗传算法的每一次进化过程中的,各个体之间的操作大多可以并列进行,因此,一个非常自然的想法就是将遗传算法并行化,以提高计算速度。

二、遗传算法的并行化

串行遗传算法的主要流程如下图所示。在每一次进化过程中,总是找出种群中的最优解与最差解,并将最优解保存,将本次最差解用上次保存的最优解替换,这样保证了各次进化的最优解的适应度不会降低,从而增快收敛的速度。

6dcdc986d8744dfeac42abf05a7f6b72.png

我们可以将串行算法改进为并行算法。将整个种群分成p个子种群,每一子种群由一个单一的进程负责,各进程独立地完成串行遗传算法的整个过程。

eec1ba3991784e3b8ba1063397a61849.png 

三、算法设计

任务一:实现随机---已传输替换

原来的代码完成的是,每个工作进程传一个本地随机个体出去,然后接收一个外来个体,替换一个随机的个体,简称随机——随机,现在需要将其改为:随机送出去一个——已经送出的那个被送来的替换。对于此项修改要求,主要在于子进程的替换语句,将原来用来随机选取替换者的语句删除,因为上面送出语句已经保存了ipass即送出值的下标,因此直接使用即可将该内容进行替换。

if (rand() % 1000 / 1000 < (1 - SPAD) || fabs(SPAD - SPAD0) < 0.00000001)
{
			//不再随机获取,而是直接替换
			dis_p[ipass] = tempdis;
			for (j1 = 0; j1 < xCity; j1++)
				colony[ipass][j1] = tempcol[j1];
	}

 

运行结果如下:

b879fb5bddf74e768f038504532600b0.png

64a48c6a95a84dd4a1558db1f09eedc1.png 

本项任务完整代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include "mpi.h"
#include <math.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <iostream>
using namespace std;

#define NPROC 16                         //进程数量(主从各一个宏定义)
#define N_COLONY   100                   // N_COLONY>=xColony300
#define CITY 431
#define TWOGRP 20                        //组间交换和漫游比例是19:1这个问题值得考虑修改?!!实际是20:1!!
#define GRPSCALE 8                       //组的规模
#define grpnum (NPROC/GRPSCALE)          //组的个数

double  sumTemp, sumbest;
int     xColony = N_COLONY;              //个体数
int     xCity = CITY;                    //城市数量
double  edgeSpeed = 5000;                //临界速度
double  PROBAB1 = 0.02;                  //变异概率
double  PROBAB2 = 0.05;                  //映射概率 //0.04(80) 0.03(50) 0.015(80)  0.05(50)
long    Ni, NOCHANGE = 200000;           //最大停止改变代数

long    loopcounter = 0;
long    MAXGEN = 1000000;                //5
long    INTERVAL = 5000;

int     colony[N_COLONY][CITY];          //所有个体的染色体
double  cityXY[CITY][2];                 //城市坐标
double  city_dis[CITY][CITY];            //城市间距离
double  dis_p[N_COLONY];                 //所有个体的评估值
double  tempdis;                         //传回的个体的评估值
int     tempcol[CITY];                   //传回的个体的染色体
double  speed;
int     temp[CITY];
int     ibest, iworst;
int     ipass;

clock_t timeStart, timeNow, timeTemp;
char    filepath[100], filepath2[100];
void 	initm();
void    init();
int     position(int* tmp, int C);
void    invert(int pos_start, int pos_end);
void    printBest(long GenNum, long Ni);
void    tempTest(int i);
void    mapped();
void    LastCP();
double  path(int tmp[], int k1, int k2);
double  SPAD_compute();
int** mat = NULL;
int** matlocalbest = NULL;
//mpiexec -n 17 TSP.exe
int main(int argc, char* argv[])
{
	mat = (int**)malloc(sizeof(int*) * CITY);
	matlocalbest = (int**)malloc(sizeof(int*) * CITY);

	for (int i = 0; i < CITY; ++i) {
		mat[i] = (int*)malloc(sizeof(int) * CITY);
		matlocalbest[i] = (int*)malloc(sizeof(int) * CITY);
	}
	int mytid, numprocs;
	MPI_Status status;
	int sign = 1, i, i1, j1;
	double result;

	double  data[NPROC], dt;        //存放交换适应值的数组
	double* ptrdata[NPROC];        //指针
	double  tempdata;

	int  chrom[NPROC][CITY];       //存储所有进程的交换标本的数组
	int* ptrchrom[NPROC];          //指针
	int  tempchr[CITY];

	int j, k, m, x;                //用于交换,m用来做记录组别的变量
	int times = 0;//times是提交的次数
	double best = 0.0;
	FILE* fpme;
	double t, probab1 = PROBAB1, probab2 = PROBAB2;
	register int C1, js, ks, pos_C, pos_C1;
	int k1, k2, l1, l2, pos_flag;
	register double disChange;
	static int is = 0;
	char mname[30];
	int r;
	FILE* fppp;
	float SPAD0 = 1.0, SPAD = 1.0;     //aveSPAD;
	MPI_Init(&argc, &argv);            /*程序初始化*/
	MPI_Comm_rank(MPI_COMM_WORLD, &mytid);/**//*得到当前进程号*/
	MPI_Get_processor_name(mname, &r);
	srand((unsigned)time(NULL) + mytid);
	strcpy_s(filepath, "E:\\gr431.tsp");
	//strcpy_s(filepath, argv[1]);

	if (mytid == 0)  //主进程
	{
		//strcpy(filepath2, argv[2]);
		strcpy(filepath2, "E:\\结果.txt");
		//初始化指针数组

		for (i = 0; i < NPROC; i++)
		{
			ptrdata[i] = &data[i];
			ptrchrom[i] = chrom[i];
		}
		//初始化指针数组
		//cout << mytid << endl;
		initm();
		for (i = 1; i <= NPROC; i++) {
			MPI_Send(cityXY, CITY * 2, MPI_DOUBLE, i, 99, MPI_COMM_WORLD);

		}
		cout << "初始数据接收完成" << endl;
	}
	else
	{
		MPI_Recv(cityXY, CITY * 2, MPI_DOUBLE, 0, 99, MPI_COMM_WORLD, &status);
		cout << to_string(mytid) + "接收初始数据" << endl;
		init();

	}
	//以上初始化
	for (loopcounter = 0; loopcounter <= MAXGEN; loopcounter++) {
		if (loopcounter % INTERVAL == 0 && loopcounter != 0) {
			times++;
		}

		if (mytid == 0) {
			if (loopcounter % INTERVAL == 0 && loopcounter != 0) {
				cout << endl;
				cout << "Time(s)=" << times << "代数是" << loopcounter << endl;
				//第二次交流
				//收
				cout << "0号进程接收到:";
				for (i = 1; i <= NPROC; i++)
				{
					MPI_Recv(&data[i - 1], 1, MPI_DOUBLE, i, 99, MPI_COMM_WORLD, &status);
					MPI_Recv(chrom[i - 1], CITY, MPI_INT, i, 99, MPI_COMM_WORLD, &status);
					cout << data[i - 1] << " ";
					//cout << to_string(loopcounter / INTERVAL)+"  " + to_string(i) << endl;
				}
				best = data[0];
				for (i = 1; i < NPROC; i++)  //获取本次提交最好的个体
				{
					if (data[i] < best)
						best = data[i];
				}
				cout << endl;
				cout << "最好个体:" << best << endl;
				//迁移交换
				for (m = 0; m < grpnum; m++) {       //指针数组顺推交换
					tempdata = *ptrdata[GRPSCALE * m];      //tempdata暂留ptrdata每组最后一个数据
					for (k = 0; k < CITY; k++)              //tempchr暂留ptrchrom每组最后一个数据
						tempchr[k] = ptrchrom[GRPSCALE * m][k];

					for (j = GRPSCALE * m; j < GRPSCALE + GRPSCALE * m - 1; j++) {   //除本组最后一个数据之外,其他全部前移一位
						*ptrdata[j] = *ptrdata[j + 1];
						for (k = 0; k < CITY; k++)
							ptrchrom[j][k] = ptrchrom[j + 1][k];
					}

					*ptrdata[GRPSCALE + GRPSCALE * m - 1] = tempdata;     //本组的最后一个数据等于0号数据
					for (k = 0; k < CITY; k++)
						ptrchrom[GRPSCALE + GRPSCALE * m - 1][k] = tempchr[k];
				}

				//发
				for (i = 1; i <= NPROC; i++) {     //原本来自2号进程的数据发送至1号,如此类推,原本来自1号进程的数据发送至16号
					MPI_Send(&data[i - 1], 1, MPI_DOUBLE, i, 99, MPI_COMM_WORLD);
					MPI_Send(chrom[i - 1], CITY, MPI_INT, i, 99, MPI_COMM_WORLD);
					//printf("I send %f to %d\n",data[i],i+1);
				}
			}

		}
		else//子进程程序
		{
			iworst = 0;   //用于存放最差个体
			ibest = 0;    //用于存放最好个体

			if (loopcounter % INTERVAL == 0 && loopcounter != 0) {

				//发
				ipass = rand() % xColony;   //天选之子(送出)
				MPI_Send(&dis_p[ipass], 1, MPI_DOUBLE, 0, 99, MPI_COMM_WORLD);
				MPI_Send(colony[ipass], CITY, MPI_INT, 0, 99, MPI_COMM_WORLD);

				//收
				//在这里把主进程的内容要回  这里是每次迁移都要做的接受主进程
				MPI_Recv(&tempdis, 1, MPI_DOUBLE, 0, 99, MPI_COMM_WORLD, &status);
				MPI_Recv(tempcol, CITY, MPI_INT, 0, 99, MPI_COMM_WORLD, &status);
				SPAD0 = SPAD;
				SPAD = SPAD_compute();

				//MPI_Send(&SPAD,1,MPI_DOUBLE,0,99,MPI_COMM_WORLD);	
				if (rand() % 1000 / 1000 < (1 - SPAD) || fabs(SPAD - SPAD0) < 0.00000001)
				{
					//不再随机获取,直接替换
					dis_p[ipass] = tempdis;
					for (j1 = 0; j1 < xCity; j1++)
						colony[ipass][j1] = tempcol[j1];
				}
			}


			//第二次交流
			for (js = 0; js < xCity; js++)
				temp[js] = colony[is][js];
			disChange = 0; pos_flag = 0;
			pos_C = rand() % xCity;
			for (;;) {
				if ((rand() * 1.0 / RAND_MAX) < probab1) {     //内变异算子

					do pos_C1 = rand() % xCity; while (pos_C1 == pos_C);
					C1 = colony[is][pos_C1];
				}
				else {
					do js = rand() % xColony; while (js == is);
					ks = position(colony[js], temp[pos_C]);
					C1 = colony[js][(ks + 1) % xCity];
					pos_C1 = position(temp, C1);
				}

				if (speed > edgeSpeed && pos_C1 < pos_C + 2)
					break;
				if ((pos_C + 1) % xCity == pos_C1 || (pos_C - 1 + xCity) % xCity == pos_C1)
					break;

				k1 = temp[pos_C]; k2 = temp[(pos_C + 1) % xCity];
				l1 = temp[pos_C1]; l2 = temp[(pos_C1 + 1) % xCity];
				disChange += city_dis[k1][l1] + city_dis[k2][l2] - city_dis[k1][k2] - city_dis[l1][l2];

				invert(pos_C, pos_C1);
				pos_flag++;
				if (pos_flag > xCity - 1)
					break;
				pos_C++;
				if (pos_C >= xCity)
					pos_C = 0;
				if (speed < edgeSpeed && disChange < 0) {     //每有改变就计算
					dis_p[is] += disChange; disChange = 0;
					tempTest(is);
				}
			}
			if (speed >= edgeSpeed && disChange < 0) { dis_p[is] += disChange; disChange = 0; tempTest(is); }  /speed>=1500 &&
			is++;
			if (is >= xColony) {
				Ni++;
				is = 0;
				//loopcounter++;
				//check();                    //此处增加一个函数,完成第一个功能,正确!!!!
				probab1 = PROBAB1 * (1 - loopcounter * 0.5 / MAXGEN);        //内逆转概率逐渐减小
				if ((rand() * 1.0 / RAND_MAX < probab2))   // speed<edgeSpeed &&
				{
					mapped();
					probab2 = PROBAB2 * (loopcounter * 2.0 / MAXGEN + 1);    //部分交换概率逐渐增大
				}
			}
		}//while(loopcounter++<=MAXGEN);
	}

	cout << to_string(mytid) + "号进程完成交流" << endl;

	if (mytid == 0)
	{
		fpme = fopen(filepath2, "a");
		fprintf(fpme, "This is a result of %d:%lf\n", CITY, best);
		fclose(fpme);
	}
	for (i = 0; i < CITY; i++) {
		free(mat[i]);
		free(matlocalbest[i]);
	}
	free(mat);
	free(matlocalbest);
	MPI_Finalize();
	return 0;
}
double SPAD_compute()
{
	int ibest2 = 0;
	int xx, yy, zz;
	//int mat[CITY][CITY], matlocalbest[CITY][CITY];
	int best_i, count_of_1;
	float D[N_COLONY], STD, lD[N_COLONY], lSTD;
	for (xx = 0; xx < N_COLONY; xx++)
	{
		if (dis_p[ibest2] > dis_p[xx])
			ibest2 = xx;
	}
	for (xx = 0; xx < xCity; xx++)
		for (yy = 0; yy < xCity; yy++)
			matlocalbest[xx][yy] = 0;
	for (xx = 0; xx < xCity; xx++)     //本地最好解之邻接矩阵建立
	{
		matlocalbest[colony[ibest2][xx]][colony[ibest2][(xx + 1) % xCity]] = 1;
	}
	lSTD = 0;
	for (zz = 0; zz < N_COLONY; zz++)
	{
		for (xx = 0; xx < CITY; xx++)   //ci chu gui 0
		{
			for (yy = 0; yy < CITY; yy++)
				mat[xx][yy] = 0;
		}
		for (xx = 0; xx < xCity; xx++)
		{
			mat[colony[zz][xx]][colony[zz][(xx + 1) % xCity]] = 1;     //全部解矩阵建立
		}
		count_of_1 = 0;
		for (xx = 0; xx < xCity; xx++)
		{
			for (yy = 0; yy < xCity; yy++)
			{
				if (matlocalbest[xx][yy] == 1 && mat[xx][yy] == 1)
				{
					break;
				}
			}
			if (yy < xCity)
				count_of_1++;
		}
		lD[zz] = 1.0 * (xCity - count_of_1) / xCity;      //求出了一个个体与本地最好个体的差异
		lSTD += lD[zz];                                   //累加差异
	}
	return lSTD / N_COLONY;
}

void invert(int pos_start, int pos_end)
{
	int j, k, t;
	if (pos_start < pos_end)
	{
		j = pos_start + 1; k = pos_end;
		for (; j <= k; j++, k--)
		{
			t = temp[j]; temp[j] = temp[k]; temp[k] = t;
		}
	}
	else
	{
		if (xCity - 1 - pos_start <= pos_end + 1)
		{
			j = pos_end; k = pos_start + 1;
			for (; k < xCity; j--, k++)
			{
				t = temp[j]; temp[j] = temp[k]; temp[k] = t;
			}
			k = 0;
			for (; k <= j; k++, j--)
			{
				t = temp[j]; temp[j] = temp[k]; temp[k] = t;
			}
		}
		else
		{
			j = pos_end; k = pos_start + 1;
			for (; j >= 0; j--, k++)
			{
				t = temp[j]; temp[j] = temp[k]; temp[k] = t;
			}
			j = xCity - 1;
			for (; k <= j; k++, j--)
			{
				t = temp[j]; temp[j] = temp[k]; temp[k] = t;
			}
		}
	}
}

int position(int* tmp, int C)
{
	int j;
	for (j = 0; j < xCity; j++)
		if (*(tmp + j) == C)break;
	return(j);
}

void tempTest(int i)
{
	int j; double dt;
	for (j = 0; j < xCity; j++)colony[i][j] = temp[j];
	if ((int)sumbest > (int)dis_p[i])
	{
		sumbest = dis_p[i]; ibest = i; Ni = 0;
		timeNow = clock();
		dt = (double)(timeNow - timeTemp) / CLOCKS_PER_SEC;;
		if (dt > 0.1)
		{
			speed = (sumTemp - sumbest) / dt;
			sumTemp = sumbest;
			timeTemp = timeNow;
		}
		//printf("\n%f   %4.2f  %10.1f",sumbest,(double)(timeNow-timeStart)/CLOCKS_PER_SEC,speed);
	}
}

void printBest(long GenNum, long Ni)
{
	int i;
	printf("\n   CITY      %d\t\tN_COLONY  %d", CITY, N_COLONY);
	printf("\n   maxGen    %d\t\ttime      %4.2f  seconds", MAXGEN, (double)(timeNow - timeStart) / CLOCKS_PER_SEC);
	printf("\n   GenNum    %d\t\tNo change %Ld\n\n", GenNum, Ni);
	for (i = 0; i < xCity; i++)
	{
		if (i % 10 == 0 && i != 0) { printf("\n"); }
		printf("%5d", colony[ibest][i] + 1);
	}
	printf("\n\n");
}

void mapped()
{
	int start, end, i, j, k, kt, t, disPlace, kDC, kC;
	double temp_dis = 0;
	i = rand() % xColony;
	j = rand() % xColony;
	if (i == j)return;
	if (dis_p[i] < dis_p[j])
	{
		t = i; i = j; j = t;
	}
	for (k = 0; k < xCity; k++)temp[k] = colony[i][k];

	start = rand() % xCity;
	end = (start + rand() % 180 + 20) % xCity; //rand()%xCity;
	kt = position(temp, colony[j][start]);                //部分映射一二位同
	disPlace = kt - start;
	if (temp[(kt + 1) % xCity] == colony[j][(start + 1) % xCity])
	{
		if (start < end)
			for (k = start; k <= end; k++)
			{
				kDC = (k + disPlace) % xCity;
				if (temp[kDC] == colony[j][k])continue;
				t = position(temp, colony[j][k]);
				temp[t] = temp[kDC];
				temp[kDC] = colony[j][k];
			}
		else
			for (k = start; k <= xCity + end; k++)
			{
				kDC = (k + disPlace) % xCity; kC = k % xCity;
				if (temp[kDC] == colony[j][kC])continue;
				t = position(temp, colony[j][kC]);
				temp[t] = temp[kDC];
				temp[kDC] = colony[j][kC];
			}
	}
	else
	{
		if (temp[(kt - 1 + xCity) % xCity] == colony[j][(start + 1) % xCity])
		{
			if (start < end)
				for (k = kt = start; k <= end; k++, kt--)
				{
					kDC = (kt + xCity + disPlace) % xCity;
					if (temp[kDC] == colony[j][k])continue;
					t = position(temp, colony[j][k]);
					temp[t] = temp[kDC];
					temp[kDC] = colony[j][k];
				}
			else
				for (k = kt = start; k <= end + xCity; k++, kt--)
				{
					kDC = (kt + xCity + disPlace) % xCity; kC = k % xCity;
					if (temp[kDC] == colony[j][kC])continue;
					t = position(temp, colony[j][kC]);
					temp[t] = temp[kDC];
					temp[kDC] = colony[j][kC];
				}
		}
		else return;
	}
	/*
	start=rand()%xCity;  end=rand()%xCity;             //部分映射找第一位同
	if(start>end){t=start;start=end;end=t;}
	disPlace=position(temp,colony[j][start])-start;
	for(k=start;k<=end;k++)
	{ if(temp[(k+disPlace)%xCity]==colony[j][k])continue;
	t=position(temp,colony[j][k]);
	temp[t]=temp[(k+disPlace)%xCity];
	temp[(k+disPlace)%xCity]=colony[j][k];
	}

	start=rand()%(xCity/2);                         //部分映射  
	end=rand()%(xCity/2)+xCity/2;
	for(k=start;k<=end;k++)
	{ if(temp[k]==colony[j][k])continue;
	t=position(temp,colony[j][k]);
	temp[t]=temp[k];
	temp[k]=colony[j][k];
	}
	*/
	for (j = 0; j < xCity - 1; j++)
		temp_dis = temp_dis + city_dis[temp[j]][temp[j + 1]];
	temp_dis = temp_dis + city_dis[temp[0]][temp[xCity - 1]];
	dis_p[i] = temp_dis;
	/*********/
	tempTest(i);
}

void LastCP()
{
	int i, k, j1, j2, k1, k2, turn, length, sign[CITY]; double dc, temp_dis = 0, change = 0;
	printf("+");
	for (k = 0; k < xCity; k++)temp[k] = colony[ibest][k];
	for (turn = 0; turn < xCity / 10; turn++)      //可改
	{
		for (k1 = 0; k1 < xCity - 1; k1 += rand() % 4 + 1)     // rand()%9+1可改
		{
			for (i = 1; i < xColony; i++)
			{
				if (i == ibest)continue;
				for (k = 0; k < xCity; k++)sign[k] = 0;
				j1 = position(colony[i], temp[k1]);
				k2 = k1; j2 = j1;
				for (length = 0; length < xCity / 2; length++)    // 70 xCity/3+10可改
				{
					k2 = (++k2) % xCity; j2 = (++j2) % xCity;
					sign[temp[k2]] = 1;
					if (temp[k2] == colony[i][j2] && length > 1)break;  // 5 xCity/10可改
				}
				if (temp[k2] != colony[i][j2])continue;
				k = j1;
				do k = (k + 1) % xCity;
				while (sign[colony[i][k]] == 1);
				if ((j1 < j2 && k < j2) || (j1 > j2 && (k > j1 || k < j2)))continue;
				temp_dis = path(temp, k1, k2);
				dc = path(colony[i], j1, j2);
				if (temp_dis > dc)
				{
					for (k = 1; k <= length; k++)
						temp[(k1 + k) % xCity] = colony[i][(j1 + k) % xCity];
					change += dc - temp_dis;
				}
			}
		}
	}
	if (change < 0)
	{
		for (k = 0; k < xCity; k++)colony[ibest][k] = temp[k];
		dis_p[ibest] += change;
		sumbest = dis_p[ibest];
		printf("\n%f  O K !!!", sumbest);
	}
}

double path(int tmp[], int k1, int k2)
{
	int j, t1, t2; double temp_dis = 0;
	if (k2 > k1)
		for (j = k1; j < k2; j++)
			temp_dis += city_dis[tmp[j]][tmp[j + 1]];
	else
		for (j = k1; j < k2 + xCity; j++)
		{
			t1 = j % xCity; t2 = (j + 1) % xCity;
			temp_dis += city_dis[tmp[t1]][tmp[t2]];
		}
	return temp_dis;
}

// 读取城市坐标
void initm() {
	int i;
	FILE* fp;
	float ffff, eeee;
	if ((fp = fopen(filepath, "r")) == NULL) {
		MPI_Finalize();
		exit(0);
	}

	//printf("hello");
	fscanf(fp, "%d", &xCity);
	for (i = 0; i < xCity; i++)      /*  init cityXY[][]  */
	{
		fscanf(fp, "%*d%f%f", &ffff, &eeee);
		//printf("\nffff=%f eeee=%f", ffff, eeee);
		cityXY[i][0] = ffff;
		cityXY[i][1] = eeee;
	}
	fclose(fp);
	cout << "读取成功" << endl;
}
// 初始化一个种群的染色体
void init() {
	int i, j, t, sign, mod, array[CITY];
	double d;
	for (i = 0; i < xCity; i++) {
		for (j = 0; j < xCity; j++) {
			if (j > i) {
				d = (cityXY[i][0] - cityXY[j][0]) * (cityXY[i][0] - cityXY[j][0]) * 1.0 +
					(cityXY[i][1] - cityXY[j][1]) * (cityXY[i][1] - cityXY[j][1]) * 1.0;
				city_dis[i][j] = (int)(sqrt(d) + 0.5);
				continue;
			}
			if (j == i) {
				city_dis[i][j] = 0;
				continue;
			}
			if (j < i)
				city_dis[i][j] = city_dis[j][i];
		}
	}
	mod = xCity;
	for (i = 0; i < xCity; i++)
		array[i] = i;     //    init colony[][]
	for (i = 0; i < xColony; i++, mod = xCity) {
		for (j = 0; j < xCity; j++) {
			sign = rand() % mod;
			colony[i][j] = array[sign];
			t = array[mod - 1];
			array[mod - 1] = array[sign];
			array[sign] = t;
			mod--;
			if (mod == 1) colony[i][++j] = array[0];
		}
		//for (j = 0; j < xCity; j++) {
		//	printf("%d ", colony[i][j]);
		//}
		//printf("\n");
	}


	for (i = 0; i < xColony; i++) {		    /*    init dis_p[]       */
		dis_p[i] = 0;
		for (j = 0; j < xCity - 1; j++)
			dis_p[i] = dis_p[i] + city_dis[*(*(colony + i) + j)][*(*(colony + i) + j + 1)];
		dis_p[i] = dis_p[i] + city_dis[**(colony + i)][*(*(colony + i) + xCity - 1)];
	}

	ibest = 0; sumbest = dis_p[0];	    /*  init ibest & sumbest */
	sumTemp = sumbest * 5;
	speed = 100000000;
	loopcounter = 0;	Ni = 0;               /*   initialize GunNum & Ni    */

											  //printf("init success!!!\n");
}

任务二:实现最好---最坏替换

各进程在每一次进化过程中,均分别保留各自的局部最优解,用来在下一次进化中替换局部最差的个体。各进程均完成所预定的进化迭代后,最后对各进程的局部最优解进行归约,从而得到整个算法的全局最优解。

else//子进程程序
		{
			iworst = 0;   //用于存放最差个体
			ibest = 0;    //用于存放最好个体

			if (loopcounter % INTERVAL == 0 && loopcounter != 0) {

				//发
				double best = 0;
				for (int p = 0; p < 100; p++)
				{
					if (best > dis_p[p])
					{
						best = dis_p[p];   //选出群体中最好的个体
						ibest = p;
					}
				}
				MPI_Send(&dis_p[ibest], 1, MPI_DOUBLE, 0, 99, MPI_COMM_WORLD);  //将最好个体发送出去
				MPI_Send(colony[ibest], CITY, MPI_INT, 0, 99, MPI_COMM_WORLD);

				//收
				//在这里把主进程的内容要回  这里是每次迁移都要做的接受主进程
				MPI_Recv(&tempdis, 1, MPI_DOUBLE, 0, 99, MPI_COMM_WORLD, &status);
				MPI_Recv(tempcol, CITY, MPI_INT, 0, 99, MPI_COMM_WORLD, &status);
				SPAD0 = SPAD;
				SPAD = SPAD_compute();

				//MPI_Send(&SPAD,1,MPI_DOUBLE,0,99,MPI_COMM_WORLD);	
				if (rand() % 1000 / 1000 < (1 - SPAD) || fabs(SPAD - SPAD0) < 0.00000001)
				{
					double worst = 0;
					for (int p = 0; p < 100; p++)
					{
						if (worst < dis_p[p])
						{
							worst = dis_p[p];  //该群体中最差的个体选出来
							worst = p;
						}
					}
					dis_p[iworst] = tempdis;   //将最差的个体替换
					for (j1 = 0; j1 < xCity; j1++)
						colony[iworst][j1] = tempcol[j1];
				}
			}

运行结果如下:

daf87bf1750449b7a8c70ae34fcd7172.png

5e673813e1b44ce89012d17100ebc818.png 

任务三:将“地主+长工”模式改为“富农+长工”模式

原先的主进程只负责数据的发送和回收,并不负责计算;要修改为主进程不仅进行数据的送出和收回,还要进行计算。

//第二次交流
				//收
				for (i = 1; i < NPROC; i++)  //修改处 ,将<=改为<
				{
					MPI_Recv(&data[i], 1, MPI_DOUBLE, i, 99, MPI_COMM_WORLD, &status);     //修改处,data[i-1]改为i,1号进程接受data[1]
					MPI_Recv(chrom[i], CITY, MPI_INT, i, 99, MPI_COMM_WORLD, &status);      //修改处,chrom[i-1]改为i,1号进程接受chrom[1]

 运行结果如下:

099da63e0e614e0c93bf0df446a6c741.png

18de0e5c39464739adb72f98220d54be.png 

该任务完整代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include "mpi.h"
#include <math.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <iostream>
using namespace std;

#define NPROC 16                         //进程数量(主从各一个宏定义)
#define N_COLONY   100                   // N_COLONY>=xColony300
#define CITY 431
#define TWOGRP 20                        //组间交换和漫游比例是19:1这个问题值得考虑修改?!!实际是20:1!!
#define GRPSCALE 8                       //组的规模
#define grpnum (NPROC/GRPSCALE)          //组的个数

double  sumTemp, sumbest;
int     xColony = N_COLONY;              //个体数
int     xCity = CITY;                    //城市数量
double  edgeSpeed = 5000;                //临界速度
double  PROBAB1 = 0.02;                  //变异概率
double  PROBAB2 = 0.05;                  //映射概率 //0.04(80) 0.03(50) 0.015(80)  0.05(50)
long    Ni, NOCHANGE = 200000;           //最大停止改变代数

long    loopcounter = 0;
long    MAXGEN = 1000000;                //5
long    INTERVAL = 5000;

int     colony[N_COLONY][CITY];          //所有个体的染色体
double  cityXY[CITY][2];                 //城市坐标
double  city_dis[CITY][CITY];            //城市间距离
double  dis_p[N_COLONY];                 //所有个体的评估值
double  tempdis;                         //传回的个体的评估值
int     tempcol[CITY];                   //传回的个体的染色体
double  speed;
int     temp[CITY];
int     ibest, iworst;
int     ipass;

clock_t timeStart, timeNow, timeTemp;
char    filepath[100], filepath2[100];
void 	initm();
void    init();
int     position(int* tmp, int C);
void    invert(int pos_start, int pos_end);
void    printBest(long GenNum, long Ni);
void    tempTest(int i);
void    mapped();
void    LastCP();
double  path(int tmp[], int k1, int k2);
double  SPAD_compute();
int** mat = NULL;
int** matlocalbest = NULL;

int main(int argc, char* argv[])
{
	mat = (int**)malloc(sizeof(int*) * CITY);
	matlocalbest = (int**)malloc(sizeof(int*) * CITY);

	for (int i = 0; i < CITY; ++i) {
		mat[i] = (int*)malloc(sizeof(int) * CITY);
		matlocalbest[i] = (int*)malloc(sizeof(int) * CITY);
	}
	int mytid, numprocs;
	MPI_Status status;
	int sign = 1, i, i1, j1;
	double result;

	double  data[NPROC], dt;        //存放交换适应值的数组
	double* ptrdata[NPROC];        //指针
	double  tempdata;

	int  chrom[NPROC][CITY];       //存储所有进程的交换标本的数组
	int* ptrchrom[NPROC];          //指针
	int  tempchr[CITY];

	int j, k, m, x;                //用于交换,m用来做记录组别的变量
	int times = 0;//times是提交的次数
	double best = 0.0;
	FILE* fpme;
	double t, probab1 = PROBAB1, probab2 = PROBAB2;
	register int C1, js, ks, pos_C, pos_C1;
	int k1, k2, l1, l2, pos_flag;
	register double disChange;
	static int is = 0;
	char mname[30];
	int r;
	FILE* fppp;
	float SPAD0 = 1.0, SPAD = 1.0;     //aveSPAD;
	MPI_Init(&argc, &argv);            /*程序初始化*/
	MPI_Comm_rank(MPI_COMM_WORLD, &mytid);/*得到当前进程号*/
	MPI_Get_processor_name(mname, &r);
	srand((unsigned)time(NULL) + mytid);
	strcpy_s(filepath, "E:\\gr431.tsp");
	//strcpy_s(filepath, argv[1]);

	if (mytid == 0)  //主进程
	{
		//strcpy(filepath2, argv[2]);
		strcpy(filepath2, "E:\\结果.txt");
		//初始化指针数组

		for (i = 0; i < NPROC; i++)
		{
			ptrdata[i] = &data[i];
			ptrchrom[i] = chrom[i];
		}
		//初始化指针数组
		initm();
		for (i = 1; i < NPROC; i++) {
			//修改处,将<=变为<  给剩下的15个进程分配数据
			MPI_Send(cityXY, CITY * 2, MPI_DOUBLE, i, 99, MPI_COMM_WORLD);

		}
		init();   //给0号进程初始化一个种群
		data[0] = dis_p[ipass];
		for (int i = 0; i < xCity; i++)
		{
			chrom[0][i] = colony[ipass][i];
		}
		cout << "初始数据接收完成" << endl;
	}
	else
	{
		MPI_Recv(cityXY, CITY * 2, MPI_DOUBLE, 0, 99, MPI_COMM_WORLD, &status);    //其他进程接收来自
		cout << to_string(mytid) + "接收初始数据" << endl;
		init();

	}
	//以上初始化
	for (loopcounter = 0; loopcounter <= MAXGEN; loopcounter++) {
		if (loopcounter % INTERVAL == 0 && loopcounter != 0) {
			times++;
		}

		if (mytid == 0) {
			if (loopcounter % INTERVAL == 0 && loopcounter != 0) {
				cout << endl;
				/*iworst = 0;   //用于存放最差个体
				ibest = 0;    //用于存放最好个体*/
				ipass = rand() % xColony;
				double temp_disp = dis_p[ipass];
				int* temp_col = colony[ipass];

				//发

				cout << "Time(s)=" << times << "代数是" << loopcounter << endl;
				//第二次交流
				//收
				for (i = 1; i < NPROC; i++)  //修改处  将<=改为<
				{
					MPI_Recv(&data[i], 1, MPI_DOUBLE, i, 99, MPI_COMM_WORLD, &status);     //修改处,data[i-1]改为i,1号进程接受data[1]
					MPI_Recv(chrom[i], CITY, MPI_INT, i, 99, MPI_COMM_WORLD, &status);      //修改处,如上
					if (i == 1)
					{
						SPAD0 = SPAD;
						SPAD = SPAD_compute();
						if (rand() % 1000 / 1000 < (1 - SPAD) || fabs(SPAD - SPAD0) < 0.00000001)
						{
							dis_p[ipass] = data[i];
							for (j1 = 0; j1 < xCity; j1++)
								colony[ipass][j1] = chrom[i][j1];
						}

						for (js = 0; js < xCity; js++)
							temp[js] = colony[is][js];
						disChange = 0; pos_flag = 0;
						pos_C = rand() % xCity;
						for (;;) {
							if ((rand() * 1.0 / RAND_MAX) < probab1) {     //内变异算子

								do pos_C1 = rand() % xCity; while (pos_C1 == pos_C);
								C1 = colony[is][pos_C1];
							}
							else {
								do js = rand() % xColony; while (js == is);
								ks = position(colony[js], temp[pos_C]);
								C1 = colony[js][(ks + 1) % xCity];
								pos_C1 = position(temp, C1);
							}

							if (speed > edgeSpeed && pos_C1 < pos_C + 2)
								break;
							if ((pos_C + 1) % xCity == pos_C1 || (pos_C - 1 + xCity) % xCity == pos_C1)
								break;

							k1 = temp[pos_C]; k2 = temp[(pos_C + 1) % xCity];
							l1 = temp[pos_C1]; l2 = temp[(pos_C1 + 1) % xCity];
							disChange += city_dis[k1][l1] + city_dis[k2][l2] - city_dis[k1][k2] - city_dis[l1][l2];

							invert(pos_C, pos_C1);
							pos_flag++;
							if (pos_flag > xCity - 1)
								break;
							pos_C++;
							if (pos_C >= xCity)
								pos_C = 0;
							if (speed < edgeSpeed && disChange < 0) {     //每有改变就计算
								dis_p[is] += disChange; disChange = 0;
								tempTest(is);
							}
						}
						if (speed >= edgeSpeed && disChange < 0) { dis_p[is] += disChange; disChange = 0; tempTest(is); }  /speed>=1500 &&
						is++;
						if (is >= xColony) {
							Ni++;
							is = 0;
							//loopcounter++;
							//check();                    //此处增加一个函数,完成第一个功能,正确!!!!
							probab1 = PROBAB1 * (1 - loopcounter * 0.5 / MAXGEN);        //内逆转概率逐渐减小
							if ((rand() * 1.0 / RAND_MAX < probab2))   // speed<edgeSpeed &&
							{
								mapped();
								probab2 = PROBAB2 * (loopcounter * 2.0 / MAXGEN + 1);    //部分交换概率逐渐增大
							}
						}
					}
				}


				best = data[0];
				cout << "0号进程中的数据:";
				cout << data[0] << " ";
				for (i = 1; i < NPROC; i++)  //获取本次提交最好的个体
				{
					cout << data[i] << " ";
				}
				for (i = 1; i < NPROC; i++)  //获取本次提交最好的个体
				{
					if (data[i] < best)
						best = data[i];
				}
				cout << endl;
				cout << "最好个体:" << best << endl;
				//迁移交换
				for (m = 0; m < grpnum; m++) {       //指针数组顺推交换
					tempdata = *ptrdata[GRPSCALE * m];      //tempdata暂留ptrdata每组最后一个数据
					for (k = 0; k < CITY; k++)              //tempchr暂留ptrchrom每组最后一个数据
						tempchr[k] = ptrchrom[GRPSCALE * m][k];

					for (j = GRPSCALE * m; j < GRPSCALE + GRPSCALE * m - 1; j++) {   //除本组最后一个数据之外,其他全部前移一位
						*ptrdata[j] = *ptrdata[j + 1];
						for (k = 0; k < CITY; k++)
							ptrchrom[j][k] = ptrchrom[j + 1][k];
					}

					*ptrdata[GRPSCALE + GRPSCALE * m - 1] = tempdata;     //本组的最后一个数据等于0号数据
					for (k = 0; k < CITY; k++)
						ptrchrom[GRPSCALE + GRPSCALE * m - 1][k] = tempchr[k];
				}

				//发
				for (i = 1; i < NPROC; i++) {     //原本来自2号进程的数据发送至1号,如此类推,原本来自0号进程的数据发送至15号
					if (i == NPROC - 1)
					{
						MPI_Send(&temp_disp, 1, MPI_DOUBLE, i, 99, MPI_COMM_WORLD);
						MPI_Send(temp_col, CITY, MPI_INT, i, 99, MPI_COMM_WORLD);
						continue;
					}
					MPI_Send(&data[i], 1, MPI_DOUBLE, i, 99, MPI_COMM_WORLD);
					MPI_Send(chrom[i], CITY, MPI_INT, i, 99, MPI_COMM_WORLD);
				}
			}
		}
		else//子进程程序
		{
			iworst = 0;   //用于存放最差个体
			ibest = INT_MAX;    //用于存放最好个体

			if (loopcounter % INTERVAL == 0 && loopcounter != 0) {

				ipass = rand() % xColony;   //生成一个随机数
				MPI_Send(&dis_p[ipass], 1, MPI_DOUBLE, 0, 99, MPI_COMM_WORLD);  //将随机个体发送出去
				MPI_Send(colony[ipass], CITY, MPI_INT, 0, 99, MPI_COMM_WORLD);

				//收
				//在这里把主进程的内容要回  这里是每次迁移都要做的接受主进程
				MPI_Recv(&tempdis, 1, MPI_DOUBLE, 0, 99, MPI_COMM_WORLD, &status);
				MPI_Recv(tempcol, CITY, MPI_INT, 0, 99, MPI_COMM_WORLD, &status);


				SPAD0 = SPAD;
				SPAD = SPAD_compute();
				if (rand() % 1000 / 1000 < (1 - SPAD) || fabs(SPAD - SPAD0) < 0.00000001)
				{
					dis_p[ipass] = tempdis;   //将群体中随机的个体替换
					for (j1 = 0; j1 < xCity; j1++)
						colony[ipass][j1] = tempcol[j1];
				}
			}

			//第二次交流
			for (js = 0; js < xCity; js++)
				temp[js] = colony[is][js];
			disChange = 0; pos_flag = 0;
			pos_C = rand() % xCity;
			for (;;) {
				if ((rand() * 1.0 / RAND_MAX) < probab1) {     //内变异算子

					do pos_C1 = rand() % xCity; while (pos_C1 == pos_C);
					C1 = colony[is][pos_C1];
				}
				else {
					do js = rand() % xColony; while (js == is);
					ks = position(colony[js], temp[pos_C]);
					C1 = colony[js][(ks + 1) % xCity];
					pos_C1 = position(temp, C1);
				}

				if (speed > edgeSpeed && pos_C1 < pos_C + 2)
					break;
				if ((pos_C + 1) % xCity == pos_C1 || (pos_C - 1 + xCity) % xCity == pos_C1)
					break;

				k1 = temp[pos_C]; k2 = temp[(pos_C + 1) % xCity];
				l1 = temp[pos_C1]; l2 = temp[(pos_C1 + 1) % xCity];
				disChange += city_dis[k1][l1] + city_dis[k2][l2] - city_dis[k1][k2] - city_dis[l1][l2];

				invert(pos_C, pos_C1);
				pos_flag++;
				if (pos_flag > xCity - 1)
					break;
				pos_C++;
				if (pos_C >= xCity)
					pos_C = 0;
				if (speed < edgeSpeed && disChange < 0) {     //每有改变就计算
					dis_p[is] += disChange; disChange = 0;
					tempTest(is);
				}
			}
			if (speed >= edgeSpeed && disChange < 0) { dis_p[is] += disChange; disChange = 0; tempTest(is); }  /speed>=1500 &&
			is++;
			if (is >= xColony) {
				Ni++;
				is = 0;
				probab1 = PROBAB1 * (1 - loopcounter * 0.5 / MAXGEN);        //内逆转概率逐渐减小
				if ((rand() * 1.0 / RAND_MAX < probab2))   // speed<edgeSpeed &&
				{
					mapped();
					probab2 = PROBAB2 * (loopcounter * 2.0 / MAXGEN + 1);    //部分交换概率逐渐增大
				}
			}
		}
	}

	cout << to_string(mytid) + "号进程完成交流" << endl;

	if (mytid == 0)
	{
		fpme = fopen(filepath2, "a");
		fprintf(fpme, "富农-长工模式下 %d个城市的结果:%lf\n", CITY, best);
		fclose(fpme);
	}
	for (i = 0; i < CITY; i++) {
		free(mat[i]);
		free(matlocalbest[i]);
	}
	free(mat);
	free(matlocalbest);
	MPI_Finalize();
	return 0;
}
double SPAD_compute()
{
	int ibest2 = 0;
	int xx, yy, zz;
	//int mat[CITY][CITY], matlocalbest[CITY][CITY];
	int best_i, count_of_1;
	float D[N_COLONY], STD, lD[N_COLONY], lSTD;
	for (xx = 0; xx < N_COLONY; xx++)
	{
		if (dis_p[ibest2] > dis_p[xx])
			ibest2 = xx;
	}
	for (xx = 0; xx < xCity; xx++)
		for (yy = 0; yy < xCity; yy++)
			matlocalbest[xx][yy] = 0;
	for (xx = 0; xx < xCity; xx++)     //本地最好解之邻接矩阵建立
	{
		matlocalbest[colony[ibest2][xx]][colony[ibest2][(xx + 1) % xCity]] = 1;
	}
	lSTD = 0;
	for (zz = 0; zz < N_COLONY; zz++)
	{
		for (xx = 0; xx < CITY; xx++)   //ci chu gui 0
		{
			for (yy = 0; yy < CITY; yy++)
				mat[xx][yy] = 0;
		}
		for (xx = 0; xx < xCity; xx++)
		{
			mat[colony[zz][xx]][colony[zz][(xx + 1) % xCity]] = 1;     //全部解矩阵建立
		}
		count_of_1 = 0;
		for (xx = 0; xx < xCity; xx++)
		{
			for (yy = 0; yy < xCity; yy++)
			{
				if (matlocalbest[xx][yy] == 1 && mat[xx][yy] == 1)
				{
					break;
				}
			}
			if (yy < xCity)
				count_of_1++;
		}
		lD[zz] = 1.0 * (xCity - count_of_1) / xCity;      //求出了一个个体与本地最好个体的差异
		lSTD += lD[zz];                                   //累加差异
	}
	return lSTD / N_COLONY;
}

void invert(int pos_start, int pos_end)
{
	int j, k, t;
	if (pos_start < pos_end)
	{
		j = pos_start + 1; k = pos_end;
		for (; j <= k; j++, k--)
		{
			t = temp[j]; temp[j] = temp[k]; temp[k] = t;
		}
	}
	else
	{
		if (xCity - 1 - pos_start <= pos_end + 1)
		{
			j = pos_end; k = pos_start + 1;
			for (; k < xCity; j--, k++)
			{
				t = temp[j]; temp[j] = temp[k]; temp[k] = t;
			}
			k = 0;
			for (; k <= j; k++, j--)
			{
				t = temp[j]; temp[j] = temp[k]; temp[k] = t;
			}
		}
		else
		{
			j = pos_end; k = pos_start + 1;
			for (; j >= 0; j--, k++)
			{
				t = temp[j]; temp[j] = temp[k]; temp[k] = t;
			}
			j = xCity - 1;
			for (; k <= j; k++, j--)
			{
				t = temp[j]; temp[j] = temp[k]; temp[k] = t;
			}
		}
	}
}

int position(int* tmp, int C)
{
	int j;
	for (j = 0; j < xCity; j++)
		if (*(tmp + j) == C)break;
	return(j);
}

void tempTest(int i)
{
	int j; double dt;
	for (j = 0; j < xCity; j++)colony[i][j] = temp[j];
	if ((int)sumbest > (int)dis_p[i])
	{
		sumbest = dis_p[i]; ibest = i; Ni = 0;
		timeNow = clock();
		dt = (double)(timeNow - timeTemp) / CLOCKS_PER_SEC;;
		if (dt > 0.1)
		{
			speed = (sumTemp - sumbest) / dt;
			sumTemp = sumbest;
			timeTemp = timeNow;
		}
		//printf("\n%f   %4.2f  %10.1f",sumbest,(double)(timeNow-timeStart)/CLOCKS_PER_SEC,speed);
	}
}

void printBest(long GenNum, long Ni)
{
	int i;
	printf("\n   CITY      %d\t\tN_COLONY  %d", CITY, N_COLONY);
	printf("\n   maxGen    %d\t\ttime      %4.2f  seconds", MAXGEN, (double)(timeNow - timeStart) / CLOCKS_PER_SEC);
	printf("\n   GenNum    %d\t\tNo change %Ld\n\n", GenNum, Ni);
	for (i = 0; i < xCity; i++)
	{
		if (i % 10 == 0 && i != 0) { printf("\n"); }
		printf("%5d", colony[ibest][i] + 1);
	}
	printf("\n\n");
}

void mapped()
{
	int start, end, i, j, k, kt, t, disPlace, kDC, kC;
	double temp_dis = 0;
	i = rand() % xColony;
	j = rand() % xColony;
	if (i == j)return;
	if (dis_p[i] < dis_p[j])
	{
		t = i; i = j; j = t;
	}
	for (k = 0; k < xCity; k++)temp[k] = colony[i][k];

	start = rand() % xCity;
	end = (start + rand() % 180 + 20) % xCity; //rand()%xCity;
	kt = position(temp, colony[j][start]);                //部分映射一二位同
	disPlace = kt - start;
	if (temp[(kt + 1) % xCity] == colony[j][(start + 1) % xCity])
	{
		if (start < end)
			for (k = start; k <= end; k++)
			{
				kDC = (k + disPlace) % xCity;
				if (temp[kDC] == colony[j][k])continue;
				t = position(temp, colony[j][k]);
				temp[t] = temp[kDC];
				temp[kDC] = colony[j][k];
			}
		else
			for (k = start; k <= xCity + end; k++)
			{
				kDC = (k + disPlace) % xCity; kC = k % xCity;
				if (temp[kDC] == colony[j][kC])continue;
				t = position(temp, colony[j][kC]);
				temp[t] = temp[kDC];
				temp[kDC] = colony[j][kC];
			}
	}
	else
	{
		if (temp[(kt - 1 + xCity) % xCity] == colony[j][(start + 1) % xCity])
		{
			if (start < end)
				for (k = kt = start; k <= end; k++, kt--)
				{
					kDC = (kt + xCity + disPlace) % xCity;
					if (temp[kDC] == colony[j][k])continue;
					t = position(temp, colony[j][k]);
					temp[t] = temp[kDC];
					temp[kDC] = colony[j][k];
				}
			else
				for (k = kt = start; k <= end + xCity; k++, kt--)
				{
					kDC = (kt + xCity + disPlace) % xCity; kC = k % xCity;
					if (temp[kDC] == colony[j][kC])continue;
					t = position(temp, colony[j][kC]);
					temp[t] = temp[kDC];
					temp[kDC] = colony[j][kC];
				}
		}
		else return;
	}
	for (j = 0; j < xCity - 1; j++)
		temp_dis = temp_dis + city_dis[temp[j]][temp[j + 1]];
	temp_dis = temp_dis + city_dis[temp[0]][temp[xCity - 1]];
	dis_p[i] = temp_dis;
	/*********/
	tempTest(i);
}

void LastCP()
{
	int i, k, j1, j2, k1, k2, turn, length, sign[CITY]; double dc, temp_dis = 0, change = 0;
	printf("+");
	for (k = 0; k < xCity; k++)temp[k] = colony[ibest][k];
	for (turn = 0; turn < xCity / 10; turn++)      //可改
	{
		for (k1 = 0; k1 < xCity - 1; k1 += rand() % 4 + 1)     // rand()%9+1可改
		{
			for (i = 1; i < xColony; i++)
			{
				if (i == ibest)continue;
				for (k = 0; k < xCity; k++)sign[k] = 0;
				j1 = position(colony[i], temp[k1]);
				k2 = k1; j2 = j1;
				for (length = 0; length < xCity / 2; length++)    // 70 xCity/3+10可改
				{
					k2 = (++k2) % xCity; j2 = (++j2) % xCity;
					sign[temp[k2]] = 1;
					if (temp[k2] == colony[i][j2] && length > 1)break;  // 5 xCity/10可改
				}
				if (temp[k2] != colony[i][j2])continue;
				k = j1;
				do k = (k + 1) % xCity;
				while (sign[colony[i][k]] == 1);
				if ((j1 < j2 && k < j2) || (j1 > j2 && (k > j1 || k < j2)))continue;
				temp_dis = path(temp, k1, k2);
				dc = path(colony[i], j1, j2);
				if (temp_dis > dc)
				{
					for (k = 1; k <= length; k++)
						temp[(k1 + k) % xCity] = colony[i][(j1 + k) % xCity];
					change += dc - temp_dis;
				}
			}
		}
	}
	if (change < 0)
	{
		for (k = 0; k < xCity; k++)colony[ibest][k] = temp[k];
		dis_p[ibest] += change;
		sumbest = dis_p[ibest];
		printf("\n%f  O K !!!", sumbest);
	}
}

double path(int tmp[], int k1, int k2)
{
	int j, t1, t2; double temp_dis = 0;
	if (k2 > k1)
		for (j = k1; j < k2; j++)
			temp_dis += city_dis[tmp[j]][tmp[j + 1]];
	else
		for (j = k1; j < k2 + xCity; j++)
		{
			t1 = j % xCity; t2 = (j + 1) % xCity;
			temp_dis += city_dis[tmp[t1]][tmp[t2]];
		}
	return temp_dis;
}

// 读取城市坐标
void initm() {
	int i;
	FILE* fp;
	float ffff, eeee;
	if ((fp = fopen(filepath, "r")) == NULL) {
		MPI_Finalize();
		exit(0);
	}

	//printf("hello");
	fscanf(fp, "%d", &xCity);
	for (i = 0; i < xCity; i++)      /*  init cityXY[][]  */
	{
		fscanf(fp, "%*d%f%f", &ffff, &eeee);
		//printf("\nffff=%f eeee=%f", ffff, eeee);
		cityXY[i][0] = ffff;
		cityXY[i][1] = eeee;
	}
	fclose(fp);
	cout << "读取成功" << endl;
}
// 初始化一个种群的染色体
void init() {
	int i, j, t, sign, mod, array[CITY];
	double d;
	for (i = 0; i < xCity; i++) {
		for (j = 0; j < xCity; j++) {
			if (j > i) {
				d = (cityXY[i][0] - cityXY[j][0]) * (cityXY[i][0] - cityXY[j][0]) * 1.0 +
					(cityXY[i][1] - cityXY[j][1]) * (cityXY[i][1] - cityXY[j][1]) * 1.0;
				city_dis[i][j] = (int)(sqrt(d) + 0.5);
				continue;
			}
			if (j == i) {
				city_dis[i][j] = 0;
				continue;
			}
			if (j < i)
				city_dis[i][j] = city_dis[j][i];
		}
	}
	mod = xCity;
	for (i = 0; i < xCity; i++)
		array[i] = i;     //    init colony[][]
	for (i = 0; i < xColony; i++, mod = xCity) {
		for (j = 0; j < xCity; j++) {
			sign = rand() % mod;
			colony[i][j] = array[sign];
			t = array[mod - 1];
			array[mod - 1] = array[sign];
			array[sign] = t;
			mod--;
			if (mod == 1) colony[i][++j] = array[0];
		}
	}


	for (i = 0; i < xColony; i++) {		    /*    init dis_p[]       */
		dis_p[i] = 0;
		for (j = 0; j < xCity - 1; j++)
			dis_p[i] = dis_p[i] + city_dis[*(*(colony + i) + j)][*(*(colony + i) + j + 1)];
		dis_p[i] = dis_p[i] + city_dis[**(colony + i)][*(*(colony + i) + xCity - 1)];
	}

	ibest = 0; sumbest = dis_p[0];	    /*  init ibest & sumbest */
	sumTemp = sumbest * 5;
	speed = 100000000;
	loopcounter = 0;	Ni = 0;               /*   initialize GunNum & Ni    */

											  //printf("init success!!!\n");
}

猜你喜欢

转载自blog.csdn.net/m0_53700832/article/details/128902415