tsp 分支界限 java_干货 | 10分钟教你用branch and bound(分支定界)算法求解TSP旅行商问题...
在此之前,先給大家講講最重要的一個點,搜索樹的節點定義,節點定義了原問題的solution和子問題的solution。Node節點定義如下:
public class Node {private ArrayList path;private double bound;private int level;public double computeLength(double[][] distanceMatrix) {// TODO Auto-generated method stubdouble distance = 0;for(int i=0;i
其余不重要的接口略過。如下:
- path:保存該節點目前已經走過的城市序列。
- bound:記錄該節點目前所能達到的最低distance。
- level:記錄節點處于搜索樹的第幾層。
- computeLength:記錄當前城市序列的distance。
可能大家還沒理解節點是如何分支的,看一張圖大家就懂了。我們知道TSP問題的一個solution是能用一個序列表示城市的先后訪問順序,比如現在有4座城市(1,2,3,4):
圖中每個節點的數字序列就是path保存的。大家都看到了吧,其實分支就是一個窮枚舉的過程。
相對于窮舉,分支定界算法的優越之處就在于其加入了定界過程,在分支的過程中就砍掉了某些不可能的支,減少了枚舉的次數,大大提高了算法的效率。如下:
分支定界算法的主過程如下:
private static void solveTSP(double[][] distanceMatrix) {int totalCities = distanceMatrix.length;ArrayList cities = new ArrayList();for (int i = 0; i < totalCities; i++) {cities.add(i);}ArrayList path;double initB = initbound(totalCities, distanceMatrix);Node v = new Node(new ArrayList<>(), 0, initB, 0);queue.add(v);queueCount++;while (!queue.isEmpty()) {v = queue.remove();if (v.getBound() < shortestDistance) {Node u = new Node();u.setLevel(v.getLevel() + 1);for (int i = 1; i < totalCities; i++) {path = v.getPath();if (!path.contains(i)) {u.setPath(v.getPath());path = u.getPath();path.add(i);u.setPath(path);if (u.getLevel() == totalCities - 2) {// put index of only vertex not in u.path at the end// of u.pathfor (int j = 1; j < cities.size(); j++) {if (!u.getPath().contains(j)) {ArrayList temp = new ArrayList<>();temp = u.getPath();temp.add(j);u.setPath(temp);}}path = u.getPath();path.add(0);u.setPath(path);if (u.computeLength(distanceMatrix) < shortestDistance) {shortestDistance = u.computeLength(distanceMatrix);// implementshortestPath = u.getPath();}} else {u.setBound(computeBound(u, distanceMatrix, cities));//u.getBound()獲得的是不完整的解,如果一個不完整的解bound都大于當前最優解,那么完整的解肯定會更大,那就沒法玩了。//所以這里只要u.getBound() < shortestDistance的分支if (u.getBound() < shortestDistance) {queue.add(u);queueCount++;}else {System.out.println("currentBest = "+shortestDistance+" cut bound >>> "+u.getBound());}}}}}}}
1. 首先initbound利用貪心的方式獲得一個bound,作為初始解。
2. 而后利用優先隊列遍歷搜索樹,進行branch and bound算法。對于隊列里面的任意一個節點,只有(v.getBound() < shortestDistance)條件成立我們才有分支的必要。不然將該支砍掉。
3. 分支以后判斷該支是否到達最底層,這樣意味著我們獲得了一個完整的解。那么此時就可以更新當前的最優解了。
4. 如果沒有到達最底層,則對該支進行定界操作。如果該支的bound也比當前最優解還要大,那么也要砍掉的,就像林志炫的單身情歌里面唱的一樣:每一個單身狗都得砍頭。
然后講講定界過程,TSP問題是如何定界的呢?
private static double computeBound(Node u, double[][] distanceMatrix, ArrayList cities) {double bound = 0;ArrayList path = u.getPath();for (int i = 0; i < path.size() - 1; i++) {bound = bound + distanceMatrix[path.get(i)][path.get(i + 1)];}int last = path.get(path.size() - 1);List subPath1 = path.subList(1, path.size());double min;//回來的for (int i = 0; i < cities.size(); i++) {min = Integer.MAX_VALUE;if (!path.contains(cities.get(i))) {for (int j = 0; j < cities.size(); j++) {if (i != j && !subPath1.contains(cities.get(j))) {if (min > distanceMatrix[i][j]) {min = distanceMatrix[i][j];}}}}if (min != Integer.MAX_VALUE)bound = bound + min;}//出去的min = Integer.MAX_VALUE;for (int i = 0; i < cities.size(); i++) {if (/*cities.get(i) != last && */!path.contains(i) && min > distanceMatrix[last][i]) {min = distanceMatrix[last][i];}}bound = bound + min;//System.out.println("bound = "+bound);return bound;}
我們知道,每個節點保存的城市序列可能不是完整的解。bound的計算方式:bound = 當前節點path序列的路徑距離 + 訪問下一個城市的最短路徑距離 + 從下一個城市到下下城市(有可能是起點)的最短路徑距離。
比如城市節點5個{1,2,3,4,5}。當前path = {1,2},那么:
- 當前節點path序列的路徑距離 =d12
- 訪問下一個城市的最短路徑距離 =min (d2i), i in {3,4,5}
- 從下一個城市到下下城市(有可能是起點)的最短路徑距離=min (dij), i in {3,4,5} , j in {3,4,5,1}, i != j 。
注意這兩個是可以不相等的。
總結
以上是生活随笔為你收集整理的tsp 分支界限 java_干货 | 10分钟教你用branch and bound(分支定界)算法求解TSP旅行商问题...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java json的使用方法_JAVA编
- 下一篇: java实现多对多关系的方法_java