找回密码
 立即注册

QQ登录

只需一步,快速开始

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

蚁群算法原理及c++实现

[复制链接]

0

主题

0

回帖

26

积分

管理员

积分
26
发表于 2024-7-16 23:10:58 | 显示全部楼层 |阅读模式
  1. //轮盘赌选择下一步行进城市
  2. int citySelect(int k, int f)
  3. {
  4.         int c = 0;//记录蚂蚁可行进的城市个数
  5.         //1、计算可行进的各城市 选择概率
  6.         for (int m = 0; m < cityNum; m++)
  7.         {
  8.                 //若城市(i,j)之间有路且j不在蚂蚁k的禁忌表中,则计算概率
  9.                 if (dist(ants[k].loc, m) != -1 && !ifCityInTabu(m, k))
  10.                 {
  11.                         cityProb[c].num = m;
  12.                         cityProb[c].prob = citySelProb(k, m);
  13.                         c++;
  14.                 }
  15.         }
  16.         //2、线性化选择概率
  17.         for (int m = 0; m < c; m++)
  18.         {
  19.                 for (int n = m; n >= 0; n--)
  20.                 {
  21.                         lineCityProb[m] += cityProb[n].prob;
  22.                 }
  23.         }
  24.         //3、产生随机数选择城市
  25.         double r = rand() / double(RAND_MAX);
  26.         int j = 0;   //选取的目标城市
  27.         for (int m = 0; m < cityNum; m++)
  28.         {
  29.                 if (r <= lineCityProb[m])
  30.                 {
  31.                         j = cityProb[m].num;
  32.                         updateAnt(k, j);
  33.                         if (j == f)
  34.                                 ants[k].flag = 1;  //若蚂蚁k下一步城市为目的地城市,则修改标志
  35.                         return j;
  36.                 }
  37.         }
  38. }
  39. void updatePher()
  40. {
  41.         for (int i = 0; i < antNum; i++)
  42.         {
  43.                 if(ants[i].flag == 1)  //只对到达目的点的蚂蚁 所走过路径 更新信息素
  44.                         for (int j = 0; j < pathNum; j++)
  45.                         {
  46.                                 if (ants[i].antPath[j] == -1 || ants[i].antPath[j + 1] == -1)
  47.                                         break;
  48.                                 else
  49.                                         nextPher(ants[i].antPath[j], ants[i].antPath[j + 1])
  50.                                         += pQ / getAntLen(ants[i]);
  51.                         }
  52.                
  53.         }
  54.         nextPher = pVol * pher + nextPher;
  55. }
  56. const int cityNum = 8;     //城市数量
  57. const int pathNum = 16;    //路径数量
  58. const int antNum = 12;     //蚂蚁数量(1.5倍城市数量)
  59. const double pVol = 0.3;   //信息素挥发系数 0.2~0.5
  60. const int pQ = 10;         //信息素强度 10~1000
  61. const double pImp = 3;     //信息素相对重要性 1~4
  62. const double qImp = 4;     //启发信息相对重要性 3~4.5
  63. const int gen = 100;       //迭代次数 100~500
复制代码


  1. #include<iostream>
  2. #include<Eigen\Dense>
  3. #include<stdlib.h>
  4. #include<time.h>
  5. #include<math.h>
  6. using namespace Eigen;
  7. using namespace std;
  8. /*
  9.    功能:此代码使用蚁群算法计算源点0 ~ 其他定点的最短路径
  10.    author:yuzewei
  11.    date:2020/12/19
  12. */
  13. #define CLOCK_PER_SEC ((clock_t)1000)
  14. const int cityNum = 8;     //城市数量
  15. const int pathNum = 16;    //路径数量
  16. const int antNum = 12;     //蚂蚁数量(1.5倍城市数量)
  17. const double pVol = 0.3;   //信息素挥发系数 0.2~0.5
  18. const int pQ = 10;         //信息素强度 10~1000
  19. const double pImp = 3;     //信息素相对重要性 1~4
  20. const double qImp = 4;     //启发信息相对重要性 3~4.5
  21. const int gen = 100;       //迭代次数 100~500
  22. struct ant                 //蚂蚁结构体
  23. {
  24.         int loc;               //位置
  25.         int tabu[cityNum];     //禁忌表
  26.         int antPath[pathNum];  //走过的路
  27.         bool flag;             //是否到达终点7
  28. };
  29. struct ant ants[antNum];   //蚁群
  30. typedef Matrix<double, 8, 8> Matrix8d;
  31. Matrix8d dist;             //距离矩阵
  32. Matrix8d pher;             //信息素矩阵
  33. Matrix8d nextPher;         //下一代信息素矩阵
  34. Matrix8d insp;             //启发信息矩阵
  35. struct city                //城市结构体
  36. {
  37.         int num;               //编号
  38.         double prob;           //选择概率
  39. };
  40. struct city cityProb[cityNum];    //可到达城市组
  41. double lineCityProb[cityNum];     //线性化 可到达城市的选择概率
  42. clock_t start, finish;     
  43. double duration;
  44. void initAnts();                  
  45. void initCityProb();              
  46. void initMarix();   
  47. bool ifCityInTabu(int, int);
  48. int citySelect(int, int);
  49. void updateAnt(int, int);
  50. double citySelProb(int, int);
  51. int getAntLen(ant);
  52. int getBestPath();
  53. void printBestPath(int, int);
  54. void updatePher();
  55. void evolution();
  56. int main()
  57. {
  58.         srand((unsigned)time(NULL));
  59.         evolution();
  60. }
  61. //蚁群初始化
  62. void initAnts()
  63. {
  64.         //初始化禁忌表与行走路线
  65.         for (int i = 0; i < antNum; i++)
  66.         {
  67.                 for (int j = 0; j < cityNum; j++)
  68.                 {
  69.                         ants[i].tabu[j] = -1;
  70.                 }
  71.                 for (int j = 0; j < pathNum; j++)
  72.                 {
  73.                         ants[i].antPath[j] = -1;
  74.                 }
  75.         }
  76.         //将蚂蚁放入城市
  77.         for (int i = 0; i < antNum; i++)
  78.         {
  79.                 //ants[i].loc = rand() % 8;
  80.                 ants[i].loc = 0;//出发点都在起点
  81.                 ants[i].tabu[0] = ants[i].loc;
  82.                 ants[i].antPath[0] = ants[i].loc;
  83.                 ants[i].flag = 0;
  84.         }
  85. }
  86. //初始化城市选择概率数组
  87. void initCityProb()
  88. {
  89.         for (int i = 0; i < cityNum; i++)
  90.         {
  91.                 cityProb[i].num = -1;
  92.                 cityProb[i].prob = 0;
  93.                 lineCityProb[i] = 0;
  94.         }
  95. }
  96. //初始化距离、信息素、启发信息矩阵
  97. void initMarix()
  98. {
  99.         dist = Matrix8d::Constant(8, 8, -1);
  100.         dist(0, 2) = 47;
  101.         dist(0, 4) = 70;
  102.         dist(0, 5) = 24;
  103.         dist(1, 3) = 31;
  104.         dist(1, 6) = 74;
  105.         dist(1, 7) = 79;
  106.         dist(2, 1) = 55;
  107.         dist(2, 3) = 88;
  108.         dist(2, 4) = 23;
  109.         dist(2, 6) = 66;
  110.         dist(3, 7) = 29;
  111.         dist(4, 1) = 31;
  112.         dist(4, 6) = 42;
  113.         dist(5, 2) = 25;
  114.         dist(5, 3) = 120;
  115.         dist(6, 7) = 66;
  116.         pher = Matrix8d::Zero();
  117.         nextPher = Matrix8d::Zero();
  118.         insp = Matrix8d::Zero();
  119.         for (int i = 0; i < 8; i++)
  120.         {
  121.                 for (int j = 0; j < 8; j++)
  122.                 {
  123.                         if (dist(i, j) != -1)
  124.                         {
  125.                                 insp(i, j) = 1 / dist(i, j);//启发信息为距离的倒数
  126.                                 pher(i, j) = 1;             //信息素浓度初始值为1
  127.                         }
  128.                 }
  129.         }
  130. }
  131. //轮盘赌选择下一步行进城市
  132. int citySelect(int k, int f)
  133. {
  134.         int c = 0;//记录蚂蚁可行进的城市个数
  135.         //1、计算可行进的各城市 选择概率
  136.         for (int m = 0; m < cityNum; m++)
  137.         {
  138.                 //若城市(i,j)之间有路且j不在蚂蚁k的禁忌表中,则计算概率
  139.                 if (dist(ants[k].loc, m) != -1 && !ifCityInTabu(m, k))
  140.                 {
  141.                         cityProb[c].num = m;
  142.                         cityProb[c].prob = citySelProb(k, m);
  143.                         c++;
  144.                 }
  145.         }
  146.         //2、线性化选择概率
  147.         for (int m = 0; m < c; m++)
  148.         {
  149.                 for (int n = m; n >= 0; n--)
  150.                 {
  151.                         lineCityProb[m] += cityProb[n].prob;
  152.                 }
  153.         }
  154.         //3、产生随机数选择城市
  155.         double r = rand() / double(RAND_MAX);
  156.         int j = 0;   //选取的目标城市
  157.         for (int m = 0; m < cityNum; m++)
  158.         {
  159.                 if (r <= lineCityProb[m])
  160.                 {
  161.                         j = cityProb[m].num;
  162.                         updateAnt(k, j);
  163.                         if (j == f)
  164.                                 ants[k].flag = 1;  //若蚂蚁k下一步城市为目的地城市,则修改标志
  165.                         return j;
  166.                 }
  167.         }
  168. }
  169. //更新蚂蚁信息
  170. void updateAnt(int k, int l)
  171. {
  172.         ants[k].loc = l;
  173.         for (int i = 0; i < cityNum; i++)
  174.                 if (ants[k].tabu[i] == -1)
  175.                 {
  176.                         ants[k].tabu[i] = l;
  177.                         break;
  178.                 }
  179.         for (int i = 0; i < pathNum; i++)
  180.                 if (ants[k].antPath[i] == -1)
  181.                 {
  182.                         ants[k].antPath[i] = l;
  183.                         break;
  184.                 }
  185. }
  186. //蚂蚁k从当前城市i选择下一步行进城市为j市的概率
  187. double citySelProb(int k, int j)
  188. {
  189.         double a, b, c, prob;
  190.         a = b = c = prob = 0;
  191.         int i = ants[k].loc;
  192.         a = pow(pher(i, j), pImp) + pow(insp(i, j), qImp);
  193.         for (int m = 0; m < cityNum; m++)
  194.         {
  195.                 if (dist(i, m) != -1 && !ifCityInTabu(m, k))
  196.                 {
  197.                         b = pow(pher(i, m), pImp) + pow(insp(i, m), qImp);
  198.                         c += b;
  199.                 }
  200.         }
  201.         prob = a / c;
  202.         return prob;
  203. }
  204. //判断城市j是否在蚂蚁k的禁忌表中
  205. bool ifCityInTabu(int j, int k)
  206. {
  207.         for (int i = 0; i < cityNum; i++)
  208.         {
  209.                 if (j == ants[k].tabu[i])
  210.                 {
  211.                         return 1;
  212.                         //break;
  213.                 }
  214.         }
  215.         return 0;
  216. }
  217. //计算路径长度
  218. int getAntLen(struct ant a)
  219. {
  220.         int len = 0;
  221.         for (int j = 0; j < pathNum; j++)
  222.         {
  223.                 if (a.antPath[j] == -1 || a.antPath[j + 1] == -1)
  224.                         break;
  225.                 else
  226.                         len += dist(a.antPath[j], a.antPath[j + 1]);
  227.         }
  228.         return len;
  229. }
  230. //计算最优路径对应的蚂蚁编号
  231. int getBestPath()
  232. {
  233.         int d[antNum];
  234.         int min;
  235.         int k;  //蚂蚁k的路线到达目的地节点最短
  236.         for (int i = 0; i < antNum; i++)
  237.         {
  238.                 d[i] = -1;
  239.         }
  240.         for (int i = 0; i < antNum; i++)
  241.         {
  242.                
  243.                 d[i] = getAntLen(ants[i]);
  244.         }
  245.         min = d[0];
  246.         k = 0;
  247.         for (int i = 1; i < antNum; i++)
  248.         {
  249.                 if (d[i] < min && ants[i].flag == 1)  // 最优路径只从到达目标点的蚂蚁中筛选
  250.                 {
  251.                         min = d[i];
  252.                         k = i;
  253.                 }
  254.         }
  255.         return k;
  256. }
  257. //打印最优路径、最短距离
  258. void printBestPath(int k, int f)
  259. {
  260.         cout << "  最短路径为:";
  261.         for (int i = 0; i < pathNum; i++)
  262.         {
  263.                 if (ants[k].antPath[i] == -1)
  264.                         break;
  265.                 cout << ants[k].antPath[i];
  266.                 if (ants[k].antPath[i+1] != -1)
  267.                         cout << "->";
  268.         }
  269.         cout << endl;
  270.         cout << "  对应距离为:" << getAntLen(ants[k]) << endl;
  271. }
  272. //更新信息素矩阵
  273. void updatePher()
  274. {
  275.         for (int i = 0; i < antNum; i++)
  276.         {
  277.                 if(ants[i].flag == 1)  //只对到达目的点的蚂蚁 所走过路径 更新信息素
  278.                         for (int j = 0; j < pathNum; j++)
  279.                         {
  280.                                 if (ants[i].antPath[j] == -1 || ants[i].antPath[j + 1] == -1)
  281.                                         break;
  282.                                 else
  283.                                         nextPher(ants[i].antPath[j], ants[i].antPath[j + 1])
  284.                                         += pQ / getAntLen(ants[i]);
  285.                         }
  286.                
  287.         }
  288.         nextPher = pVol * pher + nextPher;
  289. }
  290. //迭代
  291. void evolution()
  292. {
  293.         for (int f = 1; f < cityNum; f++)
  294.         {
  295.                 cout << "【从源点0到定点" << f << "】" << endl;
  296.                 cout << "开始迭代........." << endl;
  297.                 //初始化参数
  298.                 initAnts();
  299.                 initMarix();
  300.                 int g = 0; //当前代数
  301.                 start = clock();
  302.                 while (g < gen)
  303.                 {
  304.                         //1、蚁群内所有蚂蚁都到达目的地
  305.                         int p = 0; //蚁群前进步数
  306.                         while (p < pathNum)
  307.                         {
  308.                                 for (int i = 0; i < antNum; i++)
  309.                                 {
  310.                                         if (ants[i].flag == 1)//到达目的地
  311.                                                 continue;
  312.                                         citySelect(i, f);
  313.                                         initCityProb();
  314.                                 }
  315.                                 p++;
  316.                         }
  317.                         if (g == gen - 1)
  318.                         {
  319.                                 cout << "达到最高迭代次数!" << endl;
  320.                                 printBestPath(getBestPath(), f);
  321.                         }
  322.                                
  323.                         //3、更新信息素矩阵
  324.                         updatePher();
  325.                         //4、初始化蚁群;更新信息素矩阵
  326.                         initAnts();
  327.                         pher = nextPher;
  328.                         nextPher = Matrix8d::Zero();
  329.                         g++;
  330.                 }
  331.                 finish = clock();
  332.                 duration = ((double)finish - start) / CLOCK_PER_SEC;
  333.                 cout << "  耗时:" << duration << "秒" << endl;
  334.         }
  335. }
复制代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2024-12-27 22:37 , Processed in 0.137828 second(s), 19 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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