找回密码
 立即注册

QQ登录

只需一步,快速开始

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

c++蚁群算法源码

[复制链接]

0

主题

0

回帖

26

积分

管理员

积分
26
发表于 2024-7-16 23:16:03 | 显示全部楼层 |阅读模式
  1. #include<iostream>
  2. #include<math.h>
  3. #include<time.h>
  4. using namespace std;
  5. //该程序是以蚁群系统为模型写的蚁群算法程序(强调:非蚂蚁周模型),以三个著名的TSP问题为测试对象
  6. //通过微调参数,都可以获得较好的解
  7. /*
  8. //----------(1)问题一:Oliver 30 城市 TSP 问题 best_length = 423.7406; ------------------------
  9. //该程序最好的结果是423.741,可运行多次获得
  10. //城市节点数目
  11. #define N 30
  12. //城市坐标
  13. double C[N][2]={
  14.         {2,99},{4,50},{7,64},{13,40},{18,54},{18,40},{22,60},{24,42},{25,62},{25,38},
  15.         {37,84},{41,94},{41,26},{44,35},{45,21},{54,67},{54,62},{58,35},{58,69},{62,32},
  16.         {64,60},{68,58},{71,44},{71,71},{74,78},{82,7},{83,46},{83,69},{87,76},{91,38}
  17. };
  18. //----------上面参数是固定的,下面的参数是可变的-----------
  19. //蚂蚁数量
  20. #define M 30
  21. //最大循环次数NcMax
  22. int NcMax = 500;
  23. //信息启发因子,期望启发式因子,全局信息素挥发参数,局部信息素挥发参数, 状态转移公式中的q0
  24. double alpha = 2, beta = 3, rou = 0.1, alpha1 = 0.1,  qzero = 0.01;
  25. //-----------问题一结束------------------------------------------------------------------------
  26. */
  27. /*
  28. //----------(2)问题二:Elion50 城市 TSP 问题 best_length = 427.96; ----------------------------
  29. //该程序最好的结果是428.468,可运行多次获得
  30. //城市节点数目
  31. #define N 50
  32. //城市坐标
  33. double C[N][2]={
  34.         {5,64}, {5,25}, {5,6}, {7,38}, {8,52}, {10,17},
  35.         {12,42}, {13,13}, {16,57}, {17,33}, {17,63},
  36.         {20,26}, {21,47}, {21,10}, {25,32}, {25,55},
  37.         {27,68}, {27,23}, {30,48}, {30,15}, {31,62},
  38.         {31,32}, {32,22}, {32,39}, {36,16}, {37,69},
  39.         {37,52}, {38,46}, {39,10}, {40,30}, {42,57},
  40.         {42,41}, {43,67}, {45,35}, {46,10}, {48,28},
  41.         {49,49}, {51,21}, {52,33}, {52,41}, {52,64},
  42.         {56,37}, {57,58}, {58,27}, {58,48}, {59,15},
  43.         {61,33}, {62,42}, {62,63}, {63,69}
  44. };
  45. //----------上面参数是固定的,下面的参数是可变的-----------
  46. //蚂蚁数量
  47. #define M 50
  48. //最大循环次数NcMax
  49. int NcMax = 1000;
  50. //信息启发因子,期望启发式因子,全局信息素挥发参数,局部信息素挥发参数, 状态转移公式中的q0
  51. double alpha = 2, beta = 4, rou = 0.1, alpha1 = 0.1,  qzero = 0.01;
  52. //-----------问题二结束------------------------------------------------------------------------
  53. */
  54. //----------(3)问题三:Elion75 城市 TSP 问题 best_length = 542.31;
  55. //该程序最好的结果是542.309,可运行多次获得
  56. //城市节点数目
  57. #define N 75
  58. //城市坐标
  59. double C[N][2]={
  60. {6,25}, {7,43}, {9,56}, {10,70}, {11,28},
  61. {12,17}, {12,38}, {15,5}, {15,14}, {15,56},
  62. {16,19}, {17,64}, {20,30}, {21,48}, {21,45},
  63. {21,36}, {22,53}, {22,22}, {26,29}, {26,13},
  64. {26,59}, {27,24}, {29,39}, {30,50}, {30,20},
  65. {30,60}, {31,76}, {33,34}, {33,44}, {35,51},
  66. {35,16}, {35,60}, {36,6}, {36,26}, {38,33},
  67. {40,37}, {40,66}, {40,60}, {40,20}, {41,46},
  68. {43,26}, {44,13}, {45,42}, {45,35}, {47,66},
  69. {48,21}, {50,30}, {50,40}, {50,50}, {50,70},
  70. {50,4}, {50,15}, {51,42}, {52,26}, {54,38},
  71. {54,10}, {55,34}, {55,45}, {55,50}, {55,65},
  72. {55,57}, {55,20}, {57,72}, {59,5}, {60,15},
  73. {62,57}, {62,48}, {62,35}, {62,24}, {64,4},
  74. {65,27}, {66,14}, {66,8}, {67,41}, {70,64}
  75. };
  76. //----------上面参数是固定的,下面的参数是可变的-----------
  77. //蚂蚁数量
  78. #define M 75
  79. //最大循环次数NcMax
  80. int NcMax =1000;
  81. //信息启发因子,期望启发式因子,全局信息素挥发参数,局部信息素挥发参数, 状态转移公式中的q0
  82. double alpha = 2, beta = 5, rou = 0.1, alpha1 = 0.1,  qzero = 0.1;
  83. //-----------问题三结束------------------------------------------------------------------------
  84. //===========================================================================================================
  85. //局部更新时候使用的的常量,它是由最近邻方法得到的一个长度
  86. //什么是最近邻方法?:)就是从源节点出发,每次选择一个距离最短的点来遍历所有的节点得到的路径
  87. //每个节点都可能作为源节点来遍历
  88. double Lnn;
  89. //矩阵表示两两城市之间的距离
  90. double allDistance[N][N];
  91. //计算两个城市之间的距离
  92. double calculateDistance(int i, int j)
  93. {
  94.         return sqrt(pow((C[i][0]-C[j][0]),2.0) + pow((C[i][1]-C[j][1]),2.0));
  95. }
  96. //由矩阵表示两两城市之间的距离
  97. void calculateAllDistance()
  98. {
  99.         for(int i = 0; i < N; i++)
  100.         {
  101.                 for(int j = 0; j < N; j++)
  102.                 {
  103.                         if (i != j)
  104.                         {
  105.                                 allDistance[i][j] = calculateDistance(i, j);
  106.                                 allDistance[j][i] = allDistance[i][j];
  107.                         }
  108.                 }
  109.         }
  110. }
  111. //获得经过n个城市的路径长度
  112. double calculateSumOfDistance(int* tour)
  113. {
  114.         double sum = 0;
  115.         for(int i = 0; i< N ;i++)
  116.         {
  117.                 int row = *(tour + 2 * i);
  118.                 int col = *(tour + 2* i + 1);
  119.                 sum += allDistance[row][col];
  120.         }
  121.         return sum;
  122. }
  123. class ACSAnt;
  124. class AntColonySystem
  125. {
  126. private:       
  127.         double info[N][N], visible[N][N];//节点之间的信息素强度,节点之间的能见度
  128. public:       
  129.         AntColonySystem()
  130.         {
  131.         }
  132.         //计算当前节点到下一节点转移的概率
  133.         double Transition(int i, int j);       
  134.         //局部更新规则
  135.         void UpdateLocalPathRule(int i, int j);       
  136.         //初始化
  137.         void InitParameter(double value);       
  138.         //全局信息素更新
  139.         void UpdateGlobalPathRule(int* bestTour, int globalBestLength);
  140. };
  141. //计算当前节点到下一节点转移的概率
  142. double AntColonySystem::Transition(int i, int j)
  143. {
  144.         if (i != j)
  145.         {
  146.                 return (pow(info[i][j],alpha) * pow(visible[i][j], beta));
  147.         }
  148.         else
  149.         {
  150.                 return 0.0;
  151.         }       
  152. }
  153. //局部更新规则
  154. void AntColonySystem::UpdateLocalPathRule(int i, int j)
  155. {
  156.         info[i][j] = (1.0 - alpha1) * info[i][j] + alpha1 * (1.0 / (N * Lnn));
  157.         info[j][i] = info[i][j];
  158. }
  159. //初始化
  160. void AntColonySystem::InitParameter(double value)
  161. {
  162.         //初始化路径上的信息素强度tao0
  163.         for(int i = 0; i < N; i++)
  164.         {
  165.                 for(int j = 0; j < N; j++)
  166.                 {                               
  167.                         info[i][j] = value;
  168.                         info[j][i] = value;
  169.                         if (i != j)
  170.                         {
  171.                                 visible[i][j] = 1.0 / allDistance[i][j];
  172.                                 visible[j][i] = visible[i][j];
  173.                         }
  174.                 }
  175.         }       
  176. }
  177. //全局信息素更新
  178. void AntColonySystem::UpdateGlobalPathRule(int* bestTour, int globalBestLength)
  179. {
  180.         for(int i = 0; i < N; i++)
  181.         {
  182.                 int row = *(bestTour + 2 * i);
  183.                 int col = *(bestTour + 2* i + 1);
  184.                 info[row][col] = (1.0 - rou) * info[row][col] + rou * (1.0 / globalBestLength);
  185.                 info[col][row] =info[row][col];
  186.         }
  187. }
  188. class ACSAnt
  189. {
  190. private:
  191.         AntColonySystem* antColony;
  192. protected:
  193.         int startCity, cururentCity;//初始城市编号,当前城市编号
  194.         int allowed[N];//禁忌表       
  195.         int Tour[N][2];//当前路径
  196.         int currentTourIndex;//当前路径索引,从0开始,存储蚂蚁经过城市的编号
  197. public:       
  198.         ACSAnt(AntColonySystem* acs, int start)
  199.         {
  200.                 antColony = acs;
  201.                 startCity = start;
  202.         }       
  203.         //开始搜索
  204.         int* Search();
  205.         //选择下一节点
  206.         int Choose();
  207.         //移动到下一节点
  208.         void MoveToNextCity(int nextCity);
  209. };
  210. //开始搜索
  211. int* ACSAnt::Search()
  212. {
  213.         cururentCity = startCity;
  214.         int toCity;
  215.         currentTourIndex = 0;
  216.         for(int i  = 0; i < N; i++)
  217.         {
  218.                 allowed[i] = 1;
  219.         }
  220.         allowed[cururentCity] = 0;
  221.         int endCity;
  222.         int count = 0;
  223.         do
  224.         {
  225.                 count++;
  226.                 endCity = cururentCity;
  227.                 toCity = Choose();               
  228.                 if (toCity >= 0)
  229.                 {                       
  230.                         MoveToNextCity(toCity);
  231.                         antColony->UpdateLocalPathRule(endCity, toCity);
  232.                         cururentCity = toCity;
  233.                 }               
  234.         }while(toCity >= 0);
  235.         MoveToNextCity(startCity);
  236.         antColony->UpdateLocalPathRule(endCity, startCity);
  237.         return *Tour;
  238. }
  239. //选择下一节点
  240. int ACSAnt::Choose()
  241. {
  242.         int nextCity = -1;               
  243.         double q = rand()/(double)RAND_MAX;
  244.         //如果 q <= q0,按先验知识,否则则按概率转移,
  245.         if (q <= qzero)
  246.         {
  247.                 double probability = -1.0;//转移到下一节点的概率
  248.                 for(int i = 0; i < N; i++)
  249.                 {
  250.                         //去掉禁忌表中已走过的节点,从剩下节点中选择最大概率的可行节点
  251.                         if (1 == allowed[i])
  252.                         {
  253.                                 double prob = antColony->Transition(cururentCity, i);
  254.                                 if (prob  > probability)
  255.                                 {
  256.                                         nextCity = i;
  257.                                         probability = prob;
  258.                                 }
  259.                         }
  260.                 }
  261.         }
  262.         else
  263.         {
  264.                 //按概率转移                       
  265.                 double p = rand()/(double)RAND_MAX;//生成一个随机数,用来判断落在哪个区间段
  266.                 double sum = 0.0;                       
  267.                 double probability = 0.0;//概率的区间点,p 落在哪个区间段,则该点是转移的方向
  268.                 //计算概率公式的分母的值
  269.                 for(int i = 0; i < N; i++)
  270.                 {
  271.                         if (1 == allowed[i])
  272.                         {
  273.                                 sum += antColony->Transition(cururentCity, i);
  274.                         }
  275.                 }
  276.                 for(int j = 0; j < N; j++)
  277.                 {
  278.                         if (1 == allowed[j] && sum > 0)
  279.                         {
  280.                                 probability += antColony->Transition(cururentCity, j)/sum;
  281.                                 if (probability >= p || (p > 0.9999 && probability > 0.9999))
  282.                                 {
  283.                                         nextCity = j;
  284.                                         break;
  285.                                 }
  286.                         }
  287.                 }       
  288.         }       
  289.         return nextCity;
  290. }
  291. //移动到下一节点
  292. void ACSAnt::MoveToNextCity(int nextCity)
  293. {
  294.         allowed[nextCity]=0;
  295.         Tour[currentTourIndex][0] = cururentCity;
  296.         Tour[currentTourIndex][1] = nextCity;
  297.         currentTourIndex++;
  298.         cururentCity = nextCity;
  299. }
  300. //------------------------------------------
  301. //选择下一个节点,配合下面的函数来计算的长度
  302. int ChooseNextNode(int currentNode, int visitedNode[])
  303. {
  304.         int nextNode = -1;               
  305.         double shortDistance = 0.0;
  306.         for(int i = 0; i < N; i++)
  307.         {
  308.                 //去掉已走过的节点,从剩下节点中选择距离最近的节点
  309.                 if (1 == visitedNode[i])
  310.                 {                       
  311.                         if (shortDistance == 0.0)
  312.                         {
  313.                                 shortDistance = allDistance[currentNode][i];
  314.                                 nextNode = i;
  315.                         }
  316.                         if(shortDistance < allDistance[currentNode][i])
  317.                         {
  318.                                 nextNode = i;
  319.                         }
  320.                 }
  321.         }
  322.         return nextNode;
  323. }
  324. //给一个节点由最近邻距离方法计算长度
  325. double CalAdjacentDistance(int node)
  326. {
  327.         double sum = 0.0;
  328.         int visitedNode[N];
  329.         for(int j = 0; j < N; j++)
  330.         {
  331.                 visitedNode[j] = 1;
  332.         }
  333.         visitedNode[node] = 0;
  334.         int currentNode = node;
  335.         int nextNode;
  336.         do
  337.         {
  338.                 nextNode = ChooseNextNode(currentNode, visitedNode);
  339.                 if (nextNode >= 0)
  340.                 {
  341.                         sum += allDistance[currentNode][nextNode];
  342.                         currentNode= nextNode;
  343.                         visitedNode[currentNode] = 0;
  344.                 }               
  345.         }while(nextNode >= 0);
  346.         sum += allDistance[currentNode][node];
  347.         return sum;
  348. }
  349. //---------------------------------结束---------------------------------------------
  350. //--------------------------主函数--------------------------------------------------
  351. int main()
  352. {
  353.         time_t timer,timerl;
  354.         time(&timer);
  355.         unsigned long seed = timer;
  356.         seed %= 56000;
  357.         srand((unsigned int)seed);
  358.         //由矩阵表示两两城市之间的距离
  359.         calculateAllDistance();
  360.         //蚁群系统对象
  361.         AntColonySystem* acs = new AntColonySystem();
  362.         ACSAnt* ants[M];
  363.         //蚂蚁均匀分布在城市上
  364.         for(int k = 0; k < M; k++)
  365.         {
  366.                 ants[k] = new ACSAnt(acs, (int)(k%N));
  367.         }
  368.         calculateAllDistance();
  369.         //随机选择一个节点计算由最近邻方法得到的一个长度
  370.         int node = rand() % N;
  371.         Lnn = CalAdjacentDistance(node);
  372.        
  373.         //各条路径上初始化的信息素强度
  374.         double initInfo = 1 / (N * Lnn);
  375.         acs->InitParameter(initInfo);       
  376.        
  377.         //全局最优路径
  378.         int globalTour[N][2];
  379.         //全局最优长度
  380.         double globalBestLength = 0.0;       
  381.         for(int i = 0; i < NcMax; i++)
  382.         {
  383.                 //局部最优路径
  384.                 int localTour[N][2];
  385.                 //局部最优长度
  386.                 double localBestLength = 0.0;
  387.                 //当前路径长度
  388.                 double tourLength;
  389.                 for(int j = 0; j < M; j++)
  390.                 {
  391.                         int* tourPath = ants[j]->Search();
  392.                         tourLength = calculateSumOfDistance(tourPath);                               
  393.                         //局部比较,并记录路径和长度
  394.                         if(tourLength < localBestLength || abs(localBestLength - 0.0) < 0.000001)
  395.                         {                               
  396.                                 for(int m = 0; m< N; m++)
  397.                                 {
  398.                                         int row = *(tourPath + 2 * m);
  399.                                         int col = *(tourPath + 2* m + 1);
  400.                                         localTour[m][0] = row;
  401.                                         localTour[m][1] = col;
  402.                                 }
  403.                                 localBestLength = tourLength;                       
  404.                         }
  405.                 }
  406.                 //全局比较,并记录路径和长度
  407.                 if(localBestLength < globalBestLength || abs(globalBestLength - 0.0) < 0.000001)
  408.                 {                               
  409.                         for(int m = 0; m< N; m++)
  410.                         {
  411.                                 globalTour[m][0] = localTour[m][0];
  412.                                 globalTour[m][1] = localTour[m][1];
  413.                         }
  414.                         globalBestLength = localBestLength;       
  415.                 }
  416.                 acs->UpdateGlobalPathRule(*globalTour, globalBestLength);
  417.                 //输出所有蚂蚁循环一次后的迭代最优路径
  418.                 cout<<"第 "<<i + 1<<" 迭代最优路径:"<<localBestLength<<"."<<endl;
  419.                 for(int m = 0; m< N; m++)
  420.                 {
  421.                         cout<<localTour[m][0]<<".";
  422.                 }
  423.                 cout<<endl;               
  424.         }       
  425.         //输出全局最优路径
  426.         cout<<"全局最优路径长度:"<<globalBestLength<<endl;       
  427.         cout<<"全局最优路径:";
  428.         for(int m = 0; m< N; m++)
  429.         {
  430.                 cout<<globalTour[m][0]<<".";
  431.         }
  432.         cout<<endl;
  433.         time(&timerl);
  434.         int t = timerl - timer;
  435.         return 0;
  436. }
  437. //--------------------------主函数结束--------------------------------------------------
复制代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2024-12-27 21:41 , Processed in 0.145543 second(s), 19 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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