Browse Source

Fixing traveling salesperson solution for clarity.

master
Charles Reid 5 years ago
parent
commit
9aff4bc305
  1. 137
      java/guava/TSP.java

137
java/guava/TSP.java

@ -16,6 +16,13 @@ import com.google.common.graph.MutableNetwork;
/** This class solves the traveling salesman problem on a graph. */
class TSP {
public static void main(String[] args) {
TSP t = new TSP();
t.solve();
}
/**
* This class solves the traveling salesman problem on a graph.
* It makes use of Google's Guava library.
@ -35,11 +42,9 @@ class TSP {
double this_distance; // store the total distance
double min_distance; // store the shortest path found so far
/** Defaut constructor generates the graph and initializes storage variables */
/** Default constructor generates the graph and initializes storage variables */
public TSP() {
// Build the graph
//
// https://github.com/google/guava/wiki/GraphsExplained#building-graph-instances
this.graph = buildGraph();
this.graphSize = this.graph.nodes().size();
@ -50,6 +55,54 @@ class TSP {
this.this_distance = 0.0;
this.min_distance = -1.0; // negative min means uninitialized
}
/** This method actually constructs the graph. */
public ImmutableNetwork<Node,Edge> buildGraph() {
/** Make a NetworkBuilder object for an undirected network and call build().
*
* https://github.com/google/guava/wiki/GraphsExplained#building-graph-instances
*/
// MutableNetwork is an interface requiring a type for nodes and a type for edges
MutableNetwork<Node,Edge> roads = NetworkBuilder.undirected().build();
// Construct a dictionary of nodes (cities)
String[] cities = {"A","B","C","D","E"};
Map<String,Node> all_nodes = new TreeMap<String,Node>();
for(int i = 0; i<cities.length; i++) {
Node node = new Node(cities[i]);
all_nodes.put(cities[i], node);
// Add the nodes to the network
roads.addNode(node);
}
// Construct Edges for roads,
// and add them to a map
String[] distances = {"A:B:24","A:C:5","A:D:20","A:E:18","B:C:10","B:D:20","C:D:4","C:E:28","D:E:3"};
Map<String,Edge> all_edges = new TreeMap<String,Edge>();
for(int j = 0; j<distances.length; j++) {
// Parse out (city1):(city2):(distance)
String[] splitresult = distances[j].split(":");
String left = splitresult[0];
String right = splitresult[1];
String label = left + ":" + right;
int value = Integer.parseInt(splitresult[2]);
// Add edges to map
Edge edge = new Edge(left, right, value);
all_edges.put(label, edge);
// Add edges to network
roads.addEdge(all_nodes.get(edge.left), all_nodes.get(edge.right), edge);
}
// Freeze the network
ImmutableNetwork<Node,Edge> frozen_roads = ImmutableNetwork.copyOf(roads);
return frozen_roads;
}
/** Public solve method will call the recursive backtracking method to search for solutions on the graph */
public void solve() {
@ -75,14 +128,7 @@ class TSP {
// Pass the number of choices made
int nchoices = 1;
// NOTE: To change the problem so you start/end in the same city,
// change these so it's not added to the route, and nchoices is 0.
// Then add the last node constraint to the solution check.
// explore() will access the following class-wide variables:
// - this.route - for saving solutions; the current route (list of strings).
// - this.distance - distance traveled along the route thus far (double).
// - this.graph - the graph itself.
// Recursive backtracking
explore(startNode, nchoices);
}
@ -148,77 +194,14 @@ class TSP {
} // End base/recursive case
}
/** This method actually constructs the graph.
* Eventually this should read the adjacency matrix from a file. */
public ImmutableNetwork<Node,Edge> buildGraph() {
/** Here are the steps to getting a graph object we can use.
* Start by creating a mutable graph object.
* Modify the graph to construct the TSP problem specified.
* Make the graph immutable (faster than mutable).
*
* We have 2 options for graph objects:
* ValueGraph or Network.
* Networks can take arbitrary Node and Edge objects,
* while ValueGraph just stores a number in each Edge.
* We could use a ValueGraph, but the Network is more useful.
*
* Make a NetworkBuilder object for an undirected network and call build().
*/
// MutableNetwork is an interface requiring a type for nodes and a type for edges
MutableNetwork<Node,Edge> roads = NetworkBuilder.undirected().build();
// Available methods:
// addEdge(node1, node2, edge)
// addNode(node1)
// removeEdge(edge)
// removeNode(node)
// Construct a dictionary of nodes (cities)
String[] cities = {"A","B","C","D","E"};
Map<String,Node> all_nodes = new TreeMap<String,Node>();
for(int i = 0; i<cities.length; i++) {
Node node = new Node(cities[i]);
all_nodes.put(cities[i], node);
// Add the nodes to the network
roads.addNode(node);
}
// Construct a dictionary of edges (roads)
String[] distances = {"A:B:24","A:C:5","A:D:20","A:E:18","B:C:10","B:D:20","C:D:4","C:E:28","D:E:3"};
Map<String,Edge> all_edges = new TreeMap<String,Edge>();
for(int j = 0; j<distances.length; j++) {
String[] splitresult = distances[j].split(":");
String left = splitresult[0];
String right = splitresult[1];
String label = left + ":" + right;
int value = Integer.parseInt(splitresult[2]);
Edge edge = new Edge(left, right, value);
all_edges.put(label, edge);
// Add the edges to the graph
roads.addEdge(all_nodes.get(edge.left), all_nodes.get(edge.right), edge);
}
// Freeze the graph
ImmutableNetwork<Node,Edge> frozen_roads = ImmutableNetwork.copyOf(roads);
return frozen_roads;
}
/** Print out solution */
public void printSolution() {
System.out.print("@@@@@@@@@@\tNEW SOLUTION\t");
System.out.println("Route: "+Arrays.toString(this.route)
+"\tDistance: "+this.min_distance);
}
public void printFailure() {
System.out.print("XXXXXXXXXX\tNO SOLUTION\t");
System.out.println("Route: "+Arrays.toString(this.route)
+"\tDistance > Min: "+this.this_distance
+" > "+this.min_distance);
}
/** Print out failed path */
public void printFailure() { }
}
/** Node class to represent cities */

Loading…
Cancel
Save