C++下基于蚁群算法解决TSP问题

 c++求tsp问题_蚁群算法-求解TSP问题_PM熊叔的博客-CSDN博客

一、原理

蚁群算法和前面的粒子群算法很类似,也是预设一个种群,每个蚂蚁代表一条访问路线。设置一个迭代次数,随机初始化100个蚂蚁的访问路径,每个蚂蚁有一个访问路径的信息素矩阵,访问次数多的路径信息素强,然后根据信息素选择哪个路径更优。其中信息素浓度是距离的倒数,所以距离越近信息素越强。

例如有31个城市,设置100个蚂蚁路径,迭代次数设置为100次,首先计算距离矩阵,初始化信息素强度为1.接着进入循环。循环阶段,根据一定的概率,p = T^{1}*(\frac{1}{distance})^{5}(其中T为信息素浓度)决定访问的路径,相当于随机生成100条访问路径。然后根据这100条路径,更新信息素浓度矩阵,信息素浓度T=T*p+deltaT,其中p是个概率,0~1之间,deltaT是信息素浓度增量,deltaT=\frac{100}{\sum_{0}^{30}Dis},主要是第i条路径距离和的倒数,更新完信息素后,从100条路径中选择当前最优路径,作为全局最优路径保存,然后重新更新访问城市的路径(更新依据是以一定概率接受某城市的访问),更新信息素,更新全局最优路径。

二、代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 


using namespace std;

#define m 100				//蚂蚁的个数
#define n 31				//城市的数量

const int NC_max = 100;		//最大迭代次数
const double Alpha = 1;		//表征信息素重要程度的参数
const double Beta = 5;		//表征启发式因子重要程度的参数
const double Rho = 0.1;		//信息素蒸发系数
const double Q = 100;		//信息素增加强度系数
const double C[n][2] =		//各个城市的坐标数据
{ { 1304, 2312 },
	{ 3639, 1315 },
	{ 4177, 2244 },
	{ 3712, 1399 },
	{ 3488, 1535 },
	{ 3326, 1556 },
	{ 3238, 1229 },
	{ 4196, 1004 },
	{ 4312, 790 },
	{ 4386, 570 },
	{ 3007, 1970 },
	{ 2562, 1756 },
	{ 2788, 1491 },
	{ 2381, 1676 },
	{ 1332, 695 },
	{ 3715, 1678 },
	{ 3918, 2179 },
	{ 4061, 2370 },
	{ 3780, 2212 },
	{ 3676, 2578 },
	{ 4029, 2838 },
	{ 4263, 2931 },
	{ 3429, 1908 },
	{ 3507, 2367 },
	{ 3394, 2643 },
	{ 3439, 3201 },
	{ 2935, 3240 },
	{ 3140, 3550 },
	{ 2545, 2357 },
	{ 2778, 2826 },
	{ 2370, 2975 }
};

double D[n][n];			//表示完全图的邻接矩阵
double Eta[n][n];		//表示启发式因子,为D中距离的倒数
double DeltaTau[n][n];	//表示启发式因子的变化量
double Tau[n][n];		//路径上面信息素的浓度
int Tabu[m][n];			//禁忌表,存储走过的路径

double L_best[NC_max];		//存储每次迭代的路径的最短长度
double L_ave[NC_max];		//存储每次迭代的路径的平均长度
int R_best[NC_max][n];		//存储每次迭代的最佳路线


void ValueInit(void)		//变量初始化函数
{
	for (int i = 0; i < n; i++)			//初始化 D[n][n]  31
	{
		for (int j = 0; j < n; j++)//31
		{
			if (i != j)
				D[i][j] = pow(pow((C[i][0] - C[j][0]), 2) + pow((C[i][1] - C[j][1]), 2), 0.5);
			else
				D[i][j] = DBL_EPSILON;//极小数,对角线上的数0
		}
	}

	for (int i = 0; i < n; i++)			//初始化 Eta[n][n]  启发式因子,距离矩阵倒数
		for (int j = 0; j < n; j++)
			Eta[i][j] = 1.0 / D[i][j];

	for (int i = 0; i < n; i++)			//初始化 DeltaEta[n][n]  启发式因子变化量
		for (int j = 0; j < n; j++)
			DeltaTau[i][j] = 0;

	for (int i = 0; i < n; i++)			//初始化 Tau[n][n]  信息素浓度
		for (int j = 0; j < n; j++)
			Tau[i][j] = 1.0;

	for (int i = 0; i < m; i++)			//初始化 Tabu[m][n]  存储走过的路径
		for (int j = 0; j < n; j++)
			Tabu[i][j] = 0;
}

void ValueDisplayTabu(int(*p)[n])	//禁忌表,存储走过的路径, 显示函数
{
	for (int i = 0; i < m; i++)
	{
		for (int j = 0; j < n; j++)
		{
			cout << *(*(p + i) + j) << ' ';
		}
		cout << endl;
	}
}

void ValueDisplayTau(double(*p)[n])		//信息素的浓度,显示函数
{
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			cout << *(*(p + i) + j) << ' ';
		}
		cout << endl;
	}
}

double rnd(double lower, double uper)	//生成lower和uper之间的一个double类型随机数
{
	return  (rand() / (double)RAND_MAX) * (uper - lower) + lower;
}

int main()
{
	//第一步:进行变量的初始化
	ValueInit();  //计算距离矩阵、初始化启发因子

	int NC = 0;
	while (NC < NC_max)//迭代次数100
	{
		//第二步:将m只蚂蚁随机放到n个城市上
		vector temp;
		for (int i = 0; i < ceil((double)m / (double)n); i++) //m/n  蚂蚁数/城市数 100/31
		{
			for (int j = 0; j < n; j++)//31
				temp.push_back(j);
		}

		random_shuffle(temp.begin(), temp.end());	//打乱temp数组中元素的次序

		for (int i = 0; i < m; i++)//100
		{
			Tabu[i][0] = temp[i];//走过的路径,一共100个城市访问路径,第一个城市为随机选取的,temp里面有124个城市点
		}

		//第三步:m只蚂蚁按概率函数选择n中的下一座城市,完成各自的周游
		for (int j = 1; j < n; j++)//31
		{
			for (int i = 0; i < m; i++)//100个路径
			{
				vector visited;	//第i只蚂蚁已访问过的城市
				vector J;			//第i只蚂蚁待访问的城市
				vector P;		//第i只蚂蚁待访问的城市的概率

				double Psum = 0.0;		//概率值和
				double rate = 0.0;		//随机数
				double choose = 0.0;	//轮盘赌算法累加值
				int to_visit=0;			//下一个要去的城市

				for (int k = 0; k < j; k++)
					visited.push_back(Tabu[i][k]);	//visited初始化  0,0 

				for (int k = 0; k < n; k++)//31
				{
					if (find(visited.begin(), visited.end(), k) == visited.end())	//在visited中没有找到k
					{
						J.push_back(k);				//J初始化  待访问城市
						P.push_back(0.0);			//P初始化  访问的概率
					}
				}

				for (int k = 0; k < P.size(); k++)
				{
					//计算去某个城市的概率
					int x = Tau[visited.back()][J[k]];  //Tau=1  Alpha=1   Beta=5  Eta=1/Distance(距离越小,这个值越大)
					P[k] = pow(Tau[visited.back()][J[k]], Alpha) * pow(Eta[visited.back()][J[k]], Beta);//5
					Psum += P[k];
				}

				//随机生成0~Psum之间的一个数
				rate = rnd(0.0, Psum);				//使用轮盘赌算法,挑选下一座要去的城市
				for (int k = 0; k < P.size(); k++)
				{
					choose += P[k];
					if (rate < choose)
					{
						to_visit = J[k];//待访问城市
						break;
					}
				}

				//访问的路径
				Tabu[i][j] = to_visit;				//更新禁忌表 100条访问城市的路径  每个城市初始信息素
			}
		}

		//第四步:记录本次迭代蚂蚁行走的路线数据
		double L[m];	//记录本代每只蚂蚁走的路程,并初始化 100个路径
		for (int i = 0; i < m; i++)
		{
			L[i] = 0.0;
		}
		for (int i = 0; i < m; i++)//100
		{
			for (int j = 0; j < n - 1; j++)//31
			{
				L[i] += D[Tabu[i][j]][Tabu[i][j + 1]];//L[i]代表第i个路径的代价
			}
			L[i] += D[Tabu[i][0]][Tabu[i][n - 1]]; //终点和起点的距离
		}

		double min_value = L[0];	//声明求本代所有蚂蚁行走距离最小值的临时变量
		double sum_value = L[0];	//声明求本代所有蚂蚁行走距离总值的临时变量
		int min_index = 0;			//记录本代所有蚂蚁行走距离最小值的下标
		for (int i = 1; i < m; i++)
		{
			sum_value += L[i];
			if (L[i] < min_value)
			{
				min_value = L[i];
				min_index = i;
			}
		}

		L_best[NC] = min_value;						//每代中路径的最短长度
		L_ave[NC] = sum_value / m;					//每代中路径的平均长度

		for (int i = 0; i < n; i++)
		{
			R_best[NC][i] = Tabu[min_index][i];		//记录每代最短的路径数据
		}

		cout << NC << ": best cost is: " << L_best[NC] << '    ' << "the avg of ever iter is: " << L_ave[NC] << endl;	//打印各代距离信息

		NC++;	//迭代继续

		//第五步:更新信息素
		for (int i = 0; i < m; i++)
		{
			for (int j = 0; j < n - 1; j++)
			{
				//DeltaTau[i][j]信息素增量,表示蚂蚁在i到j路径上留下的信息素,L[i]表示蚂蚁已经走过路径的总长度
				//所以总长度越小,信息素越多
				DeltaTau[Tabu[i][j]][Tabu[i][j + 1]] += Q / L[i];	//此次循环在整个路径上的信息素增量 Q=100
			}
			DeltaTau[Tabu[i][n - 1]][Tabu[i][0]] += Q / L[i];
		}

		for (int i = 0; i < n; i++)//100
		{
			for (int j = 0; j < n; j++)
			{
				//Tau[i][j] 路径i到j上的信息素残余量
				Tau[i][j] = (1 - Rho) * Tau[i][j] + DeltaTau[i][j];	//考虑信息素挥发,更新后的信息素 T = p * T + delta  Qho=0.1,信息素挥发速度
			}
		}

		for (int i = 0; i < m; i++)			//信息素清零
			for (int j = 0; j < n; j++)
				Tabu[i][j] = 0;
	}

	//第六步:取出最优结果
	double min_L = L_best[0];			//所有迭代中最短距离
	int min_L_index = 0;				//所有迭代中最优路径的下标
	int Shortest_Route[n];				//所有迭代中的最优路径
	for (int i = 0; i < NC; i++)
	{
		if (L_best[i] < min_L)
		{
			min_L = L_best[i];
			min_L_index = i;
		}
	}

	cout << "The length of the shortest route is " << min_L << endl;
	cout << "The number of iteration is " << min_L_index << endl;
	cout << "The Shortest route is: " << endl;

	for (int i = 0; i < n; i++)		//所有迭代中的最优路径
	{
		Shortest_Route[i] = R_best[min_L_index][i];
		if (i == n - 1) {
			cout << Shortest_Route[i];
		}
		else {
			cout << Shortest_Route[i] << " -> ";
		}
	}
	std::cout<

C++下基于蚁群算法解决TSP问题_第1张图片

你可能感兴趣的:(多无人机集群编队,c++,无人机,蚁群算法)