天气与日历 切换到窄版

 找回密码
 立即注册
中国膜结构网
十大进口膜材评选 十大国产膜材评选 十大膜结构设计评选 十大膜结构公司评选
查看: 53|回复: 0

C++下基于蚁群算法解决TSP问题

[复制链接]
  • TA的每日心情
    开心
    昨天 15:13
  • 签到天数: 153 天

    [LV.7]常住居民III

    3456

    主题

    553

    回帖

    214748万

    积分

    管理员

    中国膜结构网www.mjgou.com

    积分
    2147483647
    QQ
    发表于 2024-7-16 23:09:23 | 显示全部楼层 |阅读模式
    1. #include <iostream>
    2. #include <fstream>
    3. #include <stdlib.h>
    4. #include <time.h>
    5. #include <stdio.h>
    6. #include <vector>
    7. #include <algorithm>


    8. using namespace std;

    9. #define m 100                                //蚂蚁的个数
    10. #define n 31                                //城市的数量

    11. const int NC_max = 100;                //最大迭代次数
    12. const double Alpha = 1;                //表征信息素重要程度的参数
    13. const double Beta = 5;                //表征启发式因子重要程度的参数
    14. const double Rho = 0.1;                //信息素蒸发系数
    15. const double Q = 100;                //信息素增加强度系数
    16. const double C[n][2] =                //各个城市的坐标数据
    17. { { 1304, 2312 },
    18.         { 3639, 1315 },
    19.         { 4177, 2244 },
    20.         { 3712, 1399 },
    21.         { 3488, 1535 },
    22.         { 3326, 1556 },
    23.         { 3238, 1229 },
    24.         { 4196, 1004 },
    25.         { 4312, 790 },
    26.         { 4386, 570 },
    27.         { 3007, 1970 },
    28.         { 2562, 1756 },
    29.         { 2788, 1491 },
    30.         { 2381, 1676 },
    31.         { 1332, 695 },
    32.         { 3715, 1678 },
    33.         { 3918, 2179 },
    34.         { 4061, 2370 },
    35.         { 3780, 2212 },
    36.         { 3676, 2578 },
    37.         { 4029, 2838 },
    38.         { 4263, 2931 },
    39.         { 3429, 1908 },
    40.         { 3507, 2367 },
    41.         { 3394, 2643 },
    42.         { 3439, 3201 },
    43.         { 2935, 3240 },
    44.         { 3140, 3550 },
    45.         { 2545, 2357 },
    46.         { 2778, 2826 },
    47.         { 2370, 2975 }
    48. };

    49. double D[n][n];                        //表示完全图的邻接矩阵
    50. double Eta[n][n];                //表示启发式因子,为D中距离的倒数
    51. double DeltaTau[n][n];        //表示启发式因子的变化量
    52. double Tau[n][n];                //路径上面信息素的浓度
    53. int Tabu[m][n];                        //禁忌表,存储走过的路径

    54. double L_best[NC_max];                //存储每次迭代的路径的最短长度
    55. double L_ave[NC_max];                //存储每次迭代的路径的平均长度
    56. int R_best[NC_max][n];                //存储每次迭代的最佳路线


    57. void ValueInit(void)                //变量初始化函数
    58. {
    59.         for (int i = 0; i < n; i++)                        //初始化 D[n][n]  31
    60.         {
    61.                 for (int j = 0; j < n; j++)//31
    62.                 {
    63.                         if (i != j)
    64.                                 D[i][j] = pow(pow((C[i][0] - C[j][0]), 2) + pow((C[i][1] - C[j][1]), 2), 0.5);
    65.                         else
    66.                                 D[i][j] = DBL_EPSILON;//极小数,对角线上的数0
    67.                 }
    68.         }

    69.         for (int i = 0; i < n; i++)                        //初始化 Eta[n][n]  启发式因子,距离矩阵倒数
    70.                 for (int j = 0; j < n; j++)
    71.                         Eta[i][j] = 1.0 / D[i][j];

    72.         for (int i = 0; i < n; i++)                        //初始化 DeltaEta[n][n]  启发式因子变化量
    73.                 for (int j = 0; j < n; j++)
    74.                         DeltaTau[i][j] = 0;

    75.         for (int i = 0; i < n; i++)                        //初始化 Tau[n][n]  信息素浓度
    76.                 for (int j = 0; j < n; j++)
    77.                         Tau[i][j] = 1.0;

    78.         for (int i = 0; i < m; i++)                        //初始化 Tabu[m][n]  存储走过的路径
    79.                 for (int j = 0; j < n; j++)
    80.                         Tabu[i][j] = 0;
    81. }

    82. void ValueDisplayTabu(int(*p)[n])        //禁忌表,存储走过的路径, 显示函数
    83. {
    84.         for (int i = 0; i < m; i++)
    85.         {
    86.                 for (int j = 0; j < n; j++)
    87.                 {
    88.                         cout << *(*(p + i) + j) << ' ';
    89.                 }
    90.                 cout << endl;
    91.         }
    92. }

    93. void ValueDisplayTau(double(*p)[n])                //信息素的浓度,显示函数
    94. {
    95.         for (int i = 0; i < n; i++)
    96.         {
    97.                 for (int j = 0; j < n; j++)
    98.                 {
    99.                         cout << *(*(p + i) + j) << ' ';
    100.                 }
    101.                 cout << endl;
    102.         }
    103. }

    104. double rnd(double lower, double uper)        //生成lower和uper之间的一个double类型随机数
    105. {
    106.         return  (rand() / (double)RAND_MAX) * (uper - lower) + lower;
    107. }

    108. int main()
    109. {
    110.         //第一步:进行变量的初始化
    111.         ValueInit();  //计算距离矩阵、初始化启发因子

    112.         int NC = 0;
    113.         while (NC < NC_max)//迭代次数100
    114.         {
    115.                 //第二步:将m只蚂蚁随机放到n个城市上
    116.                 vector<int> temp;
    117.                 for (int i = 0; i < ceil((double)m / (double)n); i++) //m/n  蚂蚁数/城市数 100/31
    118.                 {
    119.                         for (int j = 0; j < n; j++)//31
    120.                                 temp.push_back(j);
    121.                 }

    122.                 random_shuffle(temp.begin(), temp.end());        //打乱temp数组中元素的次序

    123.                 for (int i = 0; i < m; i++)//100
    124.                 {
    125.                         Tabu[i][0] = temp[i];//走过的路径,一共100个城市访问路径,第一个城市为随机选取的,temp里面有124个城市点
    126.                 }

    127.                 //第三步:m只蚂蚁按概率函数选择n中的下一座城市,完成各自的周游
    128.                 for (int j = 1; j < n; j++)//31
    129.                 {
    130.                         for (int i = 0; i < m; i++)//100个路径
    131.                         {
    132.                                 vector<int> visited;        //第i只蚂蚁已访问过的城市
    133.                                 vector<int> J;                        //第i只蚂蚁待访问的城市
    134.                                 vector<double> P;                //第i只蚂蚁待访问的城市的概率

    135.                                 double Psum = 0.0;                //概率值和
    136.                                 double rate = 0.0;                //随机数
    137.                                 double choose = 0.0;        //轮盘赌算法累加值
    138.                                 int to_visit=0;                        //下一个要去的城市

    139.                                 for (int k = 0; k < j; k++)
    140.                                         visited.push_back(Tabu[i][k]);        //visited初始化  0,0

    141.                                 for (int k = 0; k < n; k++)//31
    142.                                 {
    143.                                         if (find(visited.begin(), visited.end(), k) == visited.end())        //在visited中没有找到k
    144.                                         {
    145.                                                 J.push_back(k);                                //J初始化  待访问城市
    146.                                                 P.push_back(0.0);                        //P初始化  访问的概率
    147.                                         }
    148.                                 }

    149.                                 for (int k = 0; k < P.size(); k++)
    150.                                 {
    151.                                         //计算去某个城市的概率
    152.                                         int x = Tau[visited.back()][J[k]];  //Tau=1  Alpha=1   Beta=5  Eta=1/Distance(距离越小,这个值越大)
    153.                                         P[k] = pow(Tau[visited.back()][J[k]], Alpha) * pow(Eta[visited.back()][J[k]], Beta);//5
    154.                                         Psum += P[k];
    155.                                 }

    156.                                 //随机生成0~Psum之间的一个数
    157.                                 rate = rnd(0.0, Psum);                                //使用轮盘赌算法,挑选下一座要去的城市
    158.                                 for (int k = 0; k < P.size(); k++)
    159.                                 {
    160.                                         choose += P[k];
    161.                                         if (rate < choose)
    162.                                         {
    163.                                                 to_visit = J[k];//待访问城市
    164.                                                 break;
    165.                                         }
    166.                                 }

    167.                                 //访问的路径
    168.                                 Tabu[i][j] = to_visit;                                //更新禁忌表 100条访问城市的路径  每个城市初始信息素
    169.                         }
    170.                 }

    171.                 //第四步:记录本次迭代蚂蚁行走的路线数据
    172.                 double L[m];        //记录本代每只蚂蚁走的路程,并初始化 100个路径
    173.                 for (int i = 0; i < m; i++)
    174.                 {
    175.                         L[i] = 0.0;
    176.                 }
    177.                 for (int i = 0; i < m; i++)//100
    178.                 {
    179.                         for (int j = 0; j < n - 1; j++)//31
    180.                         {
    181.                                 L[i] += D[Tabu[i][j]][Tabu[i][j + 1]];//L[i]代表第i个路径的代价
    182.                         }
    183.                         L[i] += D[Tabu[i][0]][Tabu[i][n - 1]]; //终点和起点的距离
    184.                 }

    185.                 double min_value = L[0];        //声明求本代所有蚂蚁行走距离最小值的临时变量
    186.                 double sum_value = L[0];        //声明求本代所有蚂蚁行走距离总值的临时变量
    187.                 int min_index = 0;                        //记录本代所有蚂蚁行走距离最小值的下标
    188.                 for (int i = 1; i < m; i++)
    189.                 {
    190.                         sum_value += L[i];
    191.                         if (L[i] < min_value)
    192.                         {
    193.                                 min_value = L[i];
    194.                                 min_index = i;
    195.                         }
    196.                 }

    197.                 L_best[NC] = min_value;                                                //每代中路径的最短长度
    198.                 L_ave[NC] = sum_value / m;                                        //每代中路径的平均长度

    199.                 for (int i = 0; i < n; i++)
    200.                 {
    201.                         R_best[NC][i] = Tabu[min_index][i];                //记录每代最短的路径数据
    202.                 }

    203.                 cout << NC << ": best cost is: " << L_best[NC] << '    ' << "the avg of ever iter is: " << L_ave[NC] << endl;        //打印各代距离信息

    204.                 NC++;        //迭代继续

    205.                 //第五步:更新信息素
    206.                 for (int i = 0; i < m; i++)
    207.                 {
    208.                         for (int j = 0; j < n - 1; j++)
    209.                         {
    210.                                 //DeltaTau[i][j]信息素增量,表示蚂蚁在i到j路径上留下的信息素,L[i]表示蚂蚁已经走过路径的总长度
    211.                                 //所以总长度越小,信息素越多
    212.                                 DeltaTau[Tabu[i][j]][Tabu[i][j + 1]] += Q / L[i];        //此次循环在整个路径上的信息素增量 Q=100
    213.                         }
    214.                         DeltaTau[Tabu[i][n - 1]][Tabu[i][0]] += Q / L[i];
    215.                 }

    216.                 for (int i = 0; i < n; i++)//100
    217.                 {
    218.                         for (int j = 0; j < n; j++)
    219.                         {
    220.                                 //Tau[i][j] 路径i到j上的信息素残余量
    221.                                 Tau[i][j] = (1 - Rho) * Tau[i][j] + DeltaTau[i][j];        //考虑信息素挥发,更新后的信息素 T = p * T + delta  Qho=0.1,信息素挥发速度
    222.                         }
    223.                 }

    224.                 for (int i = 0; i < m; i++)                        //信息素清零
    225.                         for (int j = 0; j < n; j++)
    226.                                 Tabu[i][j] = 0;
    227.         }

    228.         //第六步:取出最优结果
    229.         double min_L = L_best[0];                        //所有迭代中最短距离
    230.         int min_L_index = 0;                                //所有迭代中最优路径的下标
    231.         int Shortest_Route[n];                                //所有迭代中的最优路径
    232.         for (int i = 0; i < NC; i++)
    233.         {
    234.                 if (L_best[i] < min_L)
    235.                 {
    236.                         min_L = L_best[i];
    237.                         min_L_index = i;
    238.                 }
    239.         }

    240.         cout << "The length of the shortest route is " << min_L << endl;
    241.         cout << "The number of iteration is " << min_L_index << endl;
    242.         cout << "The Shortest route is: " << endl;

    243.         for (int i = 0; i < n; i++)                //所有迭代中的最优路径
    244.         {
    245.                 Shortest_Route[i] = R_best[min_L_index][i];
    246.                 if (i == n - 1) {
    247.                         cout << Shortest_Route[i];
    248.                 }
    249.                 else {
    250.                         cout << Shortest_Route[i] << " -> ";
    251.                 }
    252.         }
    253.         std::cout<<std::endl;
    254.         system("pause");
    255.         return 0;
    256. }
    复制代码

     

     

     

     

    C++下基于蚁群算法解决TSP问题
    中国膜结构网打造全中国最好的膜结构综合平台 ,统一协调膜结构设计,膜结构施工,膜材采购,膜材定制,膜结构预算全方位服务。 中国空间膜结构协会合作单位。
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|手机版|中国膜结构网|中国膜结构协会|进口膜材|国产膜材|ETFE|PVDF|PTFE|设计|施工|安装|车棚|看台|污水池| |网站地图

    GMT+8, 2024-9-8 09:15 , Processed in 0.059609 second(s), 22 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表