import java.util.StringTokenizer; import java.util.Arrays; import java.io.*; public class TSPTester{ // Arrays to keep track of info. related to each city private String[] cityName; private String[] cityState; private int[] cityLat; private int[] cityLong; private int[] cityPop; // 2-D array to keep track of pairwise distances between cities private int[][] distances; // number of cities private static int numCities; public TSPTester(int n) { numCities = n; //Allotting the space for each 1-D array cityName = new String[numCities]; cityState = new String[numCities]; cityLat = new int[numCities]; cityLong = new int[numCities]; cityPop = new int[numCities]; // Allocate space for each 2-D array. These arrays have 0 elements in row 0, // 1 element in row 1, 2 elements in row 2, etc. distances = new int[numCities][]; for(int i = 0; i < numCities; i++) distances[i] = new int[i]; try{ // Construct a buffered reader object and connect it to the files "miles.dat" BufferedReader in = new BufferedReader(new FileReader("miles.dat")); // A counter that keeps track of the index of the current city being read int cityNumber = 0; // While-loop for reading in data from "miles.dat." At the beginning of the while-loop // the expectation is that we'll be reading a line containing the city name. Instead, // if we encounter a line that starts with "*" then we skip to the next line while(cityNumber < numCities) { // Read in a line String line = in.readLine(); // Skip the rest of the loop if line starts with a "*" if(line.charAt(0) == '*') continue; // Otherwise tokenize the line StringTokenizer tokenizedLine= new StringTokenizer(line, ",[]"); //Putting actual data into correct position in the array cityName[cityNumber] = tokenizedLine.nextToken(); cityState[cityNumber]= (tokenizedLine.nextToken()).trim(); // trim() gets rid of leading/trailing blanks cityLat[cityNumber] = Integer.parseInt(tokenizedLine.nextToken()); cityLong[cityNumber] = Integer.parseInt(tokenizedLine.nextToken()); cityPop[cityNumber] = Integer.parseInt(tokenizedLine.nextToken()); //while loop to put distances in the array; this may need to read several lines int mileNumber = 0; while (mileNumber < cityNumber) { // Read a mileage line and tokenize it String mileage = in.readLine(); StringTokenizer tokenizedMileage = new StringTokenizer(mileage, " "); // Read all the mileage data in this line into row cityNumber; increment // mileNumber after each read while(tokenizedMileage.hasMoreTokens()) { distances[cityNumber][cityNumber-mileNumber-1] = Integer.parseInt(tokenizedMileage.nextToken()); mileNumber++; } } // end of while reading distances cityNumber++; } // end of while reading cities } // end of try catch (IOException e) {System.out.println("File not found.");} } // end of TSPTester() constructor // A simple getIndex method to help test the constructor int getIndex(String city, String state) { int location; for(location = 0; location < numCities; location++) if((cityName[location].equals(city)) && (cityState[location].equals(state))) return location; return -1; } // Print information about a city, given a city index void printCityInfo(int index) { System.out.println(cityName[index] + " " + cityState[index] + " " + cityLat[index] + " " + cityLong[index] + " " + cityPop[index]); } // Print distance information between a given pair of cities void printDistanceInfo(int i, int j) { if(i < j) System.out.println(distances[j][i]); else System.out.println(distances[i][j]); } int getDistance(int i, int j) { if(i < j) return distances[j][i]; else if(j < i) return distances[i][j]; else return 0; } int[] greedyTSP() { // Find a cheapest triangle // Load triangle 0-1-2 into the the first 3 slots of the greedy array int[] greedy = new int[numCities]; int currentDistance; greedy[0] = 0; greedy[1] = 1; greedy[2] = 2; int currentBestDistance = getDistance(0, 1) + getDistance(1, 2) + getDistance(2, 0); for(int i = 0; i < numCities; i++) for(int j = 0; j < i; j++) for(int k = 0; k < j; k++) if((currentDistance = getDistance(i, j) + getDistance(j, k) + getDistance(i, k)) < currentBestDistance) { greedy[0] = i; greedy[1] = j; greedy[2] = k; currentBestDistance = currentDistance; } // Try greedily to add a city that yields the smallest increase // in the cost of the tour int partialTourSize = 3; boolean[] visited = new boolean[numCities]; for(int i = 0; i < numCities; i++) visited[i] = false; visited[greedy[0]] = true; visited[greedy[1]] = true; visited[greedy[2]] = true; // Main loop: keep repeating until partial tour covers all cities while(partialTourSize < numCities) { int smallestIncrease = Integer.MAX_VALUE; int increase = 0; int bestInsertionPoint = 0; int bestCity = 0; // Scan through all cities, stopping at unvisited cities for(int i = 0; i < numCities; i++) { if(!visited[i]) { // Consider all possible positions of inserting city i into the tour // and record the smallest increase for(int j = 0; j < partialTourSize; j++) { increase = getDistance(greedy[j], i) + getDistance(i, greedy[(j+1)%numCities]) - getDistance(greedy[j], greedy[(j+1)%numCities]); if(increase < smallestIncrease) { smallestIncrease = increase; bestCity = i; bestInsertionPoint = j; } // end of if we have found a smaller increase } // end of for-j } // end of if not visited } // end of for-i // Now we are ready to insert the bestCity at the bestInsertionPoint for(int j = partialTourSize-1; j > bestInsertionPoint; j--) greedy[j+1] = greedy[j]; greedy[bestInsertionPoint+1] = bestCity; visited[bestCity] = true; partialTourSize++; } // end-while return greedy; } void copy(int[] source, int[] dest) { for(int i = 0; i < dest.length; i++) dest[i] = source[i]; } void TSP(int[] R, int partialTourSize, boolean[] visited, int[] T) { // Base case: we have discovered a tour better than T if((partialTourSize == numCities)&&(cost(R) < cost(T))) { System.out.println("Base case. Tour cost is " + cost(R)); copy(R, T); return; } // Another base case: our partial tour is not worth completing if (cost(R, partialTourSize) >= cost(T)) return; // Recursive case: R is not complete and is currently better than T // and is therefore worth completing for(int i = 0; i < numCities; i++) { if(!visited[i]) { //System.out.println("Appending " + i); visited[i] = true; R[partialTourSize++] = i; TSP(R, partialTourSize, visited, T); partialTourSize--; visited[i] = false; //System.out.println("Deleting " + i); } } // end of for-loop } // end of TSP double cost(int[] tour) { return cost(tour, tour.length); } double cost(int[] tour, int tourSize) { double c = 0; for(int i = 0; i < tourSize-1; i++) c = c + getDistance(tour[i], tour[i+1]); c = c + getDistance(tour[tourSize-1], tour[0]); return c; } //Main method public static void main(String[] args) { for(int n = 128; n <= 128; n++) { TSPTester newTester = new TSPTester(n); int[] greedyTour = newTester.greedyTSP(); for(int i = 0; i < greedyTour.length; i++) System.out.print(greedyTour[i] + " "); System.out.println(" "); System.out.println(n + " cities. The cost of the greedy tour is " + newTester.cost(greedyTour)); /* int[] R = new int[numCities]; R[0] = 0; boolean[] visited = new boolean[numCities]; for(int i = 0; i < numCities; i++) visited[i] = false; visited[0] = true; newTester.TSP(R, 1, visited, greedyTour); for(int i = 0; i < greedyTour.length; i++) System.out.print(greedyTour[i] + " "); System.out.println(" "); System.out.println(n + " cities. The cost of the optimal tour is " + newTester.cost(greedyTour)); */ } } }