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

📄 antcycle.cpp

📁 蚁群算法经典TSP模型
💻 CPP
字号:
#pragma warning(disable:4786)
#include <map>
#include <vector>
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <string>
#include <algorithm>
#include <fstream>
using namespace std;

//该版本是采用大量STL数据结构实现的速度比较慢



map<pair<size_t,size_t > ,double>preInfo;// 先验信息---距离信息
map<pair<size_t ,size_t > ,double >posInfo;//信息素浓度信息

int main()
{
	
	const size_t NUMOFCITY(30);//和问题的规模有关
	size_t NUMOFANT;
	double city[NUMOFCITY][2];//位置坐标矩阵
	map<pair<size_t,size_t > ,double>dis;//距离矩阵
	map<size_t,vector<size_t> >tabu;
	map<size_t,double>pathAnt;//蚂蚁的某次循环总路径长度
	map<pair<size_t ,size_t > ,double >tempInfo;//某次循环中ij边的增加信息
	
	double alphaV,beta;//
	double p;//消散系数
	double Q;//
	size_t NCMAX;
	cout<<"初始化参数 :"<<endl;
	cout<<"输出蚂蚁的个数m:"<<ends;cin>>NUMOFANT;
	cout<<"信息素影响因子alpha:"<<ends;cin>>alphaV;
	cout<<"先验信息影响因子beta:"<<ends;cin>>beta;
	cout<<"残留系数p:"<<ends;cin>>p;
	cout<<"常量Q"<<ends;cin>>Q;
	cout<<"要循环的最大次数"<<ends;cin>>NCMAX;

	
	size_t NC(0);//循环次数
	const double c=1;//初始个边的信息素浓度------
	
	ifstream infile("oliver30Tsp.dat",ios::in);
	if (!infile)
	{
		cerr<<"数据文件无法打开";
		return -1;
	}
	double x,y,z;
	size_t i(0);
	while(infile>>x>>y>>z)
	{
		city[i][0]=y;
		city[i][1]=z;	
		++i;
	}
	
	for(i=0;i!=NUMOFCITY;++i)
		for(size_t j=(0);j!=NUMOFCITY;++j)
		{
			dis[make_pair(i,j)]=
				sqrt(pow((city[i][0]-city[j][0]),2.0)+pow((city[i][1]-city[j][1]),2.0));
			preInfo[make_pair(i,j)]=1.0/dis[make_pair(i,j)];
			posInfo[make_pair(i,j)]=c;
			tempInfo[make_pair(i,j)]=0.0;
		}
	for(i=0;i!=NUMOFANT;++i)
	{
		tabu[i].reserve(NUMOFCITY);
		tabu[i].push_back(i);//相当于初始时 蚂蚁i在i城
		pathAnt[i]=0.0;
	}
	//////////////////////////////////////////////////////////////////////////
/*	string fileName;
	cout<<"输入存储的文件名 最好和参数有关"<<endl;
	cin>>fileName;
	fileName+=".txt";
	ofstream outfile(fileName.c_str(),ios::out);
	outfile<<"蚂蚁的个数m:"<<NUMOFANT<<endl;
	outfile<<"信息素影响因子alpha:"<<alphaV<<endl;
	outfile<<"先验信息影响因子beta:"<<beta<<endl;
	outfile<<"残留系数p:"<<p<<endl;
	outfile<<"常量Q"<<Q<<endl;
	outfile<<"要循环的最大次数"<<NCMAX<<endl;*/
	bool AntInRoute(const size_t &i,const size_t &j,
		const vector<size_t>::const_iterator & first,
		const vector<size_t>::const_iterator & last);

	double probTrans(const double & pos,const double & alphaV,
		const double & pre,const double & beta);
	double probTransSum(const vector <size_t > &,
		const size_t & curCity,const double & alphaV,const double & beta );
	double shortestPathFinal(100000.0);
	do
	{
		cout<<"第"<<++NC<<"次循环"<<endl;
		size_t t(0);//步数
		srand(unsigned(time(0))); //产生不同的种子----------不写则产生相同的种子
		for(i=0;i!=NUMOFCITY-1;++i)//i表示本循环的步数 一共是NUMOFCITY-1个
			{
			//time(0)返回当前的时间
			for(size_t k(0);k!=NUMOFANT;++k)
				{
					size_t currCity(*(tabu[k].end()-1));
					double sumAvalible=probTransSum(tabu[k],currCity,alphaV,beta);
					double pAccumlate=0.0;
					double pRand=rand()/(double)RAND_MAX; //产生随机概率-每个蚂蚁的概率不同
					size_t tempJ(0);
					for (size_t j=0;j!=NUMOFCITY;++j)
					{			
						if (tabu[k].end()==find(tabu[k].begin(),tabu[k].end(),j))
						{
							pAccumlate+=probTrans(posInfo[make_pair(currCity,j)],alphaV,
								preInfo[make_pair(currCity,j)],beta)/sumAvalible;
							if (pRand<=pAccumlate)
							{
								tempJ=j; break;
								
							}

						}
					}
					tabu[k].push_back(tempJ);
				}
			}
	
		// 计算每个蚂蚁的路径
		double shortestPathEach(0);
		for(i=0;i!=NUMOFANT;++i)
		{
			for(size_t j=0;j!=NUMOFCITY-1;++j)
			{
				pathAnt[i]+=dis[make_pair(tabu[i].at(j),tabu[i].at(j+1))];
			}
			pathAnt[i]+=dis[make_pair(tabu[i].back(),tabu[i].front())];
	//		cout<<"蚂蚁"<<i<<"的路径长度:"<<pathAnt[i]<<endl;
		//	outfile<<"蚂蚁"<<i<<"的路径长度:"<<pathAnt[i]<<ends;
			
	//		cout<<"蚂蚁"<<i<<"的路线图:"<<ends;
	//		outfile<<"蚂蚁"<<i<<"的路线图:"<<ends;
		/*	for(j=0;j!=tabu[i].size();++j)
			{
				cout<<tabu[i].at(j)<<" ";
//				outfile<<tabu[i].at(j)<<" ";
			}*/
		//	cout<<endl;
	//		outfile<<endl;
		}
		// 计算最短路径
		shortestPathEach=pathAnt[0];
		for(i=1;i!=NUMOFANT;++i)
			if(pathAnt[i]<shortestPathEach)
				shortestPathEach=pathAnt[i];
			cout<<"该次循环最短路径"<<shortestPathEach<<endl;
	//		outfile<<"该次循环最短路径"<<shortestPathEach<<endl;
		if (shortestPathEach<shortestPathFinal)
		{
			shortestPathFinal=shortestPathEach;
		}
		cout<<"截至本次循环 总的最短路径"<<shortestPathFinal<<endl;
//		outfile<<"截至本次循环 最短路径"<<shortestPathFinal<<endl;

	
		//更新信息素
		for(i=0;i!=NUMOFCITY;++i)
			for(size_t j=i+1;j!=NUMOFCITY;++j)
			{//对于每一条路径 每一只蚂蚁
				for(size_t k(0);k!=NUMOFANT;++k)
				{
					if(AntInRoute(i,j,tabu[k].begin(),tabu[k].end()))
					{//判断时候ij边或ji边出现在禁忌表中
						//此时凡是经过ij或ji边的信息素进行累加
						tempInfo[make_pair(i,j)]+=(Q*1.0)/pathAnt[k];
					}
				}
				tempInfo[make_pair(j,i)]=tempInfo[make_pair(i,j)];
				//开始更新该ij边的信息素
				posInfo[make_pair(i,j)]
					=p*posInfo[make_pair(i,j)]+tempInfo[make_pair(i,j)];
		//		cout<<"更新后ij边"<<posInfo[make_pair(i,j)]<<" ";
				posInfo[make_pair(j,i)]=posInfo[make_pair(i,j)];
			}


		for(i=0;i!=NUMOFCITY;++i)
			for(size_t j=0;j!=NUMOFCITY;++j)
			{
				tempInfo[make_pair(i,j)]=0;
			}
		//清空禁忌表---放到循环开始 以便于在while判断语句中可以提取该信息
		for(i=0;i!=NUMOFANT;++i)
		{//相关状态复原 
			tabu[i].clear();
			tabu[i].push_back(i);//蚂蚁归位
			pathAnt[i]=0.0;//此时要进行下一次循环 所以路径必须清空
		}

	}
	while(NC!=NCMAX);
	return 0;
	//重新循环 直到所有蚂蚁的禁忌表相同或者达到循环次数
}

double probTrans(const double & pos,const double & alphaV,
				 const double & pre,const double & beta)
{
	return (pow(pos,alphaV)*pow(pre,beta));
}

bool AntInRoute(const size_t & i,const  size_t & j,
				const vector<size_t>::const_iterator & first,
				const vector<size_t>::const_iterator & last)
{//判断ij或ji是否连续的出现在由first last指向的序列中
	vector<size_t>::const_iterator iter(first);
	for(;iter!=last-1;++iter)
	{
		if( (*iter==i&&*(iter+1)==j)
			|| (*iter==j&&*(iter+1)==i) )
			break;
	}
	if(iter!=last-1)
		return true;
	return false;
}

double probTransSum(const vector <size_t > & tabu,const size_t & curCity,
					const double & alphaV,const  double & beta )
{
	double sum(0.0);
	for (size_t i(0);i!=30;++i)
	{
		if (tabu.end()==find(tabu.begin(),tabu.end(),i))
		{
			sum+=probTrans(posInfo[make_pair(curCity,i)],alphaV,
				preInfo[make_pair(curCity,i)],beta);
		}
	}
	return sum;
}

⌨️ 快捷键说明

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