Ver Fonte

part of travelling salesman

SlightlyObscure há 4 anos atrás
pai
commit
3c0adb17b2

+ 99 - 11
src/pathgame/algorithm/DijkstraMagic.java

@@ -17,7 +17,7 @@ public class DijkstraMagic {
         this.map = map;
 
         //weightMap = new Node2D[map.getWidth()][map.getHeight()];
-        weightMap = new Node2D[5][5];
+        weightMap = new Node2D[5][15];
 
         setup();
 
@@ -25,7 +25,11 @@ public class DijkstraMagic {
             doMagicforTown(i);
         }
 
-        printDijkstraResult();
+        //printDijkstraResult();
+    }
+
+    public ArrayList<ArrayList<SaleRoute>> getSalesPitch() {
+        return salesPitch;
     }
 
     private void doMagicforTown(int fromIndex) {
@@ -60,7 +64,7 @@ public class DijkstraMagic {
 
         makeListForPitch(fromIndex);
 
-        printDijkstraMap();
+        //printDijkstraMap();
     }
 
     private void makeListForPitch(int fromIndex) {
@@ -180,6 +184,26 @@ public class DijkstraMagic {
         towns.add(new Coord(0, 0));
         towns.add(new Coord(2, 3));
         towns.add(new Coord(4, 1));
+        towns.add(new Coord(0, 4));
+        towns.add(new Coord(4, 7));
+        towns.add(new Coord(2, 5));
+        towns.add(new Coord(3, 9));
+        towns.add(new Coord(1, 8));
+        //new test
+        towns.add(new Coord(1, 3));
+        towns.add(new Coord(1, 5));
+        towns.add(new Coord(2, 8));
+        towns.add(new Coord(0, 2));
+        towns.add(new Coord(0, 5));
+        towns.add(new Coord(0, 10));
+        towns.add(new Coord(0, 14));
+        towns.add(new Coord(1, 0));
+        towns.add(new Coord(1, 7));
+        towns.add(new Coord(1, 9));
+        towns.add(new Coord(1, 11));
+        towns.add(new Coord(1, 14));
+
+
 
         weightMap[0][0] = new Node2D(1);
         weightMap[1][0] = new Node2D(5);
@@ -211,6 +235,66 @@ public class DijkstraMagic {
         weightMap[3][4] = new Node2D(5);
         weightMap[4][4] = new Node2D(5);
 
+        weightMap[0][5] = new Node2D(1);
+        weightMap[1][5] = new Node2D(5);
+        weightMap[2][5] = new Node2D(1);
+        weightMap[3][5] = new Node2D(5);
+        weightMap[4][5] = new Node2D(5);
+
+        weightMap[0][6] = new Node2D(1);
+        weightMap[1][6] = new Node2D(10);
+        weightMap[2][6] = new Node2D(1);
+        weightMap[3][6] = new Node2D(5);
+        weightMap[4][6] = new Node2D(1);
+
+        weightMap[0][7] = new Node2D(1);
+        weightMap[1][7] = new Node2D(10);
+        weightMap[2][7] = new Node2D(1);
+        weightMap[3][7] = new Node2D(1);
+        weightMap[4][7] = new Node2D(1);
+
+        weightMap[0][8] = new Node2D(1);
+        weightMap[1][8] = new Node2D(10);
+        weightMap[2][8] = new Node2D(1);
+        weightMap[3][8] = new Node2D(1);
+        weightMap[4][8] = new Node2D(5);
+
+        weightMap[0][9] = new Node2D(1);
+        weightMap[1][9] = new Node2D(1);
+        weightMap[2][9] = new Node2D(1);
+        weightMap[3][9] = new Node2D(5);
+        weightMap[4][9] = new Node2D(5);
+
+        weightMap[0][10] = new Node2D(1);
+        weightMap[1][10] = new Node2D(5);
+        weightMap[2][10] = new Node2D(1);
+        weightMap[3][10] = new Node2D(5);
+        weightMap[4][10] = new Node2D(5);
+
+        weightMap[0][11] = new Node2D(1);
+        weightMap[1][11] = new Node2D(10);
+        weightMap[2][11] = new Node2D(1);
+        weightMap[3][11] = new Node2D(5);
+        weightMap[4][11] = new Node2D(1);
+
+        weightMap[0][12] = new Node2D(1);
+        weightMap[1][12] = new Node2D(10);
+        weightMap[2][12] = new Node2D(1);
+        weightMap[3][12] = new Node2D(1);
+        weightMap[4][12] = new Node2D(1);
+
+        weightMap[0][13] = new Node2D(1);
+        weightMap[1][13] = new Node2D(10);
+        weightMap[2][13] = new Node2D(1);
+        weightMap[3][13] = new Node2D(1);
+        weightMap[4][13] = new Node2D(5);
+
+        weightMap[0][14] = new Node2D(1);
+        weightMap[1][14] = new Node2D(1);
+        weightMap[2][14] = new Node2D(1);
+        weightMap[3][14] = new Node2D(5);
+        weightMap[4][14] = new Node2D(5);
+
         //test end
 
         /*towns.add(new Coord(6, 10));
@@ -257,14 +341,7 @@ public class DijkstraMagic {
             }
         }*/
 
-        for(int y = 0; y < weightMap[0].length; y++) {
-            for(int x = 0; x < weightMap.length; x++) {
-                System.out.print(weightMap[x][y].getWeight() + " ");
-            }
-            System.out.println();
-        }
-
-        System.out.println();
+        //printWeightMap();
     }
 
     private void printDijkstraMap() {
@@ -304,4 +381,15 @@ public class DijkstraMagic {
 
         System.out.println();
     }
+
+    private void printWeightMap() {
+        for(int y = 0; y < weightMap[0].length; y++) {
+            for(int x = 0; x < weightMap.length; x++) {
+                System.out.print(weightMap[x][y].getWeight() + " ");
+            }
+            System.out.println();
+        }
+
+        System.out.println();
+    }
 }

+ 53 - 0
src/pathgame/algorithm/OddDegreeList.java

@@ -0,0 +1,53 @@
+package pathgame.algorithm;
+
+import java.util.ArrayList;
+
+public class OddDegreeList {
+    private ArrayList<Integer> items = new ArrayList<>();
+    private ArrayList<Boolean> itemUsed = new ArrayList<>();
+
+    public void add(int vertex) {
+        items.add(vertex);
+        itemUsed.add(false);
+    }
+
+    public int size() {
+        return items.size();
+    }
+
+    public void resetUsed() {
+        for(int i = 0; i < itemUsed.size(); i++) {
+            itemUsed.set(i, false);
+        }
+    }
+
+    public int getUnused(int offSet) {
+        return items.get(getOffsetPos(offSet));
+    }
+
+    public int makeUsed(int offSet) {
+        int pos = getOffsetPos(offSet);
+        itemUsed.set(pos, true);
+        return pos;
+    }
+
+    public void makeUnused(int pos) {
+        itemUsed.set(pos, false);
+    }
+
+    private int getOffsetPos(int offSet) {
+        int foundValid = 0;
+
+        for (int i = 0; i < items.size(); i++) {
+            if (!itemUsed.get(i)) {
+                if (offSet == foundValid) {
+                    return i;
+                    /*itemUsed.set(i, true);
+                    return items.get(i);*/
+                }
+                foundValid++;
+            }
+        }
+        return -1;
+    }
+}

+ 68 - 0
src/pathgame/algorithm/Permutation.java

@@ -0,0 +1,68 @@
+package pathgame.algorithm;
+
+public class Permutation {
+    private int size;
+    private int[] vals;
+    private int[] minVals;
+    private int minCost = Integer.MAX_VALUE;
+    //public int tempCounter1 = 0;
+    //public int tempCounter2 = 0;
+
+    public Permutation(int listSize) {
+        this.size = (listSize/2) - 1;
+        vals = new int[size];
+    }
+
+    public int getValAtPos (int pos) {
+        return vals[pos];
+    }
+
+    public boolean isPosAtMax (int pos) {
+        if(vals[pos] == getMaxOfPos(pos)) {
+            return true;
+        }
+        return false;
+    }
+
+    private int getMaxOfPos (int pos) {
+        return 2 * (size - pos);
+    }
+
+    public int size() {
+        return size;
+    }
+
+    public void increaseAtPos (int pos) {
+        vals[pos]++;
+        for(int i = pos+1; i < size; i++) {
+            vals[i] = 0;
+        }
+    }
+
+    public int getMinCost() {
+        return minCost;
+    }
+
+    public void setMinCost(int minCost) {
+        this.minCost = minCost;
+        minVals = vals.clone();
+    }
+
+    public void makePermutMinimal() {
+        vals = minVals.clone();
+    }
+
+    public void printPermut() {
+        for(int i = 0; i < size; i++) {
+            System.out.print(vals[i] + " ");
+        }
+        System.out.println();
+    }
+
+    public void printMinPermut() {
+        for(int i = 0; i < size; i++) {
+            System.out.print(minVals[i] + " ");
+        }
+        System.out.println();
+    }
+}

+ 199 - 1
src/pathgame/algorithm/TravellingSalesAlg.java

@@ -2,10 +2,208 @@ package pathgame.algorithm;
 
 import pathgame.tilemap.TileMap;
 
+import java.util.ArrayList;
+import java.util.Collections;
+
 public class TravellingSalesAlg {
     public static int calcSalesPathLen(TileMap map) {
         DijkstraMagic dijkstra = new DijkstraMagic(map);
 
+        ArrayList<ArrayList<SaleRoute>> salesPitch = dijkstra.getSalesPitch();
+
+        //make minimum spanning tree
+        ArrayList<TreeEdge> MSTree = makeMSTree(salesPitch);
+
+        //find pairs-shortest path for verteces with odd degree and add those edges to MSTree
+        ArrayList<TreeEdge> oddDegEdges = makeOddDegEdges(MSTree, salesPitch);
+        MSTree.addAll(oddDegEdges);
+
+
         return 10;
     }
-}
+
+    private static ArrayList<TreeEdge> makeOddDegEdges(ArrayList<TreeEdge> msTree, ArrayList<ArrayList<SaleRoute>> salesPitch) {
+        int numOfEdges[] = new int[salesPitch.size()];
+
+        for (int i = 0; i < msTree.size(); i++) {
+            numOfEdges[msTree.get(i).getSrc()]++;
+            numOfEdges[msTree.get(i).getDest()]++;
+        }
+
+        OddDegreeList oddDegs = new OddDegreeList();
+
+        for (int i = 0; i < numOfEdges.length; i++) {
+            //System.out.println(numOfEdges[i]);
+            if (numOfEdges[i] % 2 == 1) {
+                oddDegs.add(i);
+            }
+        }
+
+        Permutation permut = new Permutation(oddDegs.size());
+
+        calcPairShortest(oddDegs, salesPitch, permut, 0, 0);
+        permut.makePermutMinimal();
+
+        //System.out.println(permut.tempCounter1);
+        //System.out.println(permut.tempCounter2);
+        //System.out.println("min cost: " + permut.getMinCost());
+        //permut.printPermut();
+
+        ArrayList<TreeEdge> oddEdges = new ArrayList<>();
+        oddDegs.resetUsed();
+        for(int i = 0; i < permut.size(); i++) {
+            int offSet = permut.getValAtPos(i);
+
+            addOddEdge(oddEdges, oddDegs, salesPitch, offSet);
+        }
+
+        addOddEdge(oddEdges, oddDegs, salesPitch, 0);
+
+        return oddEdges;
+    }
+
+    private static void addOddEdge(ArrayList<TreeEdge> oddEdges, OddDegreeList oddDegs, ArrayList<ArrayList<SaleRoute>> salesPitch, int offSet) {
+        int orig = oddDegs.getUnused(0);
+        oddDegs.makeUsed(0);
+        int dest = oddDegs.getUnused(offSet);
+        oddDegs.makeUsed(offSet);
+
+        oddEdges.add(new TreeEdge(orig, dest, salesPitch.get(orig).get(dest - orig - 1).getTotalCost()));
+    }
+
+    private static void calcPairShortest(OddDegreeList oddDegs, ArrayList<ArrayList<SaleRoute>> salesPitch, Permutation permut, int permutPos, int costSoFar) {
+        while(true) {
+            int offSet;
+
+            if(permutPos == permut.size()) {
+                offSet = 0;
+            }
+            else {
+                offSet = permut.getValAtPos(permutPos);
+            }
+
+            int orig = oddDegs.getUnused(0);
+            int dest = oddDegs.getUnused(1 + offSet);
+
+            int edgeWeight = salesPitch.get(orig).get(dest - orig - 1).getTotalCost();
+            int newCost = costSoFar + edgeWeight;
+            //permut.tempCounter1++;
+
+            /*System.out.println();
+            System.out.println("permut pos: " + permutPos);
+            System.out.println(orig + " : " + dest);
+            System.out.println("newCost: " + newCost);
+            permut.printPermut();*/
+
+            if(newCost < permut.getMinCost()) {
+                if(permutPos == permut.size()) {
+                    permut.setMinCost(newCost);
+                    /*System.out.println();
+                    System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+                    System.out.println("New Min: " + newCost);
+                    System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");*/
+                }
+                else {
+                    int used1 = oddDegs.makeUsed(0);
+                    int used2 = oddDegs.makeUsed(offSet);
+                    calcPairShortest(oddDegs, salesPitch, permut, permutPos+1, costSoFar+edgeWeight);
+                    oddDegs.makeUnused(used1);
+                    oddDegs.makeUnused(used2);
+                    //TODO: do the right stuff
+                }
+            }
+
+            if(permutPos == permut.size()) {
+                //permut.tempCounter2++;
+                break;
+            }
+            if(permut.isPosAtMax(permutPos)) {
+                break;
+            }
+
+            permut.increaseAtPos(permutPos);
+
+
+
+            /*permut.increaseAtPos(3);
+            permut.printPermut();
+            permut.increaseAtPos(2);
+            permut.printPermut();
+            permut.increaseAtPos(2);
+            permut.printPermut();*/
+
+            //break;
+        }
+    }
+
+    public static ArrayList<TreeEdge> makeMSTree(ArrayList<ArrayList<SaleRoute>> salesPitch) {
+        ArrayList<TreeEdge> allEdges = new ArrayList<>();
+        ArrayList<TreeEdge> msTree = new ArrayList<>();
+
+        int vertNum = salesPitch.size();
+
+        for (int orig = 0; orig < salesPitch.size(); orig++) {
+            for (int dest = 0; dest < salesPitch.get(orig).size(); dest++) {
+                allEdges.add(new TreeEdge(orig, dest + 1 + orig, salesPitch.get(orig).get(dest).getTotalCost()));
+                //System.out.println(edge.getSrc() + " " + edge.getDest() + " " + edge.getWeight());
+                //System.out.println(salesPitch.get(orig).get(dest).getTotalCost());
+            }
+        }
+
+        //System.out.println(vertNum);
+
+        Collections.sort(allEdges);
+
+        while (msTree.size() < vertNum - 1) {
+
+            if (notCycle(msTree, allEdges.get(0))) {
+                msTree.add(allEdges.get(0));
+                //System.out.println(allEdges.get(0).getSrc() + " " + allEdges.get(0).getDest() + " " + allEdges.get(0).getWeight());
+            }
+            allEdges.remove(0);
+        }
+
+        return msTree;
+    }
+
+    private static void qEdges(ArrayList<TreeEdge> tree, ArrayList<TreeEdge> edgeQ, int vertex) {
+        for(int i = 0; i < tree.size(); i++) {
+            TreeEdge edge = tree.get(i);
+            if(edge.getSrc() == vertex || edge.getDest() == vertex) {
+                if(!edge.isChecked()) {
+                    edgeQ.add(edge);
+                    //System.out.println("src: " + edge.getSrc() + "; dest: " + edge.getDest());
+                    edge.setChecked(true);
+                }
+            }
+        }
+    }
+
+    private static boolean notCycle(ArrayList<TreeEdge> tree, TreeEdge additon) {
+        ArrayList<TreeEdge> edgeQ = new ArrayList<>();
+        int dest = additon.getDest();
+        resetEdges(tree);
+
+        qEdges(tree, edgeQ, additon.getSrc());
+
+        while(edgeQ.size() > 0) {
+            TreeEdge edge = edgeQ.get(0);
+            edgeQ.remove(0);
+            if(edge.getSrc() == dest || edge.getDest() == dest) {
+                return false;
+            }
+            else {
+                qEdges(tree, edgeQ, edge.getSrc());
+                qEdges(tree, edgeQ, edge.getDest());
+            }
+        }
+
+        return true;
+    }
+
+    private static void resetEdges(ArrayList<TreeEdge> tree) {
+        for(int i = 0; i < tree.size(); i++) {
+            tree.get(i).setChecked(false);
+        }
+    }
+}

+ 37 - 0
src/pathgame/algorithm/TreeEdge.java

@@ -0,0 +1,37 @@
+package pathgame.algorithm;
+
+public class TreeEdge implements Comparable< TreeEdge > {
+    private int src, dest, weight;
+    private boolean checked = false;
+
+    public TreeEdge(int src, int dest, int weight) {
+        this.src = src;
+        this.dest = dest;
+        this.weight = weight;
+    }
+
+    public int getSrc() {
+        return src;
+    }
+
+    public int getDest() {
+        return dest;
+    }
+
+    public Integer getWeight() {
+        return weight;
+    }
+
+    public boolean isChecked() {
+        return checked;
+    }
+
+    public void setChecked(boolean checked) {
+        this.checked = checked;
+    }
+
+    @Override
+    public int compareTo(TreeEdge o) {
+        return this.getWeight().compareTo(o.getWeight());
+    }
+}