利用HTML5 Canvas和Javascript實現的蟻羣算法求解TSP問題演示

奇葩方法,看着挺酷的,忍不住轉載。。

HTML5提供了Canvas對象,爲繪圖應用提供了便利.

Javascript可運行於瀏覽器中, 而不需要安裝特定的編譯器;

基於HTML5和Javascript語言, 可隨時編寫應用, 爲算法測試帶來便利.

針對TSP問題, 編寫了Ant colony algorithm, 用於演示該算法, tsp_ant_colony_algorithm.html代碼如下:

http://blog.csdn.net/miscclp/article/details/41169837 原文鏈接

[html] view plaincopy
  1. <html>  
  2. <head>  
  3.  <meta charset = "utf-8" / >   
  4. <title>TSP_demo</title>  
  5. </head>  
  6. <body>  
  7. <div id="outText">  
  8. </div>  
  9. <canvas id="canvas" height="550px" width="1024px">  
  10. </canvas>  
  11. <script type="text/javascript">  
  12. //計時開始  
  13. t1 = new Date();            //創建"then"這個日期/時間對像  
  14. t1.setTime(t1.getTime());   //爲這個對象賦值  
  15.   
  16. var canvas = document.getElementById("canvas");  
  17. var canvasWidth = canvas.width;  
  18. var canvasHeight = canvas.height;  
  19. var context = canvas.getContext("2d");  
  20.   
  21. var N = 30;   //城市數量  
  22. var M = 120;   //螞蟻數量  
  23.   
  24. var inittao = 1;   //初始路徑激素量   
  25. var tao;   //[N][N];     //N*N矩陣——表示i和j間殘留的激素信息量, 初始化爲常熟C(各路徑相等),以表示激素的揮發  
  26. var yita; //[N][N];      //N*N矩陣——表示i和j間由舉例所決定的選擇概率矩陣  
  27. var delta_tao; //[N][N]; //一輪循環後增加的信息素  
  28. var distant; //[N][N];   //所有城市間的距離  
  29. var tabu; //[M][N];         //禁忌表  
  30. var route; //[M][N];        //M只螞蟻所走過的路徑  
  31. var solution; //[M];     //對M只螞蟻所走過路徑的適應度評價值  
  32. var BestRoute; //[N];       //最忌路徑  
  33. var BestSolution = 10000000000;   //設置的極限最大路徑  
  34. var alfa, beta, rou, Q;        //路徑激素更新數量  
  35. var NcMax;                        //蟻羣最大迭代次數  
  36.   
  37. function initMat(M, N, val) {  
  38.   var x = new Array();  
  39.   for(var i = 0; i < M; i++) {  
  40.     x[i] = new Array();  
  41.     for(var j = 0; j < N; j++)  
  42.         x[i].push(val);  
  43.   }  
  44.   return x;  
  45. }  
  46.   
  47. function initAllMats() {  
  48.     tao = initMat(N, N, 0);  
  49.     yita = initMat(N, N, 0);  
  50.     delta_tao = initMat(N, N, 0);  
  51.     distant = initMat(N, N, 0);  
  52.     tabu = initMat(M, N, 0);  
  53.     route = initMat(M, N, -1);  
  54.       
  55.     solution = new Array();  
  56.     for(var i = 0; i < M; i++)  
  57.         solution[i] = 0;  
  58.           
  59.     BestRoute = new Array();  
  60.     for(var i = 0; i < N; i++)  
  61.         BestRoute[i] = -1;  
  62. }  
  63.   
  64. //初始化城市的位置  
  65. function InCityXY(x, y)  
  66. {   
  67.     for(var i = 0; i < N; i++) {  
  68.         x[i] = (Math.random() * 32767) % 980 + 20;  
  69.         y[i] = (Math.random() * 32767) % 420 + 20;  
  70.     }  
  71. }  
  72.   
  73. //初始化算法參數  
  74. function initparameter()   
  75. {   
  76.     alfa = 1;   //積累的激素調節因子作用係數  
  77.     beta = 5;   //啓發性調節因子作用係數  
  78.     rou = 0.9;    
  79.     Q = 100;    //常量  
  80.     NcMax = 200; //羣螞蟻進化代數  
  81. }   
  82.   
  83. //取得某個路徑的長度  
  84. function EvalueSolution(a)   
  85. {   
  86.     var dist = 0;   
  87.     for(var i = 0; i < N-1; i++)  
  88.         dist += distant[a[i]][a[i+1]];   
  89.     dist += distant[a[N-1]][a[0]];   
  90.     return dist;   
  91. }   
  92.   
  93. function drawCities(x, y) {  
  94.     for(var i = 0; i < N; i++) {  
  95.         context.beginPath();  
  96.   
  97.         context.fillStyle = "blue";  
  98.         context.strokeStyle = "blue";  
  99.         context.lineWidth = 1;  
  100.         context.font = "normal 16px Arial";  
  101.   
  102.         context.arc(x[i], y[i], 3, (Math.PI / 180) * 0, (Math.PI / 180) * 360, false);  
  103.         context.fill();  
  104.         context.stroke();  
  105.         context.closePath();  
  106. /*  
  107.         context.fillStyle = "white";  
  108.         context.textAlign = "center";  
  109.         context.textBaseline = "middle";  
  110.         context.fillText(String(i), x[i], y[i]);  
  111. */  
  112.     }  
  113. }  
  114.       
  115. function drawPath(x1, y1, x2, y2, color, width) {  
  116.     context.beginPath();  
  117.     context.fillStyle = color;  
  118.     context.strokeStyle = color;  
  119.     context.lineWidth = width;  
  120.     context.moveTo(x1, y1);  
  121.     context.lineTo(x2, y2);  
  122.     context.stroke();  
  123. }  
  124.   
  125. //主函數  
  126. function ACA_TSP() {  
  127.     var NC = 0;   
  128.     //初始化算法參數  
  129.     initparameter();   
  130.       
  131.     //初始化城市的位置  
  132.     var x = new Array();  
  133.     var y = new Array();  
  134.     for(var i = 0; i < N; i++) {  
  135.         x.push(0);  
  136.         y.push(0);  
  137.     }  
  138.     //初始化城市位置  
  139.     InCityXY( x, y );   
  140.   
  141.     //計算任意兩城市間的距離  
  142.     for(var i=0;i<N;i++)   
  143.         for(var j=i+1;j<N;j++)   
  144.         {   
  145.             distant[j][i] = Math.sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));   
  146.             distant[i][j] = distant[j][i];   
  147.         }   
  148.     // calculate the heuristic parameters   
  149.     var i, j, k;  
  150.     //初始化任意兩點間的選擇可能性程度=1-p  
  151.     //若i==j,則p=1  
  152.     //否則,p=100/distant[i][j]  
  153.     for(i=0;i<N;i++)   
  154.         for(j=0;j<N;j++)   
  155.         {   
  156.             tao[i][j] = inittao;   
  157.             if(j != i)   
  158.                 yita[i][j] = 100/distant[i][j];    //值越大,i到j被選擇的路徑概率越大; 或者說,i和j距離越近,被選擇的概率越大  
  159.         }   
  160.     //初始化M個螞蟻走完所有城市(N)的路徑  
  161.     //-1表示第k只螞蟻尚沒有從當前位置走向i城市  
  162.     /*  
  163.     for(k=0;k<M;k++)   
  164.         for(i=0;i<N;i++)   
  165.             route[k][i] =- 1;   
  166.     */  
  167.     //初始化所有螞蟻的禁忌表  
  168.     for(k=0;k<M;k++)   
  169.     {   
  170.         route[k][0] = k % N;     //隨機置放螞蟻的第一站城市點---此代碼實際上沒有隨機擺放  
  171.         tabu[k][route[k][0]] = 1;  //設置禁忌表的已訪問過的城市爲1  
  172.     }   
  173.     //所有螞蟻行走NcMax趟  
  174.     do {   
  175.         var s = 1;   
  176.         var partsum;   
  177.         var pper;   
  178.         var drand;   
  179.   
  180.         //s循環N次,讓每隻螞蟻走N步,走完全程  
  181.         while( s < N)   
  182.         {   
  183.             for(k=0;k<M;k++)   
  184.             {   
  185.                 var jrand= (Math.random() * 32767) % 3000;   
  186.                 drandjrand / 3001.0;   
  187.                 partsum = 0;   
  188.                 pper = 0;   
  189.                 for(j=0;j<N;j++)   
  190.                 {   
  191.                     if(tabu[k][j]==0)   
  192.                         partsum += Math.pow(tao[route[k][s-1]][j],alfa) * Math.pow(yita[route[k][s-1]][j],beta);   
  193.                 }   
  194.                 for(j=0;j<N;j++)   
  195.                 {   
  196.                     if(tabu[k][j]==0)   
  197.                         pper += Math.pow(tao[route[k][s-1]][j],alfa) * Math.pow(yita[route[k][s-1]][j],beta)/partsum;   
  198.                     if(pper > drand)   
  199.                         break;   
  200.                 }   
  201.                 tabu[k][j]=1;   
  202.                 route[k][s]=j;   
  203.             }   
  204.             s++;   
  205.         }   
  206.         // the pheromone is updated   
  207.         for(i=0;i<N;i++)   
  208.             for(var j=0;j<N;j++)   
  209.                 delta_tao[i][j]=0;   
  210.         //記錄最短路徑及其長度  
  211.         for(k=0;k<M;k++)   
  212.         {   
  213.             solution[k] = EvalueSolution(route[k]);   
  214.             if(solution[k] < BestSolution)   
  215.             {   
  216.                 BestSolution = solution[k];   
  217.                 for(s=0; s<N; s++)   
  218.                     BestRoute[s]=route[k][s];   
  219.             }   
  220.         }   
  221.         //根據上一批次(M個螞蟻)所求路徑的長度信息,更新從i到j的選擇概率  
  222.         for(k=0;k<M;k++)   
  223.         {   
  224.             for(s=0;s<N-1;s++)   
  225.                 delta_tao[route[k][s]][route[k][s+1]] += Q/solution[k];   
  226.             delta_tao[route[k][N-1]][route[k][0]] += Q/solution[k];   
  227.         }   
  228.         //計算NxN個節點間的轉移概率,並設置最大與最小值  
  229.         for(i=0;i<N;i++)   
  230.             for(var j=0;j<N;j++)   
  231.             {   
  232.                 tao[i][j]=rou*tao[i][j]+delta_tao[i][j];   
  233.                 if(tao[i][j] < 0.00001)   
  234.                     tao[i][j] = 0.00001;   
  235.                 if(tao[i][j] > 20)   
  236.                     tao[i][j] = 20;   
  237.             }   
  238.         //重新設置所有螞蟻的禁忌表和路徑信息  
  239.         for(k=0;k<M;k++)   
  240.             for(var j=1;j<N;j++)   
  241.             {   
  242.                 tabu[k][route[k][j]]=0;   
  243.                 route[k][j]=-1;   
  244.             }   
  245.         NC++;   
  246.     } while(NC < NcMax);   
  247.     //output the calculating outs   
  248.     /*  
  249.     print("*針對旅行商問題的螞蟻克隆算法*");   
  250.     print("初始參數:");   
  251.     print("alfa=" + alfa + "beta=" + beta + "rou=" + rou + "Q=" + Q);   
  252.     print("蟻羣探索循環次數:" + NcMax);  
  253.     print("最短路徑是:" + BestSolution);  
  254.     print("最佳路徑是:");   
  255.     */  
  256.     for(i = 0; i < N; i++) {  
  257.         if (i == N - 1)  
  258.             j = 0;  
  259.         else  
  260.             j = i + 1;  
  261.         var nodeA = BestRoute[i];  
  262.         var nodeB = BestRoute[j];  
  263.         var x1 = x[nodeA];  
  264.         var y1 = y[nodeA];  
  265.         var x2 = x[nodeB];  
  266.         var y2 = y[nodeB];  
  267.         drawPath(x1, y1, x2, y2, "black", 2);  
  268.     }  
  269.     drawCities(x, y);  
  270.       
  271.       
  272.     var out = document.getElementById("outText");  
  273.     out.innerHTML = "<h1>螞蟻克隆算法求解旅行商問題: </h1>最佳路徑:<br/>";  
  274.     for(i=0;i<N;i++)   
  275.         out.innerHTML = out.innerHTML + String(BestRoute[i]) + " ";  
  276.     out.innerHTML = out.innerHTML + "<br/>最短路徑長度:<br/>" + BestSolution;  
  277. }  
  278.   
  279. //調用上述函數  
  280. initAllMats();  
  281. ACA_TSP();  
  282.   
  283. //結束後,取得現在時間, 並計算時間差  
  284. t2 = new Date();            //創建"then"這個日期/時間對像  
  285. var ms = t2.getTime() - t1.getTime();  
  286. var out = document.getElementById("outText");  
  287. out.innerHTML = out.innerHTML + "<br/>用時(毫秒):<br/>" + ms;  
  288. </script>  
  289. </body>  
  290. </html>  

刷新該頁面, 可隨機產生不同的城市點, 並計算最短路徑.

實例效果如下:


需要說明的是, 算法仍需改善, 在有些其情況下,無法保障總能獲得最短路徑.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章