TSP問題及蟻群演算法理解與實現
阿新 • • 發佈:2019-02-17
/** * Created by coco on 17-10-20. */ import java.io.*; import java.util.logging.Logger; import static java.util.logging.Logger.getLogger; public class ACO { private Ant[] ants; // 螞蟻 private int antNum; // 螞蟻數量 private int cityNum; // 城市數量 private int MAX_GEN; // 執行代數 private float[][] pheromone; // 資訊素矩陣 private int[][] distance; // 距離矩陣 private int bestLength; // 最佳長度 private int[] bestTour; // 最佳路徑 // 三個引數 private float alpha; private float beta; private float rho; public ACO() { } /** * constructor of ACO * * @param n * 城市數量 * @param m * 螞蟻數量 * @param g * 執行代數 * @param a * alpha * @param b * beta * @param r * rho * **/ public ACO(int n, int m, int g, float a, float b, float r) { cityNum = n; antNum = m; ants = new Ant[antNum]; MAX_GEN = g; alpha = a; beta = b; rho = r; } /** * 初始化ACO演算法類 * @param filename 資料檔名,該檔案儲存所有城市節點座標資料 * @throws IOException */ private void init(String filename,int firstCity,int lastCity) throws IOException { // 讀取資料 int[] x; int[] y; String strbuff; BufferedReader data = new BufferedReader(new InputStreamReader( new FileInputStream(filename))); distance = new int[cityNum][cityNum]; x = new int[cityNum]; y = new int[cityNum]; for (int i = 0; i < cityNum; i++) { // 讀取一行資料,資料格式1 6734 1453 strbuff = data.readLine(); // 字元分割 String[] strcol = strbuff.split(" "); x[i] = Integer.valueOf(strcol[0]);// x座標 y[i] = Integer.valueOf(strcol[1]);// y座標 } // 計算距離矩陣 // 針對具體問題,距離計算方法也不一樣,此處用的是att48作為案例,它有48個城市,距離計算方法為偽歐氏距離,最優值為10628 for (int i = 0; i < cityNum - 1; i++) { distance[i][i] = 0; // 對角線為0 for (int j = i + 1; j < cityNum; j++) { double rij = Math .sqrt(((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j])) / 10.0); // 四捨五入,取整 int tij = (int) Math.round(rij); if (tij < rij) { distance[i][j] = tij + 1; distance[j][i] = distance[i][j]; } else { distance[i][j] = tij; distance[j][i] = distance[i][j]; } } } distance[cityNum - 1][cityNum - 1] = 0; // 初始化資訊素矩陣 pheromone = new float[cityNum][cityNum]; for (int i = 0; i < cityNum; i++) { for (int j = 0; j < cityNum; j++) { pheromone[i][j] = 0.1f; // 初始化為0.1 } } bestLength = Integer.MAX_VALUE; bestTour = new int[cityNum + 1]; // 隨機放置螞蟻 for (int i = 0; i < antNum; i++) { ants[i] = new Ant(cityNum); ants[i].init(distance, alpha, beta,firstCity,lastCity); } } public void solve() { // 迭代MAX_GEN次 for (int g = 0; g < MAX_GEN; g++) { // if(g%100 == 0) // System.out.println("正在進行第 "+g+" 次迭代……"); // antNum只螞蟻 for (int i = 0; i < antNum; i++) { // i這隻螞蟻走cityNum步,完整一個TSP for (int j = 1; j < cityNum; j++) { ants[i].selectNextCity(pheromone); } // 把這隻螞蟻起始城市加入其禁忌表中 // 禁忌表最終形式:起始城市,城市1,城市2...城市n,終點城市 // 檢視這隻螞蟻行走路徑距離是否比當前距離優秀 if (ants[i].getTourLength() < bestLength) { // 比當前優秀則拷貝優秀TSP路徑 bestLength = ants[i].getTourLength(); for (int k = 0; k < ants[i].getTabu().size() ; k++) { bestTour[k] = ants[i].getTabu().get(k).intValue(); } } // 更新這隻螞蟻的資訊數變化矩陣,對稱矩陣 for (int j = 0; j < ants[i].getTabu().size() - 1; j++) { ants[i].getDelta()[ants[i].getTabu().get(j).intValue()][ants[i] .getTabu().get(j + 1).intValue()] = (float) (1. / ants[i] .getTourLength()); ants[i].getDelta()[ants[i].getTabu().get(j + 1).intValue()][ants[i] .getTabu().get(j).intValue()] = (float) (1. / ants[i] .getTourLength()); } } // 更新資訊素 updatePheromone(); for (int i = 0; i < antNum; i++) { ants[i].init(distance, alpha, beta,ants[i].getFirstCity(),ants[i].getLastCity()); } } // 列印最佳結果 writeToFile(); System.out.flush(); } // 更新資訊素 private void updatePheromone() { // 資訊素揮發 for (int i = 0; i < cityNum; i++) for (int j = 0; j < cityNum; j++) // pheromone[i][j] = pheromone[i][j] * (1 - rho); pheromone[i][j] = pheromone[i][j] * rho ; // 資訊素更新 for (int i = 0; i < cityNum; i++) { for (int j = 0; j < cityNum; j++) { for (int k = 0; k < antNum; k++) { pheromone[i][j] += ants[k].getDelta()[i][j]; } } } } //輸出到檔案 private void writeToFile(){ File of = new File("/home/coco/Downloads/result.txt"); try { FileWriter fw = new FileWriter(of,true); fw.append("The optimal length is: " + bestLength + "\r\n"); fw.append("The optimal tour is:"); for (int i = 0; i < cityNum; i++) { fw.append(bestTour[i] + " "); } fw.append("\r\n"); fw.close(); }catch(Exception e){e.printStackTrace();} } /** * @param args * @throws IOException */ public static void main(String[] args) throws Exception { System.out.println("Start...."); ACO aco = new ACO(48, 100, 300, 1.f, 5.f, 0.5f); for (int i = 0; i < 40; i++) { int firstCity = (int)(Math.random()*48); int lastCity = (int)(Math.random()*48); System.out.println("第"+ i+ "對起點終點\tfirstCity:"+firstCity + "\tlastCity:"+lastCity); System.err.flush(); aco.init("/home/coco/Downloads/data.txt",firstCity,lastCity); aco.solve(); } } }