Is it possible to add edges to a graph through the use of a loop? I am parsing a String to determine the appropriate edges and labels. For some reason it will only add the edge for the first round of the while loop used to iterate through the String. For all of the others the following message appears...
Warning: an edge was deleted because the underlying JGraphT graph refused to create it. This situation can happen when a constraint of the underlying graph is violated, e.g., an attempt to add a parallel edge or a self-loop to a graph that forbids them. To avoid this message, make sure to use a suitable underlying JGraphT graph.
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import org.jgraph.*;
import org.jgraph.graph.*;
import org.jgrapht.*;
import org.jgrapht.ext.*;
import org.jgrapht.graph.*;
// resolve ambiguity
import org.jgrapht.graph.DefaultEdge;
public class JGraphAdapterDemo
extends JApplet
{
private static final long serialVersionUID = 3256444702936019250L;
private static final Color DEFAULT_BG_COLOR = Color.decode("#FAFBFF");
private static final Dimension DEFAULT_SIZE = new Dimension(530, 320);
static ListenableGraph<String, String> g =
new ListenableDirectedMultigraph<String, String>(String.class);
static int [] finalStates = new int[10];
static int startState = 0;
static char tran = ' ';
static int endState = 0;
private JGraphModelAdapter<String,String> jgAdapter;
public static void main(String [] args)
{
JGraphAdapterDemo applet = new JGraphAdapterDemo();
applet.init();
JFrame frame = new JFrame();
frame.getContentPane().add(applet);
frame.setTitle("JGraphT Adapter to JGraph Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public void init()
{
// create a JGraphT graph
ListenableGraph<String, String> g =
new ListenableDirectedMultigraph<String, String>(String.class);
// create a visualization using JGraph, via an adapter
jgAdapter = new JGraphModelAdapter<String, String>(g);
JGraph jgraph = new JGraph(jgAdapter);
adjustDisplaySettings(jgraph);
getContentPane().add(jgraph);
resize(DEFAULT_SIZE);
int numStates = 4;
int numSymbols;
int currentState;
int i = 0;
String input = "4 2 0 2 -1 0 a 1 1 b 3 2 c 2 3 c 3 -1"; //place input String here
int readInt = 0;
int j = 0;
String str = "";
int place = 0;
String fState;
//read in numStates, numSymbols, initialState
i=0;
//parse string
i = input.indexOf(" ",0);
str = input.substring(0,i); //number of states
numStates = Integer.parseInt(str); //convert to int
for(int k = 0; k< numStates; k++){
g.addVertex("q"+k);
}
i++;
j = i;
i=input.indexOf(" ",j);
str = input.substring(j,i); //number of symbols
numSymbols = Integer.parseInt(str);
i++;
j = i;
i=input.indexOf(" ",j);
str = input.substring(j,i); //initial state
currentState = Integer.parseInt(str);
i++;
j = i;
//read in finalStates
while(readInt!=-1){
i=input.indexOf(" ",j);
fState = input.substring(j,i); //a final state
readInt = Integer.parseInt(fState);
if(readInt!=-1){
finalStates[place] = readInt;
i++;
j = i;
place++;
}//end if
}//end while
i++;
j = i;
String sState;
String eState;
while(startState!=-1&& j<(input.length()-2)){ //until end of file
i=input.indexOf(" ",j);
sState = input.substring(j,i); //start state
startState = Integer.parseInt(sState); //convert to int
if(startState!=-1){
i++;
j = i;
String cStr = "";
tran = input.charAt(i); //transition
cStr = cStr + tran;
i = i+2;
j=i;
i=input.indexOf(" ",j);
eState = input.substring(j,i); //end state
endState = Integer.parseInt(eState);
i++;
j=i;
String one = "q"+startState;
String two = "q"+endState;
System.out.println(one+ two +" "+cStr);
g.addEdge(one, two, cStr);
//drawEdge(one, two, cStr);
}//end if
}//end while
}
public static void drawEdge(String v, String v1, String label){
System.out.println(v +" "+v1+ " "+label);
g.addEdge(v,v1,label);
}
private void adjustDisplaySettings(JGraph jg)
{
jg.setPreferredSize(DEFAULT_SIZE);
Color c = DEFAULT_BG_COLOR;
String colorStr = null;
try {
colorStr = getParameter("bgcolor");
} catch (Exception e) {
}
if (colorStr != null) {
c = Color.decode(colorStr);
}
jg.setBackground(c);
}
#SuppressWarnings("unchecked") // FIXME hb 28-nov-05: See FIXME below
private void positionVertexAt(Object vertex, int x, int y)
{
DefaultGraphCell cell = jgAdapter.getVertexCell(vertex);
AttributeMap attr = cell.getAttributes();
Rectangle2D bounds = GraphConstants.getBounds(attr);
Rectangle2D newBounds =
new Rectangle2D.Double(
x,
y,
bounds.getWidth(),
bounds.getHeight());
GraphConstants.setBounds(attr, newBounds);
// TODO: Clean up generics once JGraph goes generic
AttributeMap cellAttr = new AttributeMap();
cellAttr.put(cell, attr);
jgAdapter.edit(cellAttr, null, null, null);
}
//~ Inner Classes ----------------------------------------------------------
/**
* a listenable directed multigraph that allows loops and parallel edges.
// */
private static class ListenableDirectedMultigraph<V, E>
extends DefaultListenableGraph<V, E>
implements DirectedGraph<V, E>
{
private static final long serialVersionUID = 1L;
ListenableDirectedMultigraph(Class<E> edgeClass)
{
super(new DirectedMultigraph<V, E>(edgeClass));
}
}
}
If you want to use a graph that allows loops you have to create an abstract class "AbstractBaseGraph". For this reason you have to create another class that extends your super class. Here's an example.
public class MiGrafo
extends AbstractBaseGraph<String, DefaultEdge>
implements DirectedGraph<String, DefaultEdge> {
public MiGrafo() {// EdgeFactory<String, DefaultEdge> arg0, boolean arg1,boolean arg2
super(new ClassBasedEdgeFactory<String, DefaultEdge>(
DefaultEdge.class),
true,
true);
// TODO Auto-generated constructor stub
}
}
In addition you have to implement a directed or undirected graph follow of your extends.
When you create the new graph that allows using loops you only have to write this sentence:
MiGrafo h = new MiGrafo();
Finally you only have to use the graph like a simple graph.
See you.
Related
I get a nullPointerException in my program when I try to call a boolean array in a method parameter. The boolean array is created as a constant, and then initialized in a separate void method. Can someone explain to me why it can't find the boolean array (or can't find the array values)?
public static void moveTarget(Graphics g) {
if (!targetMovement)
return;
drawTarget(g, BACKGROUND_COLOR);
drawShield(g, BACKGROUND_COLOR);
This line right here is the specific part where the program fails. (nullPointerException)
int f = findTargetMissilePosition(targetMissileActive);
I specify the constants here, but do not initialize.
// Target Missile values
public static Color TARGET_MISSILE_COLOR = TARGET_COLOR;
public static int MAX_MISSILES = 10;
public static double TARGET_MISSILE_SPEED = MISSILE_SPEED;
public static double TARGET_SHOOT_PROBABILITY = .1;
public static double[] targetMissilePositionX;
public static double[] targetMissilePositionY;
public static double[] targetMissileDeltaX;
public static double[] targetMissileDeltaY;
public static boolean[] targetMissileActive;
// main method does initialization and calls startGrame
public static void main(String[] args) {
DrawingPanel panel = new DrawingPanel(PANEL_WIDTH, PANEL_HEIGHT);
Graphics g = panel.getGraphics( );
initialize();
startGame(panel, g);
}
//initialize() is called above which is where the arrays are intialized
// start the main game loop which runs forever
public static void startGame(DrawingPanel panel, Graphics g) {
while(true) {
panel.sleep(SLEEP_TIME);
handleKeys(panel,g);
moveTarget(g);
drawAll(g);
moveMissile(g);
shootTargetMissile(g);
for (int i=0;i<10;i++) {
int f = findTargetMissilePosition(targetMissileActive);
moveTargetMissile(g, f);
}
shieldHitTimer--;
targetHitTimer--;
shooterHitTimer--;
}
}
// above is the first time that line of code appears and does not appear to have an issue.
// reset all parameters to start over
public static void reset(Graphics g) {
g.setColor(BACKGROUND_COLOR);
g.fillRect(0,0,PANEL_WIDTH,PANEL_HEIGHT);
initialize();
}
//Here the arrays are initialized
// initialize parameters for the start of the program
public static void initialize() {
shooterPositionX = SHOOTER_INITIAL_POSITION_X;
gunAngle = 0;
targetPositionX = PANEL_WIDTH/2;
missileActive = false;
hitCount = 0;
shooterHitCount = 0;
hitDisplayString = "Hits: ";
targetDeltaX = 0;
targetHitTimer = 0;
shieldHitTimer = 0;
shooterHitTimer = 0;
boolean [] targetMissileActive = new boolean [9]; // might change??
int [] targetMissilePositionX = new int [9];
int [] targetMissilePositionY = new int [9];
int [] targetMissileDeltaX = new int [9];
int [] targetMissileDeltaY = new int [9];
for (int i=0; i<9; i++) {
targetMissilePositionX[i] = 0;
targetMissilePositionY[i] = 0;
targetMissileDeltaX[i] = 0;
targetMissileDeltaY[i] = 0;
targetMissileActive[i] = false;
}
}
// draw everything in its current position
public static void drawAll(Graphics g) {
g.setColor(Color.BLACK);
g.drawString("Project 3 by Benjamin Koch",10,15);
g.drawString(hitDisplayString,10,30);
int f = findTargetMissilePosition(targetMissileActive);
drawTargetMissile(g, TARGET_MISSILE_COLOR, f);
drawShooter(g,SHOOTER_COLOR);
if (targetHitTimer > 0)
drawTarget(g, SHIELD_HIT_COLOR);
else
drawTarget(g,TARGET_COLOR);
Color shieldColor = BACKGROUND_COLOR; // default: do not draw
if (shieldActive) {
if (shieldHitTimer > 0)
shieldColor = SHIELD_HIT_COLOR;
else
shieldColor = SHIELD_COLOR;
}
drawShield(g, shieldColor);
}
public static int findTargetMissilePosition (boolean[] data) {
for (int i=0;i<MAX_MISSILES;i++) {
if (data[i]==false) {
return i;
}
}
return -1;
}
Inside your initialize() function, you're creating local variables but not initializing the global ones.
targetMissileActive = new boolean [9];
targetMissilePositionX = new int [9];
targetMissilePositionY = new int [9];
targetMissileDeltaX = new int [9];
targetMissileDeltaY = new int [9];
for (int i=0; i<9; i++) {
targetMissilePositionX[i] = 0;
targetMissilePositionY[i] = 0;
targetMissileDeltaX[i] = 0;
targetMissileDeltaY[i] = 0;
targetMissileActive[i] = false;
}
This will reference the variables to the global one.
I want to pass 4 arrays from a method which is in A class, to a method in B class.
I create an instance of class A in the method which is in class B to get the arrays.
The method in A class is defined as Object[] and I use:
return new Object[]{Array1,Array2,Array3,Array4};
to return the arrays.
In method of B class I get the arrays with an object defined as:
private Object outGeoObj[] = new Object[4];
I am retrieving successfully the arrays, but I want to clear the object before I use it again. I tried:
public void ClearValues(){
if (outGeoObj != null){
outGeoObj = null;
}
else{
System.out.println("Object is null");
}
}
but it doesn't work. Any suggestions?
Minimal Working Example:
Class B:
public class MainFem {
private OutGeoMesh outmesh;
private Object outGeoObj[] = new Object[4]; // [0: Xmpoint, 1: Ympoint, 2: Vec, 3: numpoints]
public MainFem() {
outmesh = new OutGeoMesh();
}
public void ClearValues(){
if (outGeoObj != null){
for(int i = 0; i < outGeoObj.length; i++) {
outGeoObj[i] = null;
}
}
else{
System.out.println("Object is null");
}
} // END Method ClearValues
public void MainStart(int Xpoint[][], int Ypoint[][], int nump[], int c2, int Line[][][], DrawPanel drawPanel){
outGeoObj = outmesh.createOutGeomesh(Xpoint, Ypoint, nump, c2, Line, drawPanel);
int temp = (int[][]) outGeoObj[3];
System.out.println(temp[0][0]);
}// End Method MainStart
} // END CLASS MainFem
Class A:
public class OutGeoMesh {
private double Xmpoint[][][] = new double[500][200][20];
private double Ympoint[][][] = new double[500][200][20];
private double Vec[][][] = new double[500][2][20];
private int numpoints[][] = new int[500][20];
public OutGeoMesh() {
// TODO Auto-generated constructor stub
}
public Object[] createOutGeomesh(int Xpoint[][], int Ypoint[][], int nump[], int c2, int Line[][][], DrawPanel drawPanel) {
for (int j = 0; j <= c2; j++) {
for (int i = 0; i < nump[j]; i++) {
Vec[i][0][j] = i;
Vec[i][1][j] = i+1;
Xmpoint[i][0][j] = Xpoint[i][j];
Ympoint[i][1][j] = Ypoint[i][j];
numpoints[i][j] = numpoints[i][j] + 1;
} // END FOR i
} // END FOR j
return new Object[]{Xmpoint,Ympoint,Vec,numpoints};
} // END METHOD createOutGeomesh
// ---------------------------------
} // END CLASS OutGeoMesh
You need to do something like this:
Arrays.fill(outGeoObj, null);
The reason that your code doesn't work is because you are only erasing your reference to the array, but other parts of your code are still using that same array. By using Arrays.fill you can erase the contents of the array.
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.
I have an object and client class created which prints coordinates in order of their distance from the origin. The client class asks the user how many dimensions they want the array to have (x,y or x,y,z) how many points they want generated, and a range from which each coordinate will run from (ex. -x to x, -y to y etc.). When I run the program it prints out the correct number of points, but there is always one extra element in the array (etc. when user enters dimension of array as '4', it always prints out one extra element -> [4, 5, 9, 6, 1]). Why is this happening?
Client Class
import java.io.*;
public class MA {
public MA() { }
public static void main(String args[]) throws IOException {
String myString = "arrayNumPoints.txt";
int numpoints = 0;
int dimension = 0;
double lengthscale = 0;
double [][] points = new double[numpoints][dimension + 1];
BufferedReader myInput = new BufferedReader(new InputStreamReader(System.in));
MB pointsB = new MB();
System.out.println("Enter number of points:");
String numpointsA = myInput.readLine();
numpoints = Integer.parseInt(numpointsA);
pointsB.setnumpoints(numpoints);
System.out.println("Enter the dimension:");
String dimensionA = myInput.readLine();
dimension = Integer.parseInt(dimensionA);
pointsB.setdim(dimension);
System.out.println("Enter length(range):");
String lengthscaleA = myInput.readLine();
lengthscale = Double.parseDouble(lengthscaleA);
pointsB.setlengthscale(lengthscale);
pointsB = new MB(numpoints, lengthscale, dimension, points);
pointsB.fillarray(pointsB.getarray(), pointsB.getlengthscale(), pointsB.getdim(), pointsB.getnumpoints());
pointsB.caldistance(pointsB.getarray(), pointsB.getnumpoints(), pointsB.getdim());
pointsB.sort(pointsB.getarray(), 0, pointsB.getnumpoints()-1, pointsB.getdim());
pointsB.writefile(pointsB.getarray(), pointsB.getnumpoints(), myString);
pointsB.readfile(myString);
}
}
Object Class
import java.io.*;
import java.util.Arrays;
public class MB {
//variables and arrays are declared
private double lengthscale;
private int numpoints;
private int dimension;
private double [][] points;
//constructor
public MB() { }
//constructor
public MB(double [][] points) {
numpoints = 0;
lengthscale = 0;
dimension = 0;
points = new double[numpoints][dimension + 1];
}
//constructor
public MB(int mynumpoints, double mylengthscale, int mydimension, double [][] mypoints) {
numpoints = mynumpoints;
lengthscale = mylengthscale;
dimension = mydimension;
points = new double[numpoints][dimension + 1];
}
//numpoints getter
public int getnumpoints()
{
return numpoints;
}
//numpoints setter
public void setnumpoints(int mynumpoints) {
numpoints = mynumpoints;
}
//lengthscale getter
public double getlengthscale() {
return lengthscale;
}
//lengthscale setter
public void setlengthscale(double mylengthscale) {
lengthscale = mylengthscale;
}
//dimension getter
public int getdim() {
return dimension;
}
//dimension setter
public void setdim(int mydimension) {
dimension = mydimension;
}
//array getter
public double[][] getarray() {
return points;
}
//array setter
public void setarray(double [][]mypoints, int numpoints, int dimension) {
points[numpoints][dimension] = mypoints[numpoints][dimension];
}
//fill array method
public void fillarray(double [][]mypoints, double mylengthscale, int mydimension, int mynumpoints) throws IOException {
for(int x = 0; x < mynumpoints; x++)
{
for(int y = 0; y < mydimension; y++) {
//fills array with random points within the specified range
mypoints[x][y] = (dimension * Math.random() - 1) * mylengthscale;
}//end for
}//end for
}
//writefile method
public void writefile(double [][]mypoints, int mynumpoints, String myString) throws IOException {
//writes to myString
PrintWriter fileOut = new PrintWriter(new FileWriter(myString));
//for loop runs for length of mylengthscale
for(int m = 0; m < mynumpoints; m++) {
//prints points to file
fileOut.println(Arrays.toString(mypoints[m]));
}
//close file
fileOut.close();
//end for
}
//readfile metod
public void readfile(String myString) throws IOException
{
String filePath = myString;
//reads data from mString
BufferedReader in = new BufferedReader(new FileReader(new File(myString)));
String line = null;
while(( (line = in.readLine()) != null))
System.out.println(line);
in.close();
}
//caldistance method
public void caldistance(double [][]mypoints, int mynumpoints, int mydimension) {
//for loop; calculates distance for specified number of points
for(int i = 0; i < mynumpoints; i++) {
for(int k = 0; k < mydimension; k++) {
mypoints[i][mydimension] = mypoints[i][k] * mypoints[i][k];
}//end for loop
mypoints[i][mydimension] = Math.sqrt(mypoints[i][mydimension]);
}//end for loop
}
//sort method
public double[][] sort(double[][] mynewpoints, int down, int top, int mydimension) {
System.arraycopy(mynewpoints, 0, mynewpoints, 0, mynewpoints.length);
//variables are declared
int d = down;
int u = top;
//determines pivot point
double [] pivot = mynewpoints[(down + top)/2];
//sorts the values of the array, comparing it to the pivot
do {
while (mynewpoints[d][mydimension] < pivot[mydimension]) {
d++;
}
while (mynewpoints[u][mydimension] > pivot[mydimension]) {
u--;
}
if (d <= u) {
double[] temporary = new double[mynewpoints[d].length];
//compres values in array and switches them
for (int y = 0; y < mynewpoints[d].length; y++) {
temporary[y] = mynewpoints[d][y];
mynewpoints[d][y] = mynewpoints[u][y];
mynewpoints[u][y] = temporary[y];
}
d++;
u--;
}
} while (d <= u);
if (down < u) {
mynewpoints = sort(mynewpoints, mydimension, down, u);
}
if (d < top) {
mynewpoints = sort(mynewpoints, mydimension, d, top);
}
return mynewpoints;
}
}
You should be more specific (show us the code fragments, which you use and which go wrong).
However do you realize, that in your MB constructor :
//constructor
public MB(double [][] points) {
numpoints = 0;
lengthscale = 0;
dimension = 0;
points = new double[numpoints][dimension + 1];
}
The last line is not doing anything? You have to write it like this :
this.points = new double[numpoints][dimension + 1];
Because you have two variables points, one is class variable, second is passed as parameter. If this happens, without using this the non-class variable is chosen.
Probably because you're adding 1 to the dimension given by the user:
points = new double[numpoints][dimension + 1];
This results in the array having one more column than value of dimension.
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]);
}
}
}`}