package ch.usi.inf.ikm.tsp;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Date;
import java.util.InvalidPropertiesFormatException;
import javax.activation.UnsupportedDataTypeException;
public class TSPBuilder {
private int[] nodes;
private double[] nodesX;
private double[] nodesY;
private String name;
private String comment;
private int dimension;
private int bestKnown;
public TSPBuilder(final String filename) {
this.name = "TSP Instance " + new Date();
this.comment = "Generated with Nearest Neighbour, 2-Opt and Simulated Annealing by Jacques DAFFLON";
final File file = new File(filename);
this.load(file);
}
private void load(final File file) {
BufferedReader reader = null;
String line = null;
boolean hasDimension = false;
boolean validType = false;
try {
reader = new BufferedReader(new FileReader(file));
} catch (final FileNotFoundException e) {
System.err.println("The file specified was not found.");
e.printStackTrace();
}
try {
while ((line = reader.readLine()) != null) {
line = line.trim();
if (line.equals("NODE_COORD_SECTION")) {
if (!hasDimension || !validType) {
throw new InvalidPropertiesFormatException("Missing the DIMENSION property or this is not a tsp");
}
this.nodes = new int[this.dimension];
this.nodesX = new double[this.dimension];
this.nodesY = new double[this.dimension];
this.loadNodes(reader);
} else if (line.equals("EOF")) {
//Done
break;
} else if (line.isEmpty()) {
//Do nothing
} else {
final String[] tokens = line.split(":");
final String key = tokens[0].trim();
final String value = tokens[1].trim();
if (key.equals("NAME")) {
this.name = value;
} else if (key.equals("COMMENT")) {
this.comment = this.comment + " " + value;
} else if (key.equals("TYPE")) {
validType = value.toLowerCase().equals("tsp");
} else if (key.equals("DIMENSION")) {
this.dimension = Integer.parseInt(value);
hasDimension = true;
} else if (key.equals("EDGE_WEIGHT_TYPE")) {
if (!value.equals("EUC_2D")) {
throw new UnsupportedDataTypeException("Only EUC_2D edge weights are supported for now");
}
} else if (key.equals("BEST_KNOWN")) {
this.bestKnown = Integer.parseInt(value);
}
}
}
} catch (final IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void loadNodes(final BufferedReader reader) throws IOException {
for (int i = 0; i < this.dimension; i++) {
final String line = reader.readLine();
final String[] tokens = line.trim().split("\\s+");
if (tokens.length != 3) {
throw new IOException("Invalid node entry");
}
final int value = Integer.parseInt(tokens[0]);
final double nodeX = Double.parseDouble(tokens[1]);
final double nodeY = Double.parseDouble(tokens[2]);
final int precisionNode = Math.max(
Double.toString(nodeX).length() - Double.toString(nodeX).indexOf('.') - 1,
Double.toString(nodeY).length() - Double.toString(nodeY).indexOf('.') - 1);
this.nodes[i] = value;
this.nodesX[i] = nodeX;
this.nodesY[i] = nodeY;
}
}
public int getBestKnown() {
return this.bestKnown;
}
public String getComment() {
return this.comment;
}
public int getDimension() {
return this.dimension;
}
public String getName() {
return this.name;
}
public int[] getNodes() {
return this.nodes;
}
public double[] getNodesX() {
return this.nodesX;
}
public double[] getNodesY() {
return this.nodesY;
}
}