ACO蚁群优化算法求解TSP旅行商问题C++(2020.10.13)

1、TSP旅行商问题介绍

        旅行商问题:假定城市的集合为C={1,2,…,n},城市之间的距离由一个nxn的距离矩阵D=(dij)给出,其中dij表示城市i与j之间的距离,旅行商问题是要求一条周游路线π1—π2—…—πn—π1,使得
m i n ∑ i = 1 n − 1 d π i π i + 1 + d π n π 1 (式1.1) min\sum_{i=1}^{n-1}d_{π_i π_{i+1} } +d_{π_n π_1}\tag{式1.1} mini=1n1dπiπi+1+dπnπ1(1.1)
        其中, π = ( π 1 , π 2 , . . . , π n ) π=(π_1,π_2,...,π_n) π=π1,π2,...,πn为1,2,…,n的一个全排列。
        旅行商问题可形式化地描述为 ( S , f , Ω ) (S,f,Ω) (S,f,Ω)的形式,其中
        (1)解空间 S = { ( π 1 , π 2 , . . . , π n ) ∣ π i ∈ C = { 1 , 2 , . . . , n } } S = \{(π_1,π_2,...,π_n)| π_i∈C=\{1,2,...,n\}\} S={ π1,π2,...,πnπiC={ 1,2,...,n}};
        (2)目标函数 f : S → R , f ( π ) = ∑ i = 1 n − 1 d π i π i + 1 + d π n π 1 f:S→R,f(π) =\sum_{i=1}^{n-1}d_{π_i π_{i+1} } +d_{π_n π_1} f:SRf(π)=i=1n1dπiπi+1+dπnπ1;
        (3)约束 Ω : ( π 1 , π 2 , . . . , π n ) Ω:(π_1,π_2,...,π_n) Ω:π1,π2,...,πn)为1,2,…,n的一个全排列。
        当n=4时,旅行商问题的构建图如图1所示,每条边与信息素与启发式信息相关联,这是因为问题的解实际上是通过边的选择来构建的。启发式信息 η i j \eta_{ij} ηij与边 ( i , j ) τ (i,j) \tau (i,j)τ上的权值相关,是由问题本身确定的。

图1 n=4, 旅行商问题的构建图

2、ACO算法求解TSP

        下面通过将ACO算法用于求解旅行商问题来了解ACO算法的工作方式和一些实现细节。
        用图论的术语,旅行商问题可以叙述如下;
        给定一个赋权完全图 G = ( V , E ) G = (V,E) G=(V,E),其中, V = { 1 , 2 , . . . , n } V=\{1,2,...,n\} V={ 1,2,...,n}表示 n n n个城市的集合,每一条边 ( i , j ) ∈ E (i,j)∈E (i,j)E都带有一个权值 d i j d_{ij} dij,它代表城市 i i i j j j之间的距离。问题是求经过图中每一个顶点一次且仅一次的一条最短回路。在下面的算法中,假定问题的一个实例是通过一个距离矩阵给定的。

2.1 ACO算法的设计

        求解旅行商问题的ACO算法设计如下:
        (1)构建图:构建图 G c = ( C , L ) G_c=(C,L) Gc=(C,L)与旅行商问题实例的描述图一致,即有 C = V , L = E C = V,L= E C=VL=E,每条边 ( i , j ) ∈ L (i,j)∈L (i,j)L与信息素 τ i j \tau_{ij} τij和启发式信息 η i j \eta_{ij} ηij相关联。信息素 τ i j \tau_{ij} τij表示在访问城市 i i i 之后访问城市 j j j 的期望度。启发式信息,这就是说,从城市 i i i 直接到城市 j j j 的启发式期望度与这两个城市之间的距离成反比。
        (2)路径的构建:每只蚂蚁如下地构造一条路径:蚂蚁被放置在一个随机选择的城市上;利用信息素和启发式信息,以一定的概率逐次向蚂蚁构建的部分路径添加尚未被访问的城市,直到所有的城市都被访问为止;蚂蚁返回到起始城市。在路径构造的每一步中,第 k k k只蚂蚁从城市 i i i转移到城市 j j j的概率为
p i j k = { τ i j α η i j β ∑ t ∈ N i k τ i t α η i t β , j ∈ N i k , 0 , 否 则 (式2.1) p_{ij}^{k}= \begin{cases} \frac{\tau_{ij}^{α}\eta_{ij}^{β}}{\sum_{t∈N_i^k}^{} {\tau_{it}^{α}\eta_{it}^{β}}} , &{ j ∈ N_i^k,} \\ 0, &{ 否则} \\ \end{cases} \tag{式2.1} pijk=tNikτitαηitβτijαηijβ,0,jNik,(2.1)
        其中, N i k N_i^k Nik 表示位于城市 i i i 的第 k k k 只蚂蚁下一步允许选择的城市的集合,即还没有被第 k k k 只蚂蚁访问的城市的集合,α 和 β 是两个参数,它们分别决定了信息素和启发式信息的相对影响力,α 和 β 的设置对算法的性能起着重要的作用。若 α = 0 ,这时算法不使用信息素,最靠近城市 i i i 的城市将很有可能被选出,这相当于随机贪心算法。若 β = 0 ,则算法只使用了信息素,而没有利用启发式信息所带来的的偏向性,这将使算法的性能变得很差。特别是当 α > 1 时,算法将很快陷入停滞状态,此时所有的蚂蚁都按照同一条路线移动,而最后所构建出的路径常常与最优路径相差甚远。所以,应在α 和 β 的设置之间取得某种均衡。通常取 α = 1,β = 2~5.
        (3)信息素更新:当所有的蚂蚁都构建好路径后,各条边上的信息素按以下公式更新:
τ i j = ( 1 − ρ ) ⋅ τ i j + ∑ k = 1 m △ τ i j k , (式2.2) \tau_{ij} = (1-\rho)\cdot \tau_{ij} +\sum_{k=1}^{m} △\tau_{ij}^k ,\tag{式2.2} τij=(1ρ)τij+k=1mτijk,(2.2)
        其中, ρ ∈ ( 0 , 1 ] \rho ∈(0,1] ρ(0,1]表示信息素的蒸发率, m m m为蚂蚁的数目,参数 ρ \rho ρ的作用是避免信息素的无线积累,而且还可以使算法“”忘记“”之前较差的路径,通常取 ρ = 0.5 , △ τ i j k \rho = 0.5,△\tau_{ij}^k ρ=0.5,τijk表示第 k k k只蚂蚁向边 ( i , j ) (i,j) (i,j)释放的信息素量, △ τ i j k △\tau_{ij}^k τijk定义为
△ τ i j k = { Q L k , 边 ( i , j ) 在 第 k 只 蚂 蚁 构 建 的 路 径 T k 上 , 0 , 否 则 (式2.3) △\tau_{ij}^k= \begin{cases} \frac{Q}{L_k} , &{ 边(i,j)在第k只蚂蚁构建的路径T_k上,} \\ 0, &{ 否则} \\ \end{cases} \tag{式2.3} τijk={ LkQ,0,(i,jkTk(2.3)
        其中, Q Q Q是一个常数, L k L_k Lk表示路径 T k T_k Tk的长度,通常取 Q = 1. Q = 1. Q=1.
        (4)参数设置:除了上面提到的一些参数外,还有一个重要参数时蚁群的规模 m m m ,通常取 m = n m=n m=n.
        (5)初始化:在算法的开始时,需要对构建图中每条边上的信息素初始化。初始化时,各条边上信息素量相同,即有 ∀ \forall ( i , j ) ∈ L , τ i j = τ 0 , (i,j)\in L, \tau_{ij}=\tau_0, (i,j)L,τij=τ0,其中, τ 0 \tau_0 τ0是一个正常数。如果初始值 τ 0 \tau_0 τ0太小,搜索区域就会很快地集中到蚂蚁最初产生的几条路径中,这将会白白浪费掉,直到信息素逐渐蒸发,并减小到足够小时,蚂蚁释放的信息素才开始发挥引导搜索的作用。一种好的信息素初始化方法是将信息素的初始值设为略高于每一次迭代中蚂蚁释放信息素大小的期望值。
        (6)终止条件:蚁群优化算法通常采用以下的算法终止条件:
                        (i)算法执行到预先指定的最大迭代次数;
                        (ii)算法的运行时间达到预先指定的最大值;
                        (iii)算法已探索的路径数目达到最大值;
                        (iv)算法陷入停滞状态。

2.2 ACO算法的实现

下面介绍用ACO算法求解旅行商问题所用的数据结构和具体的实现过程。

2.2.1 数据结构

       首先定义全局变量CityCount(城市数目)、AntCount(蚂蚁数量)、besttour[CityCount] (最佳路线)、参数α 、β、ρ、Q 。

const int CityCount = 29, AntCount = 29;//城市数量和蚂蚁数量
int besttour[CityCount];//最佳路线
const double α = 1, β = 5,ρ = 0.5, Q = 1;
Graph Map_City;//城市地图,存储城市信息、信息素等
Ant ant[AntCount]//蚁群

       同时为了表示待解问题所需要的所有数据,编写C++代码需要City类、Graph类、Ant类,类中的成员变量和方法如下表所示:

成员 方法
City name、x、y shuchu()
Graph city[CityCount] 、Distance[CityCount][CityCount]、τ[CityCount][CityCount]、Deltτ[CityCount][CityCount] Readcoordinatetxt(string txtfilename)、shuchu()
Ant tour[CityCount + 1]、can_visit[CityCount]、tour_citycount、tour_length、select_probability[CityCount] Ant()、Build_Trip()、Next_City()、GetFirstCity()、Addcity(int city)、UpdateTourLength()、Clear()
\ \ UpdatePheromones(Graph Map_City,Ant ant[AntCount])

       在ACO算法中,每只蚂蚁是一个基本计算单元,它负责构建待解问题的一条路径,并可能向它所经过的边释放一定量的信息素 △ τ △\tau τ。这样,每只蚂蚁必须能够储存它至今所构建的部分路径、确定每个城市可能的相邻城市、计算并储存它构建解的目标函数值。

2.2.2 算法的实现

       这里主要介绍核心的路径构造算法城市选择算法信息素更新算法以及求解旅行商问题的ACO算法
       一、路径构造算法思路:首先清空蚂蚁的记忆、之后随机地选择一个城市作为起始城市、蚂蚁根据城市选择算法依次选择 n − 1 n-1 n1 个城市,最后,蚂蚁返回起始城市。为了方便算法的实现,在路径表示时把第一个城市重复地记录在路径的第 n + 1 n+1 n+1 个位置上。
       单只蚂蚁的路径构造算法:

void Ant::Build_Trip()
{
	for (int i = 0; i < CityCount; i++)
	{
		can_visit[i] = true;
	}
	GetFirstCity();
	while (tour_citycount < CityCount)
	{
		if(tour_citycount <CityCount) Next_City();//轮盘赌法选择下一个城市
		else if (tour_citycount == CityCount - 1)
		{
			for (int i = 0; i<CityCount; i++)
				if (can_visit[i] == true)
				{
					Addcity(i);
					break;
				}//如果还剩下一个城市可以访问,那么这个城市就是最后一个城市,添加到蚂蚁旅行的城市上
		}
	}
	tour[CityCount] = tour[0];//蚂蚁旅行的最后一个城市
}

       二、至于城市选择算法,按照如下方式进行:首先判断蚂蚁目前在哪个城市,然后用类似于演化计算中的轮盘赌选择按照式2.1定义的概率选择下一个城市。
       单只蚂蚁的城市选择算法:

void Ant::Next_City()
{
	int currentcity = tour[tour_citycount - 1];//计算下一步先找到上一步所到的城市
	double temp = 0, sum_probability = 0;
	for (int i = 0; i < CityCount; i++)
	{
		if (can_visit[i] == true)
			temp += pow((Map_City.τ[currentcity][i]), α)*pow(1.0 / Map_City.Distance[currentcity][i], β);
	}
	for (int i = 0; i < CityCount; i++)
	{
		if (can_visit[i] == false)
			select_probability[i] = 0;//已经到过的城市选择概率为0
		else
		{
			select_probability[i] = pow((Map_City.τ[currentcity][i]), α)*pow(1.0 / Map_City.Distance[currentcity][i], β) / temp;//对于未到过的城市,则计算选择概率
			sum_probability += select_probability[i];
		}
	}
	double r = random(0, sum_probability);//取概率区间的随机浮点数
	double p = 0;
	int nextcity = -1;
	for (int j = 0; j < CityCount; j++)
	{
		if (can_visit[j] == true) p += select_probability[j];
		if (p >= r)
		{
			nextcity = j; break;
		}
	}
	/*if (nextcity == -1)
	{
		temp = -1;
		for (int i = 0; i<CityCount; i++)
		{
			if (can_visit[i] == true)
				if (temp<pow((Map_City.τ[currentcity][i]), α)*pow(1.0 / Map_City.Distance[currentcity][i], β))
				{
					temp = pow((Map_City.τ[currentcity][i]), α)*pow(1.0 / Map_City.Distance[currentcity][i], β);
					nextcity = i;
				}
		}
	}*/
	Addcity(nextcity);
}

       三、信息素更新算法:包括信息素的蒸发和释放两个过程,按照式2.2式2.3进行。
       蚁群的信息素更新算法:

void UpdatePheromones(Graph Map_City,Ant ant[AntCount])//更新信息素的函数
{
	for (int i = 0; i<AntCount; i++)
	{
		for (int j = 0; j<CityCount - 1; j++)
		{
			Map_City.Deltτ[ant[i].tour[j]][ant[i].tour[j + 1]] += Q / ant[i].tour_length;
			Map_City.Deltτ[ant[i].tour[j + 1]][ant[i].tour[j]] += Q / ant[i].tour_length;
		}
		Map_City.Deltτ[ant[i].tour[CityCount - 1]][ant[i].tour[0]] += Q / ant[i].tour_length;
		Map_City.Deltτ[ant[i].tour[0]][ant[i].tour[CityCount - 1]] += Q / ant[i].tour_length;
	}
	for (int i = 0; i<CityCount; i++)
	{
		for (int j = 0; j<CityCount; j++)
		{
			Map_City.τ[i][j] = (1 - ρ)*Map_City.τ[i][j] + Map_City.Deltτ[i][j];
			Map_City.Deltτ[i][j] = 0;
		}
	}
}

       四、ACO_TSP算法思路:首先对算法所用的参数进行设置,对Graph类中的城市、距离矩阵、信息素矩阵和信息素增量矩阵进行初始化,然后开始迭代,对蚁群中的每只蚂蚁构建路径后计算路径长度,并将蚂蚁的路径长度与算法目前发现的最短路径相比,若小于最短路径则将这只蚂蚁的路径赋值给最短路径路线,每一次迭代过程中对蚁群中所有的蚂蚁重复同样的过程,在下一次迭代之前对信息素进行更新并清空蚂蚁的记忆。
       蚁群优化算法求解旅行商问题的算法过程:

for (int iteratorcishu = 0; iteratorcishu < MAX_GEN; iteratorcishu++)
	{
		for (int k = 0; k < AntCount; k++)
		{
			ant[k].Build_Trip();
			ant[k].UpdateTourLength();//计算蚂蚁k所发现路径Tk的长度Lk
			if (ant[k].tour_length < Ljia)
			{
				for (int h = 0; h < CityCount; h++)
					Tjia[h] = ant[k].tour[h];
				Ljia = ant[k].tour_length;
			}
		}
		//找到最短的路径长度,放到temp里
		double temp = ant[0].tour_length;
		for (int i = 0; i<CityCount; i++) temptour[i] = ant[0].tour[i];
		for (int i = 0; i<AntCount; i++)
		{
			if (temp>ant[i].tour_length) 
			{
				temp = ant[i].tour_length;
				for (int j = 0; j< CityCount; j++)
					temptour[j] = ant[i].tour[j];
			}
		}
		if (temp<global_tourlength) 
		{
			global_tourlength = temp;
			for (int j = 0; j< CityCount; j++)
				besttour[j] = temptour[j];
		}
		std::cout << "第" << iteratorcishu << "次迭代的最短距离:" << global_tourlength << endl;
		UpdatePheromones(Map_City,ant);
		for (int i = 0; i < AntCount; i++) ant[i].Clear();
	}

2.3 可直接运行的C++完整代码(main.cpp)

2.3.1 main.cpp

// main.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <math.h>
#include <ctime>
using namespace std;
const int CityCount = 29, AntCount = 29;//城市数量和蚂蚁数量
int besttour[CityCount];//最佳路线
const double α = 1, β = 5,ρ = 0.5, Q = 1;
double  random(int low, double uper)//生成某个区间内随机数的函数
{
    
    
	return (rand() / (double)RAND_MAX)*(uper - low) + low;
};
int random(int uper)//返回一个从0到最大随机数的任意整数
{
    
    
	return (rand() % uper);
};
class City
{
    
    
public:
	string name;
	double x, y;//城市的x、y坐标
	void shuchu()
	{
    
    
		std::cout << name << " " << x << " " << y << endl;
	}
};
class Graph//图信息
{
    
    
public:
	City city[CityCount];
	double Distance[CityCount][CityCount];//城市间的距离矩阵
	double τ[CityCount][CityCount];//信息素矩阵
	double Deltτ[CityCount][CityCount];//信息素变化量矩阵
	void shuchu()
	{
    
    
		cout << "城市名称 " << "坐标x" << " " << "坐标y" << endl;
		for (int i = 0; i < CityCount; i++)
			city[i].shuchu();
		cout << "距离矩阵: "<< endl;
		for (int i = 0; i < CityCount; i++)
		{
    
    
			for (int j = 0; j < CityCount; j++)
			{
    
    
				if (j == CityCount - 1)
					std::cout << Distance[i][j] << endl;
				else
					std::cout << Distance[i][j] << "  ";
			}
		}
		cout << "信息素矩阵: " << endl;
		for (int i = 0; i < CityCount; i++)
		{
    
    
			for (int j = 0; j < CityCount; j++)
			{
    
    
				if (j == CityCount - 1)
					std::cout << τ[i][j] << endl;
				else
					std::cout << τ[i][j] << "  ";
			}
		}
		cout << "信息素增量矩阵: " << endl;
		for (int i = 0; i < CityCount; i++)
		{
    
    
			for (int j = 0; j < CityCount; j++)
			{
    
    
				if (j == CityCount - 1)
					std::cout << Deltτ[i][j] << endl;
				else
					std::cout << Deltτ[i][j] << "  ";
			}
		}
	}
	void Readcoordinatetxt(string txtfilename);//读取城市坐标文件的函数
};
Graph Map_City;//定义全局对象图
void Graph::Readcoordinatetxt(string txtfilename)
{
    
    
	ifstream myfile(txtfilename, ios::in);
	double x = 0, y = 0;
	int z = 0;
	if (!myfile.fail())
	{
    
    
		int i = 0;
		while (!myfile.eof() && (myfile >> z >> x >> y))
		{
    
    
			city[i].name = to_string(long double(z));//城市名称转化为字符串
			city[i].x = x; city[i].y = y;
			i++;
		}
	}
	else
		cout << "文件不存在";
	myfile.close();//计算城市距离矩阵
	for (int i = 0; i < CityCount; i++)
		for (int j = 0; j < CityCount; j++)
		{
    
    
			Distance[i][j] = sqrt(pow((city[i].x - city[j].x), 2) + pow((city[i].y - city[j].y), 2));//计算城市ij之间的距离
			τ[i][j] = 1;
			Deltτ[i][j] = 0;
		}
}
class Ant
{
    
    
public:
	int tour[CityCount + 1];//蚂蚁所构建路径的CityCount+1元数组
	bool can_visit[CityCount];//蚂蚁是否能够访问城市的n元布尔数组
	int tour_citycount;//蚂蚁当前走过城市的数量
	double tour_length, tour_length_shortest;//蚂蚁所走的路径长度tour_length
	double select_probability[CityCount];//蚂蚁对各城市的选择概率数组
	Ant();//蚂蚁的初始化函数
	void Build_Trip();//蚂蚁构造旅行路径的函数
	void Next_City();//蚂蚁选择下一个城市的函数
	void GetFirstCity();//蚂蚁随机到访第一个城市的函数
	void Addcity(int city);//蚂蚁路径上添加城市的函数
	void UpdateTourLength();//更新旅行路径长度的函数
	void Clear();//清空函数
};
Ant ant[AntCount];//蚁群用m元数组ant来表示
Ant::Ant()//蚂蚁的构造函数
{
    
    
	tour_length = tour_length_shortest = 0;
	tour_citycount = 0;//起初所旅行过的城市数量为0
	for (int i = 0; i<CityCount; i++)
	{
    
    
		can_visit[i] = true;//每个城市都可以访问
		select_probability[i] = 0;//选择各个城市的概率为0
	}
}
void Ant::Clear()
{
    
    
	tour_length = 0;
	for (int i = 0; i<CityCount; i++)
	{
    
    
		select_probability[i] = 0;
		can_visit[i] = true;
	}
	tour_citycount = 0;
}
void Ant::Addcity(int city)
{
    
    
	//add city to tabu;
	tour[tour_citycount] = city;
	tour_citycount++;
	can_visit[city] = false;
}
void Ant::GetFirstCity()
{
    
    
	srand((unsigned)time(NULL) + rand());
	Addcity(random(CityCount));
}
void Ant::Next_City()
{
    
    
	int currentcity = tour[tour_citycount - 1];//计算下一步先找到上一步所到的城市
	double temp = 0, sum_probability = 0;
	for (int i = 0; i < CityCount; i++)
	{
    
    
		if (can_visit[i] == true)
			temp += pow((Map_City.τ[currentcity][i]), α)*pow(1.0 / Map_City.Distance[currentcity][i], β);
	}
	for (int i = 0; i < CityCount; i++)
	{
    
    
		if (can_visit[i] == false)
			select_probability[i] = 0;//已经到过的城市选择概率为0
		else
		{
    
    
			select_probability[i] = pow((Map_City.τ[currentcity][i]), α)*pow(1.0 / Map_City.Distance[currentcity][i], β) / temp;//对于未到过的城市,则计算选择概率
			sum_probability += select_probability[i];
		}
	}
	double r = random(0, sum_probability);//取概率区间的随机浮点数
	double p = 0;
	int nextcity = -1;
	for (int j = 0; j < CityCount; j++)
	{
    
    
		if (can_visit[j] == true) p += select_probability[j];
		if (p >= r)
		{
    
    
			nextcity = j; break;
		}
	}
	/*if (nextcity == -1)
	{
		temp = -1;
		for (int i = 0; i<CityCount; i++)
		{
			if (can_visit[i] == true)
				if (temp<pow((Map_City.τ[currentcity][i]), α)*pow(1.0 / Map_City.Distance[currentcity][i], β))
				{
					temp = pow((Map_City.τ[currentcity][i]), α)*pow(1.0 / Map_City.Distance[currentcity][i], β);
					nextcity = i;
				}
		}
	}*/
	Addcity(nextcity);
}
void Ant::Build_Trip()
{
    
    
	for (int i = 0; i < CityCount; i++)
	{
    
    
		can_visit[i] = true;
	}
	GetFirstCity();
	while (tour_citycount < CityCount)
	{
    
    
		if(tour_citycount <CityCount) Next_City();//轮盘赌法选择下一个城市
		else if (tour_citycount == CityCount - 1)
		{
    
    
			for (int i = 0; i<CityCount; i++)
				if (can_visit[i] == true)
				{
    
    
					Addcity(i);
					break;
				}//如果还剩下一个城市可以访问,那么这个城市就是最后一个城市,添加到蚂蚁旅行的城市上
		}
	}
	tour[CityCount] = tour[0];//蚂蚁旅行的最后一个城市
}
void Ant::UpdateTourLength()//更新旅行路径长度的函数
{
    
    
	for (int i = 0; i<CityCount - 1; i++)
		tour_length += Map_City.Distance[tour[i]][tour[i + 1]];
	tour_length += Map_City.Distance[tour[CityCount - 1]][tour[0]];
}
void UpdatePheromones(Graph Map_City,Ant ant[AntCount])//更新信息素的函数
{
    
    
	for (int i = 0; i<AntCount; i++)
	{
    
    
		for (int j = 0; j<CityCount - 1; j++)
		{
    
    
			Map_City.Deltτ[ant[i].tour[j]][ant[i].tour[j + 1]] += Q / ant[i].tour_length;
			Map_City.Deltτ[ant[i].tour[j + 1]][ant[i].tour[j]] += Q / ant[i].tour_length;
		}
		Map_City.Deltτ[ant[i].tour[CityCount - 1]][ant[i].tour[0]] += Q / ant[i].tour_length;
		Map_City.Deltτ[ant[i].tour[0]][ant[i].tour[CityCount - 1]] += Q / ant[i].tour_length;
	}
	for (int i = 0; i<CityCount; i++)
	{
    
    
		for (int j = 0; j<CityCount; j++)
		{
    
    
			Map_City.τ[i][j] = (1 - ρ)*Map_City.τ[i][j] + Map_City.Deltτ[i][j];
			Map_City.Deltτ[i][j] = 0;
		}
	}
}
int main()
{
    
    
	int MAX_GEN = 1000;
	double global_tourlength = 10e9,Ljia = DBL_MAX;
	int Tjia[CityCount];//表示蚁群优化算法最终发现的最短路径
	//首先对城市地图进行初始化
	Map_City.Readcoordinatetxt("E:\\下学期课程\\Matlab智能计算\\ACO\\ACO\\bayg29.tsp");
	Map_City.shuchu();
	int temptour[CityCount];
	for (int iteratorcishu = 0; iteratorcishu < MAX_GEN; iteratorcishu++)
	{
    
    
		for (int k = 0; k < AntCount; k++)
		{
    
    
			ant[k].Build_Trip();
			ant[k].UpdateTourLength();//计算蚂蚁k所发现路径Tk的长度Lk
			if (ant[k].tour_length < Ljia)
			{
    
    
				for (int h = 0; h < CityCount; h++)
					Tjia[h] = ant[k].tour[h];
				Ljia = ant[k].tour_length;
			}
		}
		//找到最短的路径长度,放到temp里
		double temp = ant[0].tour_length;
		for (int i = 0; i<CityCount; i++) temptour[i] = ant[0].tour[i];
		for (int i = 0; i<AntCount; i++)
		{
    
    
			if (temp>ant[i].tour_length) 
			{
    
    
				temp = ant[i].tour_length;
				for (int j = 0; j< CityCount; j++)
					temptour[j] = ant[i].tour[j];
			}
		}
		if (temp<global_tourlength) 
		{
    
    
			global_tourlength = temp;
			for (int j = 0; j< CityCount; j++)
				besttour[j] = temptour[j];
		}
		std::cout << "第" << iteratorcishu << "次迭代的最短距离:" << global_tourlength << endl;
		UpdatePheromones(Map_City,ant);
		for (int i = 0; i < AntCount; i++) ant[i].Clear();
	}
	std::cout << "最短路径为:" << endl;
	for (int i = 0; i < CityCount; i++)
	{
    
    
		if (i == CityCount - 1)std::cout << Map_City.city[besttour[i]].name << endl;
		else std::cout << Map_City.city[besttour[i]].name << "->";
	}
	std::cout << "最短路径长度为:" << global_tourlength << endl;
	system("Pause");
	return 0;
}

2.3.2 数据文件:bayg29.tsp

(github地址https://github.com/pmateusz/tsp-datasets/tree/master/tsplib/tsp

   1    1150.0  1760.0
   2     630.0  1660.0
   3      40.0  2090.0
   4     750.0  1100.0
   5     750.0  2030.0
   6    1030.0  2070.0
   7    1650.0   650.0
   8    1490.0  1630.0
   9     790.0  2260.0
  10     710.0  1310.0
  11     840.0   550.0
  12    1170.0  2300.0
  13     970.0  1340.0
  14     510.0   700.0
  15     750.0   900.0
  16    1280.0  1200.0
  17     230.0   590.0
  18     460.0   860.0
  19    1040.0   950.0
  20     590.0  1390.0
  21     830.0  1770.0
  22     490.0   500.0
  23    1840.0  1240.0
  24    1260.0  1500.0
  25    1280.0   790.0
  26     490.0  2130.0
  27    1460.0  1420.0
  28    1260.0  1910.0
  29     360.0  1980.0

2.4 运行结果

初始化的结果:
在这里插入图片描述
运行结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/jing_zhong/article/details/109037793