找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 70|回复: 0

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

[复制链接]

0

主题

0

回帖

26

积分

管理员

积分
26
发表于 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. }
复制代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|膜结构网

GMT+8, 2024-12-27 22:28 , Processed in 0.105600 second(s), 18 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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