奇葩方法,看着挺酷的,忍不住轉載。。
HTML5提供了Canvas對象,爲繪圖應用提供了便利.
Javascript可運行於瀏覽器中, 而不需要安裝特定的編譯器;
基於HTML5和Javascript語言, 可隨時編寫應用, 爲算法測試帶來便利.
針對TSP問題, 編寫了Ant colony algorithm, 用於演示該算法, tsp_ant_colony_algorithm.html代碼如下:
http://blog.csdn.net/miscclp/article/details/41169837 原文鏈接
- <html>
- <head>
- <meta charset = "utf-8" / >
- <title>TSP_demo</title>
- </head>
- <body>
- <div id="outText">
- </div>
- <canvas id="canvas" height="550px" width="1024px">
- </canvas>
- <script type="text/javascript">
- //計時開始
- t1 = new Date(); //創建"then"這個日期/時間對像
- t1.setTime(t1.getTime()); //爲這個對象賦值
- var canvas = document.getElementById("canvas");
- var canvasWidth = canvas.width;
- var canvasHeight = canvas.height;
- var context = canvas.getContext("2d");
- var N = 30; //城市數量
- var M = 120; //螞蟻數量
- var inittao = 1; //初始路徑激素量
- var tao; //[N][N]; //N*N矩陣——表示i和j間殘留的激素信息量, 初始化爲常熟C(各路徑相等),以表示激素的揮發
- var yita; //[N][N]; //N*N矩陣——表示i和j間由舉例所決定的選擇概率矩陣
- var delta_tao; //[N][N]; //一輪循環後增加的信息素
- var distant; //[N][N]; //所有城市間的距離
- var tabu; //[M][N]; //禁忌表
- var route; //[M][N]; //M只螞蟻所走過的路徑
- var solution; //[M]; //對M只螞蟻所走過路徑的適應度評價值
- var BestRoute; //[N]; //最忌路徑
- var BestSolution = 10000000000; //設置的極限最大路徑
- var alfa, beta, rou, Q; //路徑激素更新數量
- var NcMax; //蟻羣最大迭代次數
- function initMat(M, N, val) {
- var x = new Array();
- for(var i = 0; i < M; i++) {
- x[i] = new Array();
- for(var j = 0; j < N; j++)
- x[i].push(val);
- }
- return x;
- }
- function initAllMats() {
- tao = initMat(N, N, 0);
- yita = initMat(N, N, 0);
- delta_tao = initMat(N, N, 0);
- distant = initMat(N, N, 0);
- tabu = initMat(M, N, 0);
- route = initMat(M, N, -1);
- solution = new Array();
- for(var i = 0; i < M; i++)
- solution[i] = 0;
- BestRoute = new Array();
- for(var i = 0; i < N; i++)
- BestRoute[i] = -1;
- }
- //初始化城市的位置
- function InCityXY(x, y)
- {
- for(var i = 0; i < N; i++) {
- x[i] = (Math.random() * 32767) % 980 + 20;
- y[i] = (Math.random() * 32767) % 420 + 20;
- }
- }
- //初始化算法參數
- function initparameter()
- {
- alfa = 1; //積累的激素調節因子作用係數
- beta = 5; //啓發性調節因子作用係數
- rou = 0.9;
- Q = 100; //常量
- NcMax = 200; //羣螞蟻進化代數
- }
- //取得某個路徑的長度
- function EvalueSolution(a)
- {
- var dist = 0;
- for(var i = 0; i < N-1; i++)
- dist += distant[a[i]][a[i+1]];
- dist += distant[a[N-1]][a[0]];
- return dist;
- }
- function drawCities(x, y) {
- for(var i = 0; i < N; i++) {
- context.beginPath();
- context.fillStyle = "blue";
- context.strokeStyle = "blue";
- context.lineWidth = 1;
- context.font = "normal 16px Arial";
- context.arc(x[i], y[i], 3, (Math.PI / 180) * 0, (Math.PI / 180) * 360, false);
- context.fill();
- context.stroke();
- context.closePath();
- /*
- context.fillStyle = "white";
- context.textAlign = "center";
- context.textBaseline = "middle";
- context.fillText(String(i), x[i], y[i]);
- */
- }
- }
- function drawPath(x1, y1, x2, y2, color, width) {
- context.beginPath();
- context.fillStyle = color;
- context.strokeStyle = color;
- context.lineWidth = width;
- context.moveTo(x1, y1);
- context.lineTo(x2, y2);
- context.stroke();
- }
- //主函數
- function ACA_TSP() {
- var NC = 0;
- //初始化算法參數
- initparameter();
- //初始化城市的位置
- var x = new Array();
- var y = new Array();
- for(var i = 0; i < N; i++) {
- x.push(0);
- y.push(0);
- }
- //初始化城市位置
- InCityXY( x, y );
- //計算任意兩城市間的距離
- for(var i=0;i<N;i++)
- for(var j=i+1;j<N;j++)
- {
- distant[j][i] = Math.sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
- distant[i][j] = distant[j][i];
- }
- // calculate the heuristic parameters
- var i, j, k;
- //初始化任意兩點間的選擇可能性程度=1-p
- //若i==j,則p=1
- //否則,p=100/distant[i][j]
- for(i=0;i<N;i++)
- for(j=0;j<N;j++)
- {
- tao[i][j] = inittao;
- if(j != i)
- yita[i][j] = 100/distant[i][j]; //值越大,i到j被選擇的路徑概率越大; 或者說,i和j距離越近,被選擇的概率越大
- }
- //初始化M個螞蟻走完所有城市(N)的路徑
- //-1表示第k只螞蟻尚沒有從當前位置走向i城市
- /*
- for(k=0;k<M;k++)
- for(i=0;i<N;i++)
- route[k][i] =- 1;
- */
- //初始化所有螞蟻的禁忌表
- for(k=0;k<M;k++)
- {
- route[k][0] = k % N; //隨機置放螞蟻的第一站城市點---此代碼實際上沒有隨機擺放
- tabu[k][route[k][0]] = 1; //設置禁忌表的已訪問過的城市爲1
- }
- //所有螞蟻行走NcMax趟
- do {
- var s = 1;
- var partsum;
- var pper;
- var drand;
- //s循環N次,讓每隻螞蟻走N步,走完全程
- while( s < N)
- {
- for(k=0;k<M;k++)
- {
- var jrand= (Math.random() * 32767) % 3000;
- drand= jrand / 3001.0;
- partsum = 0;
- pper = 0;
- for(j=0;j<N;j++)
- {
- if(tabu[k][j]==0)
- partsum += Math.pow(tao[route[k][s-1]][j],alfa) * Math.pow(yita[route[k][s-1]][j],beta);
- }
- for(j=0;j<N;j++)
- {
- if(tabu[k][j]==0)
- pper += Math.pow(tao[route[k][s-1]][j],alfa) * Math.pow(yita[route[k][s-1]][j],beta)/partsum;
- if(pper > drand)
- break;
- }
- tabu[k][j]=1;
- route[k][s]=j;
- }
- s++;
- }
- // the pheromone is updated
- for(i=0;i<N;i++)
- for(var j=0;j<N;j++)
- delta_tao[i][j]=0;
- //記錄最短路徑及其長度
- for(k=0;k<M;k++)
- {
- solution[k] = EvalueSolution(route[k]);
- if(solution[k] < BestSolution)
- {
- BestSolution = solution[k];
- for(s=0; s<N; s++)
- BestRoute[s]=route[k][s];
- }
- }
- //根據上一批次(M個螞蟻)所求路徑的長度信息,更新從i到j的選擇概率
- for(k=0;k<M;k++)
- {
- for(s=0;s<N-1;s++)
- delta_tao[route[k][s]][route[k][s+1]] += Q/solution[k];
- delta_tao[route[k][N-1]][route[k][0]] += Q/solution[k];
- }
- //計算NxN個節點間的轉移概率,並設置最大與最小值
- for(i=0;i<N;i++)
- for(var j=0;j<N;j++)
- {
- tao[i][j]=rou*tao[i][j]+delta_tao[i][j];
- if(tao[i][j] < 0.00001)
- tao[i][j] = 0.00001;
- if(tao[i][j] > 20)
- tao[i][j] = 20;
- }
- //重新設置所有螞蟻的禁忌表和路徑信息
- for(k=0;k<M;k++)
- for(var j=1;j<N;j++)
- {
- tabu[k][route[k][j]]=0;
- route[k][j]=-1;
- }
- NC++;
- } while(NC < NcMax);
- //output the calculating outs
- /*
- print("*針對旅行商問題的螞蟻克隆算法*");
- print("初始參數:");
- print("alfa=" + alfa + ", beta=" + beta + ", rou=" + rou + ", Q=" + Q);
- print("蟻羣探索循環次數:" + NcMax);
- print("最短路徑是:" + BestSolution);
- print("最佳路徑是:");
- */
- for(i = 0; i < N; i++) {
- if (i == N - 1)
- j = 0;
- else
- j = i + 1;
- var nodeA = BestRoute[i];
- var nodeB = BestRoute[j];
- var x1 = x[nodeA];
- var y1 = y[nodeA];
- var x2 = x[nodeB];
- var y2 = y[nodeB];
- drawPath(x1, y1, x2, y2, "black", 2);
- }
- drawCities(x, y);
- var out = document.getElementById("outText");
- out.innerHTML = "<h1>螞蟻克隆算法求解旅行商問題: </h1>最佳路徑:<br/>";
- for(i=0;i<N;i++)
- out.innerHTML = out.innerHTML + String(BestRoute[i]) + " ";
- out.innerHTML = out.innerHTML + "<br/>最短路徑長度:<br/>" + BestSolution;
- }
- //調用上述函數
- initAllMats();
- ACA_TSP();
- //結束後,取得現在時間, 並計算時間差
- t2 = new Date(); //創建"then"這個日期/時間對像
- var ms = t2.getTime() - t1.getTime();
- var out = document.getElementById("outText");
- out.innerHTML = out.innerHTML + "<br/>用時(毫秒):<br/>" + ms;
- </script>
- </body>
- </html>
刷新該頁面, 可隨機產生不同的城市點, 並計算最短路徑.
實例效果如下:
需要說明的是, 算法仍需改善, 在有些其情況下,無法保障總能獲得最短路徑.