// 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;
}
ant
最新推荐文章于 2024-06-14 10:15:15 发布