FPGA机器学习之蚁群算法的源代码C++

不知道现在是否还有人在研究蚁群算法?应该有吧。当初为了找C或C++源代码而不可得,在阅读了多份”杂七杂八”的代码的基础,总算写出来了。运行了三个TSP经典用例,基本符合要求。2008年3月份写的,现在贴出来大家共享一下,注释加的应该算齐全。仅仅是一份按照蚁群算法的原理写的代码,没有做任何优化。至于我做优化后的代码,就不发出来了吧,呵呵。环境为:Windows XP SP2 + VC 6.0.

 

[cpp]
view plain
copy
print
?

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