Monalisa TSP Tour Length/Distance always wrong - java

the tour length of www.math.uwaterloo.ca/tsp/data/ml/tour/monalisa_5757191.tour is supposed to be 5757191 yet my code gives a result of 5759929.877458311. Assuming that the claim of being willing to pay $1000 for any improvement to be true, then the below code MUST be wrong, and yet I see no flaw. At first I assumed it was a numerical precision issue so I started using arbitrary precision arithmetic and I got almost the same results.
- double: 5759929.877458459
- BigDecimal(precision: 8 digits): 5759756.8
- BigDecimal(precision: 16 digits): 5759929.877458103
- BigDecimal(precision: 32 digits): 5759929.877458311
- BigDecimal(precision: 64,128,256,512 digits): no change
all of these are WAY OFF from the stated 5757191.
I even removed the cyclic edge from the beginning to the end on the assumption that it was a TSP path instead of a cycle, but it is still way to high.
The datafile clearly states "EDGE_WEIGHT_TYPE: EUC_2D" so it's not a matter of it being a different distance metric... (i.e. euclidean metric (i.e. sqrt(sum of squares)))
Here is the dataset of the points
in this format
nodeId integerCoordinate1 integerCoordinate2
Here is the code that reads thoses files and only returns the given tour length:
import java.util.HashMap;
import java.util.ArrayList;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.io.File;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.PrintWriter;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.MathContext;
public class TSPTest {
//map from NodeId from the input mona-lisa100K.tsp file to it's 2d coordinates
HashMap<Integer,int[]> pointMap;
//the order of NodeId's visited in a tour (first in the order of `mona-lisa100K.tsp' then replaced with the NodeId's in the best known 'monalisa_5757191.tour' file)
ArrayList<Integer> initState = new ArrayList<Integer>();
File file;
File tour;
int dimension;//i.e. 2 in this case
public TSPTest(File file, File tour) throws FileNotFoundException,IOException {
this.file = file;
this.tour = tour;
readFromFile();
loadTour();
}
public static void main(String... args) throws Throwable {
TSPTest tester = new TSPTest(new File("mona-lisa100K.tsp"),new File("monalisa_5757191.tour"));
int[] state = tester.initState();//the same values in 'monalisa_5757191.tour'
System.out.println("state.length: "+state.length);
double distance = tester.evaluate(state);
System.out.println("TOUR DISTANCE="+distance);
return;
}
synchronized void loadTour() throws FileNotFoundException,IOException {
if (tour == null) return;
BufferedReader in = new BufferedReader(new FileReader(tour), 1000000);
String line;
Pattern pLine = Pattern.compile("^\\d+$");
initState.clear();
while ((line = in.readLine()) != null) {
Matcher matcher = pLine.matcher(line);
if (!matcher.find()) {continue;}
initState.add(Integer.valueOf(matcher.group()));
}
in.close();
return;
}
synchronized void readFromFile() throws FileNotFoundException,IOException {
pointMap = new HashMap<Integer, int[]>();
BufferedReader in = new BufferedReader(new FileReader(file), 1000000);
String line;
Pattern pLine = Pattern.compile("\\d+( \\d+(?:\\.\\d*)?|\\.\\d+)+");
Pattern p = Pattern.compile("\\d+(?:\\.\\d*)?|\\.\\d+");
while ((line = in.readLine()) != null) {
Matcher matcher = pLine.matcher(line);
if (!matcher.find()) {continue;}
matcher = p.matcher(line);
if (!matcher.find()) {continue;}
dimension = 0;
while (matcher.find()) {++dimension;}
Integer index;
int[] cords = new int[dimension];
matcher.reset();
matcher.find();
index = Integer.valueOf(matcher.group());
initState.add(index);
for (int i = 0; i < dimension; ++i) {
matcher.find();
cords[i] = Integer.parseInt(matcher.group());
if (Math.abs(Double.parseDouble(matcher.group())-cords[i])>0.00001) {
//I'm assuming all integer coordinates
throw new RuntimeException(line);
}
}
pointMap.put(index, cords);
}
in.close();
return;
}
public int[] initState() {
int[] state = new int[initState.size()];
for (int i = 0; i < state.length; ++i) {
state[i] = initState.get(i);
}
return state;
}
public double evaluate(int[] state) {
int[] p1;
int[] p2;
java.math.MathContext mc = new java.math.MathContext(512,java.math.RoundingMode.HALF_EVEN);
//double distance = 0.;
java.math.BigDecimal distance = BigDecimal.ZERO;
//get first point in TSP tour
p1=pointMap.get(state[0]);
for (int i = 1; i<state.length; ++i) {
p2=pointMap.get(state[i]);//get the next point
//distance += distance(p1,p2,null);
distance = distance.add(distance(p1,p2,mc), mc);
p1=p2;//next point is now the first point
}
//next two lines would make it a distance over a TSP cycle instead of a path
//p2=pointMap.get(state[0]);
//distance += distance(p1,p2);
//return distance;
return distance.doubleValue();
}
//commented out double version of code that is replaced with BigDecimal
//private double distance(int[] p1, int[] p2, MathContext mc2) {
private BigDecimal distance(int[] p1, int[] p2, MathContext mc2) {
/*//old double based code
double distance = 0;
for (int i = 0; i < p1.length; ++i) {
distance += Math.pow(p1[i]-p2[i],2);
}
distance = Math.sqrt(distance);
return distance;
*/
//I thought this might improve precision... (no difference)
//return Math.hypot(p1[0]-p2[0],p1[1]-p2[1]);
//+8 just to be safe :)
MathContext mc = new MathContext(mc2.getPrecision()+8, java.math.RoundingMode.HALF_EVEN);
//euclidean distance
return sqrt(new BigDecimal(p1[0],mc).subtract(new BigDecimal(p2[0],mc)).pow(2,mc).add(new BigDecimal(p1[1],mc).subtract(new BigDecimal(p2[1],mc)).pow(2,mc)), mc);
}
//Babylonian method (aka Hero's method) (Newton's method)
private java.math.BigDecimal sqrt(java.math.BigDecimal A, java.math.MathContext mc2) {
MathContext mc = new MathContext(mc2.getPrecision()+8, java.math.RoundingMode.HALF_EVEN);
BigDecimal TWO = new BigDecimal(2);
BigDecimal x0 = new BigDecimal("0");
BigDecimal x1 = new BigDecimal(Math.sqrt(A.doubleValue()));
BigDecimal xp = null;
while (!x0.equals(x1) && (xp==null || x1.compareTo(xp)!=0)) {//xp is used to detect a convergence loop (x1 swaps with x0 in an infinite loop)
xp = x0;
x0 = x1;
x1 = A.divide(x0,mc);
x1 = x1.add(x0,mc);
x1 = x1.divide(TWO,mc);
}
return x1;
}
}

Related

How to brute force a math equation in a way that does not slow down an Android app

I am building a math game for Android using Java. It includes a 3x3 grid of numbers that the user has to solve using mathematical operations. Before the start of the game, three random numbers 1-6 are rolled.
However, during my testing, I have discovered that some of the numbers are not solvable, say 4, with 1, 1, 1. (These numbers would never be rolled, but you get the point.)
I am using MxParser to find if the generated equation is correct, but the help I need is on how to create valid math equations.
I have decided to take the brute-force approach, but I am unsure as how to create valid mathematical equations with that method. It would have to generate equations like:
(Our numbers are: 1, 2, 3)
12^03^0 = 1 (True) Next number #1
12^03^0 = 2 (True) Next number #2
12^23^2 = 13 (False) Try again. #3
And so on.
I have tried brute-forcing already, but am unsure exactly how to do so.
`
import org.mariuszgromada.math.mxparser.Expression;
import java.util.ArrayList;
public class GridParser {
public String num1String = "";
public String num2String = "";
public String num3String = "";
private static String l;
private static String q;
private static String a;
private static int p;
private static char[] w;
private static char[] c;
public void parseGrid(int num1, int num2, int num3, int gridID) {
num1String = String.valueOf(num1);
num2String = String.valueOf(num2);
num3String = String.valueOf(num3);
String operator1 = "+";
String operator2 = "-";
String operator3 = "/";
String operator4 = "*";
String operator5 = "^";
ArrayList solutions3x3 = new ArrayList();
ArrayList solutions4x4 = new ArrayList();
ArrayList solutions6x6 = new ArrayList();
String currentSolution = "";
double NumberOnGrid = 0.0;
int currentPOS = 0;
if (gridID == 3) {
NumberOnGrid = 3.0;
String l = "1234567890-()=+√*/^";
q = "";
p = 0;
w = a.toCharArray();
c = l.toCharArray();
while (!q.equals(a)) {
for (int i = 0; i < l.length(); i++) {
System.out.println("[❕] Trying: " + c[i]);
if (c[i] == w[p]) {
q += c[i];
p++;
System.out.println("[✔️] Found: " + c[i]);
Expression targetExpression = new Expression(q);
double expressonResult = targetExpression.calculate();
if(expressonResult == NumberOnGrid){
}
}
if (q.equals(a)) {
System.out.println("\n[✔️] Equation Found!");
}
}
}
}
}
}
I apologize for my code, it is still in "Rough Draft" state. =)
Additionally, it would be great if this could run on a background thread so it would not slow down my Android app.
Thanks
Someone PLZZZ help!

Can't access variable from toString in

I'm back with another question about my Dijkstra algorithm. I fixed my previous question, but now I want to make a toString() method.
When I try to make it, the variables I use are unreachable from toString(), and I don't understand why.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.ArrayList;
public class Graph
{
ArrayList<Vertex> vertexObjects = new ArrayList<Vertex>();
ArrayList<Edge> edgeObjects = new ArrayList<Edge>();
ArrayList<Vertex> visitedObjects = new ArrayList<Vertex>();
ArrayList<Vertex> unvisitedObjects = new ArrayList<Vertex>();
ArrayList<Edge> tempEdge = new ArrayList<Edge>();
int numVertices = 0;
public void readFile(String textfile)
{
try {
Scanner s = new Scanner(new File(textfile));
String sameVertex = "";
while (s.hasNext()) {
String preVertex = s.next();
String postVertex = s.next();
String distance = s.next();
Edge temp = new Edge(preVertex, postVertex, distance);
edgeObjects.add(temp);
if (!(preVertex.equals(sameVertex)))
{
Vertex herp = new Vertex(preVertex, Double.POSITIVE_INFINITY, false, null);
vertexObjects.add(herp);
sameVertex = preVertex;
numVertices++;
}
}
} catch (FileNotFoundException e) {
System.out.println("I can't find that file!");
}
}
public void dijkstra(String startVertex, String endVertex)
{
// Change the distance of the startVertex to 0 and all others to infinity.
for (int i = (numVertices-1); i >= 0; i--)
{
if (vertexObjects.get(i).vertexName.equals(startVertex))
{
vertexObjects.get(i).distance = 0;
} else {
vertexObjects.get(i).distance = Double.POSITIVE_INFINITY;
}
}
//Set the node with lowest distance value to Current Status
unvisitedObjects = vertexObjects;
double smallDistance = Double.POSITIVE_INFINITY;
while(unvisitedObjects.size() != 0) {
//set current node to vertex with shortest distance
String currentNode = "";
for (int j = (unvisitedObjects.size()-1); j >= 0; j--) {
if (unvisitedObjects.get(j).distance <= smallDistance) {
smallDistance = unvisitedObjects.get(j).distance;
currentNode = unvisitedObjects.get(j).vertexName;
}
}
//remove the smallest distance having node from the unvisited array
//and place into visited array.
for (int g = (unvisitedObjects.size()-1); g >= 0; g--) {
if (unvisitedObjects.get(g).vertexName.equals(currentNode))
{
visitedObjects.add(unvisitedObjects.get(g));
unvisitedObjects.remove(g);
}
}
//for all the nodes that are adjacent to the current node, update their
//distance values if they are larger than the weight plus previous distances.
for (int w = (edgeObjects.size()-1); w >= 0; w--) {
if (edgeObjects.get(w).startVertex == currentNode) {
tempEdge.add(edgeObjects.get(w));
}
for (int t = (tempEdge.size()-1); t >=0; t--) {
for (int p = (vertexObjects.size()-1); p >= 0; p--) {
if (tempEdge.get(t).endVertex == vertexObjects.get(p).vertexName)
{
if ((Double.parseDouble(tempEdge.get(t).edgeWeight) + smallDistance) < vertexObjects.get(p).distance) {
vertexObjects.get(p).distance = (Double.parseDouble(tempEdge.get(t).edgeWeight) + smallDistance);
}
}
}
}
}
}
String smallDString = Double.toString(smallDistance);
}
public Graph(String textfile, String startingVertex, String endingVertex) {
String graphFile = textfile;
String startVertex = startingVertex;
String endVertex = endingVertex;
}
public String toString() {
return ("The shortest path from "+startVertex+" to "+endVertex+" is "+smallDistance+".");
}
}
You can't access them because they are initialized within a function. You need to declare them as global variables.
ArrayList<Vertex> vertexObjects = new ArrayList<Vertex>();
ArrayList<Edge> edgeObjects = new ArrayList<Edge>();
ArrayList<Vertex> visitedObjects = new ArrayList<Vertex>();
ArrayList<Vertex> unvisitedObjects = new ArrayList<Vertex>();
ArrayList<Edge> tempEdge = new ArrayList<Edge>();
int numVertices = 0;
String startVertex, smallDistance, endVertex = "";
that might be the problem.
You need to make them field in your class. Not just local variables. For example in your constructor you can do:
private String graphFile; // declare variable to store value
public Graph(String textfile, String startingVertex, String endingVertex) {
graphFile = textfile; // assign value in constructor
...
You've only declared the variables in the public Graph(...) constructor, not in the scope for the rest of the class.
You need to declare them in the class body (normally near the top) for the methods to have access to them.
This is because you declared and initialized the variables (graphFile,startVertex,endVertex,) inside of your constructor. This means that they are only visible/usable inside the constructor. You need to declare them as class variables, then you can initialize them in the constructor. For example
public class Graph {
String graphFile;
public Graph(String textfile) {
this.graphFile = textfile;
}
}
You can do the same for the others as well.

Filtering the right path to implement dijkstra's algorithm

I have a goal and a starting point and a list of obstacles which are rectangles. My starting point is (0, 0) now I have perform dijkstra's algorithm to traverse from start to goal avoiding the obstacles. I can travel through the sides of the rectangle to reach the goal, but I cannot go through, basically all the points that form my rectangle are the vertices.
My input file is of this format
1.75 -0.25
-0.5 2.5 -1 1
0.75 1.31 -0.56 0.25
2 2.32 0.35 0.75
something like this ..
(xgoal ygoal
xmin0 xmax0 ymin0 ymax0
xmin1 xmax1 ymin1 ymax1
...
xminN xmaxN yminN ymaxN)
(line 1 is goal
line 2 is the boundary arena
line 3, line4, and thereafter... Are a list of obstacles, I.e rectangles)
Help: I have parsed the file and extracted all the points, the rectangles (obstacles)
I have a list which stores all the edges from a given point to every other point and
and a EdgeList which has the list of all the edges.
Can anyone tell me how to filter out the edges (obstacles) and generate a right path to implement dijkstra's.
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
//import DrawingRects;
import javax.swing.JPanel;
public class GlobalNav {
//private static BufferedReader br;
public static final ArrayList<Float> storeCoordinateList = new ArrayList<Float>();
public static final ArrayList<Rectangle2D> rectangleList = new ArrayList<Rectangle2D>();
public static final ArrayList<Float> storeCoordinates = new ArrayList<Float>();
public static final ArrayList<Point2D> points = new ArrayList<Point2D>();
public static void main(String[] args) throws IOException {
//ArrayList<Float> storeCoordinateList = new ArrayList<Float>();
FileInputStream fstream = new FileInputStream(args[0]);
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
//Read File Line By Line
while ((strLine = br.readLine()) != null) {
String[] nums = strLine.split(" ");
for (String n : nums){
try {
Float num = Float.parseFloat(n);
storeCoordinateList.add(num);
}
catch(NumberFormatException e){
}
}
}
//Close the input stream
System.out.println("Co-ordinate List " + storeCoordinateList);
in.close();
System.out.println("Size of Coo " + storeCoordinateList.size());
System.out.println("GlobalNav.main()4 " + storeCoordinateList.size());
int x1 = 2, x2 = 3, y1 = 4, y2 = 5;
//int xmin = 2, xmax = 3, ymin = 4, ymax =5;
System.out.println("GlobalNav.main()" + storeCoordinateList.size());
int expansion = 210;
points.add(new Point2D.Float(0, 0));
while(y2 < storeCoordinateList.size()){
//System.out.println("GlobalNav.main()" + x1);
float height = (storeCoordinateList.get(y2)) - (storeCoordinateList.get(y1));
float width = (storeCoordinateList.get(x2)) - (storeCoordinateList.get(x1));
//Rectangle rect = new Rectangle(Math.round(storeCoordinateList.get(x1)), Math.round(storeCoordinateList.get(y1)), Math.round(height), Math.round(width));
Rectangle2D.Float rect = new Rectangle2D.Float(storeCoordinateList.get(x1), storeCoordinateList.get(y1), height, width);
rectangleList.add(rect);
points.add(new Point2D.Float(storeCoordinateList.get(x1), storeCoordinateList.get(y1)));
points.add(new Point2D.Float(storeCoordinateList.get(x1), storeCoordinateList.get(y2)));
points.add(new Point2D.Float(storeCoordinateList.get(x2), storeCoordinateList.get(y1)));
points.add(new Point2D.Float(storeCoordinateList.get(x2), storeCoordinateList.get(y2)));
x1 += 4;
x2 += 4;
y1 += 4;
y2 += 4;
}
points.add(new Point2D.Float(storeCoordinateList.get(0), storeCoordinateList.get(1)));
System.out.println("List" + rectangleList.toString());
System.out.println("List" + points.toString());
filterIntersectionEdges(points);
}
private static void filterIntersectionEdges(ArrayList<Point2D> points2) {
// TODO Auto-generated method stub
ArrayList<Edge> edge = new ArrayList<Edge>();
//edge.add(Point(0, 0));
ArrayList<ArrayList<Edge>> listOfEdges = new ArrayList<ArrayList<Edge>>();
for (int i = 0; i < points2.size(); i++) {
for (int j = i + 1; j < points2.size(); j++) {
edge.add(new Edge(points2.get(i),points2.get(j)));
listOfEdges.add(edge);
// System.out.println("Edges" + edge.toString());
// System.out.println("List of Edges" + listOfEdges.toString());
}
}
Edge line1 = new Edge();
int i = 0;
for (ArrayList<Edge> newEdge : listOfEdges) {
line1 = newEdge.get(i);
for (Iterator iterator = newEdge.iterator(); iterator.hasNext();) {
Edge line2 = (Edge) iterator.next();
//System.out.println(" lIne 2 " + line2);
}
i++;
}
}
}
class Edge{
private Point2D pointA;
private Point2D pointB;
public Edge(Point2D pointA, Point2D pointB){
this.pointA = pointA;
this.pointB = pointB;
}
public String size() {
// TODO Auto-generated method stub
return null;
}
public Edge() {
// TODO Auto-generated constructor stub
}
public Point2D getPoint1(){
return this.pointA;
}
public Point2D getPoint2(){
return this.pointB;
}
#Override
public String toString(){
return "Point 1:" + pointA.toString() + " Point 2:" + pointB.toString();
}
}

File input for Dijkstra's algorithm

I am having trouble figuring out how to read an input file with java. The file has the following format:
u1 v1 w1
u2 v2 w2
...
um vm wm
-1
source
Each 3-tuple denotes an edge, which is specified by its source-vertex, its destination-vertex, and its weight (example: newyork boston 30). The description of the graph is terminated by a “flag”, the integer -1. A string follows this flag; this string is the name of the source vertex for the Dijkstra shortest-path algorithm. That is, you are to determine and print out the shortest path from this source vertex to every other vertex in the graph.
Here is my current work.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.PriorityQueue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
class Vertex implements Comparable<Vertex> {
public final String name;
public Edge[] adjacencies;
public double minDistance = Double.POSITIVE_INFINITY;
public Vertex previous;
public Vertex(String argName) {
name = argName;
}
public String toString() {
return name;
}
public int compareTo(Vertex other) {
return Double.compare(minDistance, other.minDistance);
}
}
class Edge {
public final Vertex target;
public final double weight;
public Edge(Vertex argTarget, double argWeight) {
target = argTarget;
weight = argWeight;
}
}
public class Dijkstra {
public static void computePaths(Vertex source) {
source.minDistance = 0.;
PriorityQueue<Vertex> vertexQueue = new PriorityQueue<Vertex>();
vertexQueue.add(source);
while (!vertexQueue.isEmpty()) {
Vertex u = vertexQueue.poll();
// Visit each edge exiting u
for (Edge e : u.adjacencies) {
Vertex v = e.target;
double weight = e.weight;
double distanceThroughU = u.minDistance + weight;
if (distanceThroughU < v.minDistance) {
vertexQueue.remove(v);
v.minDistance = distanceThroughU;
v.previous = u;
vertexQueue.add(v);
}
}
}
}
public static ArrayList<Vertex> getShortestPathTo(Vertex target) {
ArrayList<Vertex> path = new ArrayList<Vertex>();
for (Vertex vertex = target; vertex != null; vertex = vertex.previous)
path.add(vertex);
Collections.reverse(path);
return path;
}
public String[] readFile(String fileName) throws FileNotFoundException {
Scanner input = new Scanner(new File(fileName));
String line = "";
while (input.hasNext()) {
line = line.concat(input.nextLine());
}
String[] graph = line.split("");
return graph;
}
public static void main(String[] args) throws FileNotFoundException {
final String TEST = "/TestInput.txt";
Scanner input = new Scanner(new File(TEST));
String line = "";
while (input.hasNext()) {
line = line.concat(input.nextLine());
}
String[] graph = line.split(" ");
for (int i = 0; i < graph.length; i++) {
System.out.println(graph[i]);
}
Vertex[] verts = new Vertex[graph.length];
Edge[] edges = new Edge[graph.length];
Vertex v1 = new Vertex("");
Vertex v2 = new Vertex("");
Vertex source = new Vertex("");
int count = 0;
outerloop: for (int i = 0; i < (graph.length); i++) {
if (graph[i].equals("-1")) {
// do algorithm initialization here w/ source
}
if (i == 0) {
verts[i] = new Vertex(graph[i]);
count++;
} else {
innerloop: for (int j = count; j >= 0; j--) {
if (i / 3 == 0) {
if (graph[i].equals(verts[j].toString())) {
break innerloop;
} else if (j == 0) {
verts[count] = new Vertex(graph[i]);
v1 = verts[count];
count++;
}
}
if (i / 3 == 1) {
if (graph[i].equals(verts[j])) {
break innerloop;
} else if (j == 0) {
verts[count] = new Vertex(graph[i]);
v2 = verts[count];
count++;
}
}
if (i / 3 == 2) {
}
}
}
}
for (int i = 0; i < verts.length; i++) {
System.out.println(verts[i]);
}
}
}
So my only problem is how to get from the given .txt file format to a graph. Any suggestions are welcome.
Use a Scanner to parse the file data. For each tuple, if the source vertex hasn't been created, create it, otherwise find it in the pre-existing graph -- create a search function. Do the same for the target vertex. Next, create an edge with a weight equal to the third token in the tuple, and add the target vertex to the edge. Finally, add the edge to the adjacency list of the source vertex.
For the previously mentioned search function, you can implement something that can search through each vertex of the graph starting from any vertex. Recursion will be necessary.
public static Vertex search(Vertex src, String name);
A simpler solution is to keep a list of all the vertices you create as your constructing the graph and search through that.
public static Vertex search(List<Vertex> vertices, String name);
When your done constructing the graph and you have the name of the vertex where Dijkstra's algorithm will begin, you can use the search function to get a reference to the vertex.
Dijkstra.computePath(search(vertices, startVertexName));
And, that's it. Here's an example of how to parse your file data:
List<Vertex> vertices = new ArrayList<Vertex>();
String src =
"Pittsburgh Philadelphia 323 "+
"Pittsburgh Ohio 125 "+
"Ohio Philadelphia 400 "+
"-1 Ohio";
//new Scanner(new File(fileName));
Scanner scnr = new Scanner(src);
String src, target;
int weight;
while(scnr.hasNext())
{
src = scnr.next();
if(src.equals("-1"))
break;
else {
target = scnr.next();
weight = scnr.nextInt();
}
//call search(), implement logic in addToGraph()
addVertexToGraph(src, target, weight, vertices);
}
String startVertexName = scnr.next();
scnr.close();
Note that Scanner.next returns the next token separated by white space (the default delimiter), so your file data must be formatted that way.
Here's a shot:
/**
* Read the file using provided filename, construct vertices etc.
*
* #param fileName name of the file to read.
* #return true if everything is OK
* #throws FileNotFoundException if file is not found or not readable
*/
public boolean readFile(final String fileName) throws FileNotFoundException {
final Scanner input = new Scanner(new File(fileName));
boolean result = false;
while (input.hasNext()) {
final String line = line = input.nextLine();
if ("-1".equals(line)) {
// end of data
if (input.hasNext()) {
final String nameOfTheSource = input.next();
// TODO: do something with nameOfTheSource
result = true;
} else {
// bad input format: there should be something after -1
}
} else {
final String Scanner vert = new Scanner(line);
try {
final String sourceName = vert.next();
final String targetName = vert.next();
final int weight = vert.nextInt(); // assuming int for weight
// TODO: create Vertices and Edge here
} catch (final NoSuchElementException ex) {
// bad input format for "line"!
}
}
}
return result;
}
Not tested.
{import Stack.Dijkstra;
{import java.io.File;
{import java.io.FileNotFoundException;
{import java.util.Scanner;
{public class App {
{public static void main(String[] args) throws {FileNotFoundException {
{Vertex v1 = new Vertex("A");
{Vertex v2 = new Vertex("B");
{Vertex v3 = new Vertex("C");
{`v1.addNeighbour(new Edge(1, v1, v2));
{`v1.addNeighbour(new Edge(10, v1, v2));
{`v2.addNeighbour(new Edge(1, v2, v3));
{`Dijkstra dijkstra = new Dijkstra();
{`dijkstra.computePath(v1);
{`System.out.println(dijkstra.getShortestPathTo(v3));
{`final String test = "X:\\neon3\\eclipse\\TestInput.txt";
{`Scanner input = new Scanner(new File(test));
{`String line = "";
{`while (input.hasNext()) {
{`line = line.concat(input.nextLine());
}
{`String[] graph = line.split(" ");
{`for (int i = 0; i < graph.length; i++) {
{`System.out.println(graph[i]);
}
}
}`}

NullPointerException, Collections not storing data?

I posted this question earlier but not with the code in its entirety. The coe below also calls to other classes Background and Hydro which I have included at the bottom.
I have a Nullpointerexception at the line indicate by asterisks. Which would suggest to me that the Collections are not storing data properly. Although when I check their size they seem correct.
Thanks in advance. PS: If anyone would like to give me advice on how best to format my code to make it readable, it would be appreciated.
Elliott
>package exam0607;
>import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Collection;
import java.util.Scanner;
import java.util.Vector;
>import exam0607.Hydro;
import exam0607.Background;// this may not be necessary???? FIND OUT
>public class HydroAnalysis {
public static void main(String[] args) {
Collection<Hydro> hydroList = null;
Collection<Background> backList = null;
try{hydroList = readHydro("http://www.hep.ucl.ac.uk/undergrad/3459/exam_data/2006-07/final/hd_data.dat");}
catch (IOException e){
e.getMessage();}
try{backList = readBackground("http://www.hep.ucl.ac.uk/undergrad/3459/exam_data/2006-07/final/hd_bgd.dat");
//System.out.println(backList.size());
}
catch (IOException e){
e.getMessage();}
for(int i =0; i <=14; i++ ){
String nameroot = "HJK";
String middle = Integer.toString(i);
String hydroName = nameroot + middle + "X";
System.out.println(hydroName);
ALGO_1(hydroName, backList, hydroList);
}
}
public static Collection<Hydro> readHydro(String url) throws IOException {
URL u = new URL(url);
InputStream is = u.openStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader b = new BufferedReader(isr);
String line ="";
Collection<Hydro> data = new Vector<Hydro>();
while((line = b.readLine())!= null){
Scanner s = new Scanner(line);
String name = s.next();
System.out.println(name);
double starttime = Double.parseDouble(s.next());
System.out.println(+starttime);
double increment = Double.parseDouble(s.next());
System.out.println(+increment);
double p = 0;
double nterms = 0;
while(s.hasNextDouble()){
p = Double.parseDouble(s.next());
System.out.println(+p);
nterms++;
System.out.println(+nterms);
}
Hydro SAMP = new Hydro(name, starttime, increment, p);
data.add(SAMP);
}
return data;
}
public static Collection<Background> readBackground(String url) throws IOException {
URL u = new URL(url);
InputStream is = u.openStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader b = new BufferedReader(isr);
String line ="";
Vector<Background> data = new Vector<Background>();
while((line = b.readLine())!= null){
Scanner s = new Scanner(line);
String name = s.next();
//System.out.println(name);
double starttime = Double.parseDouble(s.next());
//System.out.println(starttime);
double increment = Double.parseDouble(s.next());
//System.out.println(increment);
double sum = 0;
double p = 0;
double nterms = 0;
while((s.hasNextDouble())){
p = Double.parseDouble(s.next());
//System.out.println(p);
nterms++;
sum += p;
}
double pbmean = sum/nterms;
Background SAMP = new Background(name, starttime, increment, pbmean);
//System.out.println(SAMP);
data.add(SAMP);
}
return data;
}
public static void ALGO_1(String hydroName, Collection<Background> backgs, Collection<Hydro> hydros){
//double aMin = Double.POSITIVE_INFINITY;
//double sum = 0;
double intensity = 0;
double numberPN_SIG = 0;
double POSITIVE_PN_SIG =0;
//int numberOfRays = 0;
for(Hydro hd: hydros){
System.out.println(hd.H_NAME);
for(Background back : backgs){
System.out.println(back.H_NAME);
if(back.H_NAME.equals(hydroName)){//ERROR HERE
double PN_SIG = Math.max(0.0, hd.PN - back.PBMEAN);
numberPN_SIG ++;
if(PN_SIG > 0){
intensity += PN_SIG;
POSITIVE_PN_SIG ++;
}
}
}
double positive_fraction = POSITIVE_PN_SIG/numberPN_SIG;
if(positive_fraction < 0.5){
System.out.println( hydroName + "is faulty" );
}
else{System.out.println(hydroName + "is not faulty");}
System.out.println(hydroName + "has instensity" + intensity);
}
}
}
THE BACKGROUND CLASS
package exam0607;
public class Background {
String H_NAME;
double T_START;
double DT;
double PBMEAN;
public Background(String name, double starttime, double increment, double pbmean) {
name = H_NAME;
starttime = T_START;
increment = DT;
pbmean = PBMEAN;
}}
AND THE HYDRO CLASS
public class Hydro {
String H_NAME;
double T_START;
double DT;
double PN;
public double n;
public Hydro(String name, double starttime, double increment, double p) {
name = H_NAME;
starttime = T_START;
increment = DT;
p = PN;
}
}
Ah. Your Hydro class is completely wrong. You're assigning the parameters to the uninitialised members.
e.g.
public Hydro(String name, double starttime, double increment, double p) {
name = H_NAME;
but H_NAME is uninitialised. You need to reverse these e.g.
public Hydro(String name, double starttime, double increment, double p) {
H_NAME = name;
Some hints:
write a toString() method for each class, so you can print it out meaningfully
declare your method parameters as final if you don't expect them to change
declare your member variables to be final if you expect your class to be immutable (unchanging)
investigate unit tests and JUnit
In the above, 1. makes debugging easier 2. and 3. means that the compiler will prevent you from the (all too common) mistake above (try preceeding your method parameters with final and see what happens!) 4. will force you to test at a low level and keep your code correct.
For debugging purposes it's useful to only deference one reference at a time. This helps you identify unexpected null references e.g. if the following gives a NullPointerException
a.getB().getC().getD()
which of a, getB(), getC() gave the null reference ? Dereferencing one per line is more verbose but will give you much more info (object purists will object to the above and refer you to the Law Of Demeter - I shall ignore that for this example).

Categories

Resources