ant

// AntTsp.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <math.h>
#include <stdlib. h>
#include <fstream>
#include <time.h>
#include <stdio.h>
using namespace std;

const int iAntCount = 34;//蚂蚁数量
const int iCityCount = 51;//城市数量
const int iItCount = 500;//最大跌代次数
const double Q = 100;//每只蚂蚁周游一遍留下的信息素总量
const double alpha = 1;//信息素浓度所起作业的程序
const double beta = 5;//期望值所起作用的程度
double rou = 0.5;//挥发系数 怎么用的挥发捏?
int besttour[iCityCount];//最优路径列表
int count=0;//记录连续多少代没有产生更优的解
double  rnd(double low,double uper)//获得随机数, 范围为 [low, uper]
{
	double p = (rand()/(double)RAND_MAX)*((uper)-(low))+(low);
	return p;
};

int rnd(int uper)	//返回[0,uper]之间的整数
{
	return (rand()%uper);
};
class GInfo {//tsp地图信息,包含了信息素,城市距离,和信息素变化矩阵
public: 
	double m_dDeltTrial[iCityCount][iCityCount]; //信息素变化矩阵
	double m_dTrial[iCityCount][iCityCount]; //信息素
	double distance[iCityCount][iCityCount]; //城市距离
};
GInfo Map;	//地图
class ant {	//蚂蚁类
private:
	int ChooseNextCity();//选择城市
	int m_iCityCount;	//已走过的城市个数
	int AllowedCity[iCityCount];//没有走过的城市
public:
	void addcity(int city); //把城市放到已走过的路数组中
	int tabu[iCityCount];/*记录蚂蚁行走顺序*/
	void Reset();  //重置
	void UpdateLength(); //更新路径长度
	double m_dLength;	//路径长度
	void mov();			//直到下一步
	ant();
	double AntProduct( int from, int to );	//蚂蚁在from和to城市之间的路线上撒下的信息素
};
void ant::Reset()
{
	int i;
	m_dLength=0;

	for(i=0; i<iCityCount;i++) {
		AllowedCity[i]=1;
	}

	i=tabu[iCityCount-1];  //从终点城市返回
	m_iCityCount=0;
	addcity(i);
}
ant::ant()
{
	int i;
	m_dLength=0;
	m_iCityCount=0;

	for(i=0;i<iCityCount;i++) {
		AllowedCity[i]=1;/*一开始每个城市都可访问*/
	}
}
void ant::addcity(int city)
{
	tabu[m_iCityCount]=city; //记录city为走过的城市
	m_iCityCount++;
	AllowedCity[city]=0;
}
double ant::AntProduct(int from, int to )
{
	double p;
	p=pow((1.0/Map.distance[from][to]),beta)*pow((Map.m_dTrial[from][to]),alpha);	//转移期望
	if( p<=0)p=rnd(0,1)*pow( (1.0 / Map.distance[from][to]), beta);  //如果没有其他蚂蚁走过,就按距离选择
	return p;
}
int ant::ChooseNextCity()
{
	int i,to=-1;	//to为下一个要到的城市
	double hormone=0;	//信息总量
	int curCity=tabu[m_iCityCount-1];	//当前城市

	if(count<6)	//如果没有产生最优解的代数不超过6,则断续按信息素的浓度选择城市
	{
		for (i=0;i<iCityCount;i++) {
			if((AllowedCity[i]==1)) {
				hormone += AntProduct(curCity,i);//计算信息总量
			}
		}

		if(hormone==0.0)
		{
			to=rnd(iCityCount);	//如果所有的城市都走完一遍,则随意先一个城市
		}
		else
		{
			for(to=0;to<iCityCount;to++)
			{
				double p;
				if(AllowedCity[to]==1)
				{
					p=AntProduct(curCity,to)/hormone;
					if(rnd(0,1)<p)	//按转移概率大小选择下一个城市,同时也避免了局部最优解
						break;
				}
			}
		}
		if(to==iCityCount)
		{
			hormone=-1;
			for(i=0;i<iCityCount;i++)
				if(AllowedCity[i]==1)
				{
					if (hormone<AntProduct(curCity,i)) {
						hormone=AntProduct(curCity,i);	//如果上一步选择失败,则选择具有最大信息量的城市
						to=i;
					}
				}
		}
	}
	
	if(count>=6)	//当连续6代都没有产生更短的路径,则
	{
		for ( i=0;i<iCityCount;i++) {
			if((AllowedCity[i]==1)) {
				to=i;
				count=0;
				rou=0.5;
				if(rnd(0.0,1.0)>0.5)	//随机选择一个还没访问的城市
				{
					break;
				}
			}
		}
	}
	return to;
}
void ant::UpdateLength()
{
	// Update the length of tour
	int i;
	for(i=0;i<iCityCount-1;i++) {
		m_dLength+=Map.distance[tabu[i]][tabu[i+1]];	//计算路径长度
	}
	m_dLength+=Map.distance[tabu[iCityCount-1]][tabu[0]]; //加上第一个与最后一个城市之间的距离
}
void ant::mov()
{
	addcity(ChooseNextCity());
}
class AntProj
{
public:
	void UpdateTrial();	//更新信息素
	double m_dLength;	//记录最佳路径长度
	void initmap();		//初始化地图
	ant ants[iAntCount];//蚁群   //蚁群初始化
	void GetAnt();		//初始蚁群
	void StartSearch();	//搜索路径
	AntProj();
	struct city {
		int num;//城市号
		int x; //城市坐标
		int y;
	}cc[iCityCount];
};
void AntProj::UpdateTrial()
{
	int i;
	int j;
	int from,to;
	for(i=0;i<iAntCount;i++) {
		for (j=0;j<iCityCount-1;j++) { 
			from=ants[i].tabu[j];
			to=ants[i].tabu[j+1];
			Map.m_dDeltTrial[from][to]+=Q/ants[i].m_dLength ;   //增加的信息量
			Map.m_dDeltTrial[to][from]=Map.m_dDeltTrial[from][to]; //两个方向的信息量相等
		}
		from=ants[i].tabu[iCityCount-1];
		to=ants[i].tabu[0];
		Map.m_dDeltTrial[from][to]+=Q/ants[i].m_dLength ;	//加上起点和终点之间的信息量
		Map.m_dDeltTrial[to][from]=Map.m_dDeltTrial[from][to]; //两个方向的信息量相等
	}

	for (i=0;i<iCityCount;i++) {
		for (j=0;j<iCityCount;j++) {
			Map.m_dTrial[i][j]=(rou*Map.m_dTrial[i][j]+Map.m_dDeltTrial[i][j] );  //计算新的信息量  对以前的信息素要进行挥发,然后再加上新的信息素
			Map.m_dDeltTrial[i][j]=0;
		}
	}
}
void AntProj::initmap()
{
	int i;
	int j;

	for(i=0;i<iCityCount;i++) {
		for (j=0;j<iCityCount;j++) {
			Map.m_dTrial[i][j] = 1; //信息素初始化为1,信息素变化量初始化为0
			Map.m_dDeltTrial[i][j] = 0;
		}
	}
}
AntProj::AntProj()/*intialize pheromone, delta-pheromone, distance */
{
	initmap();	//初始化地图
	m_dLength=10e9;//最小长度初始化


    srand((unsigned)time(NULL));
	for (int i=0;i<iCityCount;i++) {
		cc[i].num=i;
		cc[i].x=(rand()/(double)RAND_MAX)*20;
		cc[i].y=(rand()/(double)RAND_MAX)*20; //调入城市数据
		besttour[i]=0;
	}
	int j;

	for(int i=0;i<iCityCount;i++) {
		for (j=0;j<iCityCount;j++) {//计算两城市之间的距离
			Map.distance[i][j]=sqrt(pow((double)(cc[i].x-cc[j].x),2)+pow((double)(cc[i].y-cc[j].y),2));
		}
	}
}
void AntProj::GetAnt()// 蚂蚁随机放到地图的城市里
{
	int i=0;
	int city;
	/* 
	本句的作用就是以系统时钟产生的随机数作为srand的一个种子
	*/
	srand( (unsigned)time( NULL ));

	for ( i=0; i<iAntCount; i++) {/* 把一只蚂蚁随机地放在一个城市上 */
		city = rnd(iCityCount);
		ants[i].addcity(city);
	}
}
void AntProj::StartSearch()
{
	int max=0;//当前的代数
	int i;
	int j;
	double temp;

	FILE * outresult=fopen("result.txt","w+");
	FILE *fp=fopen("fout.txt","w+");//存放最优路径 内容为城市标号和坐标点
	fprintf(outresult," 代数   最短路径\n");
	while (max<iItCount) {  
		for(i=0;i<iCityCount-1;i++)  { //总共前进iCityCount-1步遍历完所有城市
			for (j=0;j<iAntCount;j++) {//所有的蚂蚁都前进一步
				ants[j].mov(); 
			}
		}

		for(j=0;j<iAntCount;j++) {
			ants[j].UpdateLength ();	//更新蚂蚁的路径长度
		}
		int t,minant;

		temp=ants[0].m_dLength; //临时的最优路径长度
		minant=0;

		for(j=1;j<iAntCount;j++) {
			if (temp>ants[j].m_dLength) {
				temp=ants[j].m_dLength;
				minant=j;				//找出周游路径最短的蚂蚁
			}
		}
		if(temp<m_dLength){
			count=0;	
			rou+=0.1;	//如果产生了更短的路径,则减慢信息素的挥发,获得更多的启发信息
			if(rou>=0.9)
				rou=0.9;
			m_dLength=temp;	//记录更优的路径长度
			for ( t=0;t<iCityCount;t++) {
				besttour[t]=ants[minant].tabu[t];//记录周游路径
			}
		}
		else
			count++;
		if(count>=2) //如果连续两代都没有产生更好的路径,则加快信息素的挥发,减少信息素的作用
		{
			rou-=0.1;
			if(rou<=0.1)
				rou=0.1;
		}
		printf("%d : %f\n",max,m_dLength);
		fprintf(outresult,"  %d  :  %f\n",max,m_dLength);
		UpdateTrial(); //更新信息素
		for(j=0;j<iAntCount;j++) {
			ants[j].Reset();	//重置蚂蚁的数据
		}
		max++;
	}

	printf("The shortest toure is : %f\n",m_dLength);	//输出当代最小路径值
	fprintf(outresult,"最短周游路径为:%f\n",m_dLength);
	fprintf(outresult,"最优路径为:\n");
	for ( int t=0;t<iCityCount;t++) {
		printf(" %d ",cc[besttour[t]]);	//输出当代最代路径
		fprintf(outresult," %d ",cc[besttour[t]]);
		fprintf(fp,"%d %d %d\n",cc[besttour[t]].num,cc[besttour[t]].x,cc[besttour[t]].y);
	}
	fclose(outresult);
	fclose(fp);
}
int main()
{
	AntProj TSP; //声明一个测试对象
	TSP.GetAnt();//初始化蚁群
	TSP.StartSearch();//寻找最短路径
	printf("\n");


	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值