蚁群算法求解tsp

先来说一下整个蚁群算法的思想:模拟蚂蚁寻找食物的过程。每只蚂蚁觅食时在走过的路线上会留下一种称为信息素的物质,蚂蚁之间靠感知这种物质的浓度进行信息传递。蚂蚁在选择路径时总是倾向于朝信息索浓度高的方向移动,而距离短的路径上走过的蚂蚁多,留下的信息素也多,后续蚂蚁选择它的概率也会越大;其他路径上的信息素会随着时间的推移不断挥发,这样就形成了一种正反馈机制,最后整个蚁群聚集到最短路径上。

我个人感觉这个算法比较重要的两个点:(1)如何选择先一步要走的城市。这个选择里面有两个值起作用,一个是当前位置到下一个城市的距离,另一个是这条路上的信息素的浓度。有两个值ALPHA和BETA分别调节他们的权重,(怎么设置好像得靠经验了)。

2)就是信息素的更新方式。代码里采用蚁量算法更新信息素即:

 

就是释放的信息素除ij的距离。(为什么这么设置原因很简单,路径越长信息素就越少)。

最后就是通过新信息素=信息素残留系数*原来的信息素+增加的信息素的方式完成更新。其他的都是比较简单的了。

具体看代码吧!

#include <bits/stdc++.h>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
//#define NULL -1
typedef long long ll;
using namespace std;
double INF = 10e9;
const int num_ant=30;//蚂蚁的数量
const int num_city=30;//城市数量
const int MAX_GEN=1000;//最大迭代次数
int ALPHA = 1;//信息素的权重
int BETA = 4;//启发式因子重要程度权重
int remain = 100;//信息素残留参数
//double beat_path;//最优路径长度
double dis[num_city+50][num_city+50];//各个城市的距离
int city[num_city][2]={{87,7},{91,38},{83,46},{71,44},{64,60},{68,58},{83,69},{87,76},{74,78},{71,71},{58,69},{54,62},{51,67},{37,84},{41,94},{2,99},{7,64},{22,60},{25,62},{18,54},{4,50},{13,40},{18,40},{24,42},{25,38},{41,26},{45,21},{44,35},{58,35},{62,32}};
//各个城市的位置
int vis[num_city][num_city];//禁忌表
double info[num_city][num_city];//信息素矩阵
//double active[num_city][num_city];//启发因子矩阵
const int Q = 100;//信息素残留系数
double ROU = 0.5;//信息素残留度
unsigned seed=(unsigned)time(0);
int random (int l,int h)
{
    return l+(h-l)*rand()/(RAND_MAX+1);
}
double random(double l,double h)
{
    return l+(h-l)*rand()/(RAND_MAX+1.0);
}
double Random (double ans)
{
    return (double)((int)(ans+0.5));
}
double power(double x, int y)//快速幂
{
    double ans = 1;
    while(y)
    {
        if(y&1)ans*=x;
        x*=x;
        y>>=1;
    }
    return ans;
}
struct Ant
{
    int Path[num_city];
    double length;//当前已走的长度;
    int vis[num_city];//已走的城市
    int cur_city;//现在所在的城市
    int num_move;//已经走的城市数
    void Init()
    {
        memset(vis,0,sizeof(vis));
        length=0.0;
        cur_city=random(0,num_city);
        Path[0]=cur_city;
        vis[cur_city]=1;
        num_move=1;
    }
    int choose()
    {
        int select_city=-1;//选择的城市
        double sum=0.0;
        double possible_city[num_city];//各个城市被选中的概率
        for(int i=0;i<num_city;i++)
        {
            if(!vis[i])
            {
                possible_city[i]=power(info[cur_city][i],ALPHA)*power(1.0/dis[cur_city][i],BETA);
                sum+=possible_city[i];//计算概率
            }
            else
            {
                possible_city[i]=0;
            }
        }
        //轮盘赌选择
        double possible_du=0.0;
        //double sum_tmp=0.0;
        if(sum>0.0)
        {
            possible_du=random(0.0,sum);
            for(int i=0;i<num_city;i++)
            {
                if(!vis[i])
                {
                    possible_du-=possible_city[i];
                    if(possible_du<0.0)
                    {
                        select_city=i;
                        break;
                    }
                }
            }
        }
        if(select_city==-1)
        {
            for(int i=0;i<num_city;i++)
            {
                if(!vis[i])
                {
                    select_city=i;
                    break;
                }
            }
        }
        return select_city;
    }
    void move_ant()
    {
        //if(num_move>=30)printf("KKKKKKK");
        int next_city=choose();//选择的城市
        Path[num_move]=next_city;
        vis[next_city]=1;
        cur_city=next_city;//更新当前位置
        length+=dis[Path[num_move-1]][Path[num_move]];
        num_move++;
        //if(num_move>=30)printf("KKKKKKK");
    }
    void find_()
    {
        Init();
        while(num_move<num_city)
        {
            move_ant();
            //printf("%d ",num_move);
            //printf("?????");
        }
        //printf("???");
        length+=dis[Path[num_city-1]][Path[0]];//更新长度
        //printf("??");
    }
};
struct TSP
{
    Ant ants[num_ant];
    Ant ant_best;
    void Init()
    {
        ant_best.length=double(INF);//初始化最优的蚂蚁,设为最大
        printf("Begin to count
");
        for(int i=0;i<num_city;i++)
        {
            for(int j=0;j<num_city;j++)
            {
                double tmp1=city[j][0]-city[i][0];
                double tmp2=city[j][1]-city[i][1];
                dis[i][j]=sqrt(tmp1*tmp1+tmp2*tmp2);//计算每个城市间的距离
                //printf("%d %d %lf
",i,j,dis[i][j]);
            }
        }
        printf("Init Information
");
        for(int i=0;i<num_city;i++)
        {
            for(int j=0;j<num_city;j++)
            {
                info[i][j]=1.0;//初始化信息素
            }
        }
    }
    void Update()
    {
        double tmpinfo[num_city][num_city];//临时矩阵储存新增的信息素
        memset(tmpinfo,0,sizeof(tmpinfo));
        int n=0;
        int m=0;
        //蚁量算法更新信息素
        for(int i=0;i<num_ant;i++)
        {
            for(int j=1;j<num_city;j++)
            {
                n=ants[i].Path[j-1];
                m=ants[i].Path[j];
                tmpinfo[n][m]+=Q/ants[i].length;
                tmpinfo[m][n]=tmpinfo[n][m];
            }
            n=ants[i].Path[0];
            tmpinfo[n][m]+=Q/ants[i].length;
            tmpinfo[m][n]=tmpinfo[n][m];
        }
        //更新环境的信息素
        for(int i=0;i<num_city;i++)
        {
            for(int j=0;j<num_city;j++)
            {
                //新环境的信息素=残留的+新留下的
                info[i][j]=info[i][j]*ROU+tmpinfo[i][j];//感觉ROU有待商榷
            }
        }
    }

    void find_()
    {
        for(int i=0;i<MAX_GEN;i++)
        {
            printf("current generation is %d
",i);
            for(int j=0;j<num_ant;j++)
            {
                ants[j].find_();
                //printf("****");
            }
            for(int j=0;j<num_ant;j++)
            {
                if(ant_best.length>ants[j].length)
                {
                    ant_best=ants[j];//更新每一代的最优解
                }
            }
            Update();
            printf("current best length is %lf
",ant_best.length);
        }
    }
};
int main()
{
    srand(seed);//随机函数初始化
    TSP tsp;
//    printf("Please enter 30 cities position
");
//    for(int i=0;i<30;i++)
//    {
//        scanf("%d%d",&city[i][0],&city[i][1]);//可以自己手动输入城市位置
//    }
    tsp.Init();
    tsp.find_();
    printf("The minimum path is 
");
    for(int i=0;i<num_city;i++)
    {
        printf("%d ",tsp.ant_best.Path[i]);//打印出路径
    }
    return 0;
}
原文地址:https://www.cnblogs.com/kayiko/p/12049296.html