Thursday, August 10, 2017

Graph and Dijkstra infinite loop?

Leave a Comment

So I creating a minecraft plugin where I am in need of a graph to create a navigation system. I researched a bit and found out that I should be able to use Dijkstra, but I have a problem. When searching for the shortest path I am sometimes getting an infinite loop(not always, it usally works the first 2-3 runs but after that it goes into the loop).

When the player wants to get to a destination I search for the closest vertex and use computePaths with that vertex as parameter. When I then run the getShortestPathTo it sometimes gets stuck in an infinite loop and I run out of memory(which makes sence since im adding the same vertexes to the list). Can you see why it is getting stuck? As far as I knew Dijkstra should be able to handle going from A node to B node and from B node to A node right?

Below is my code:

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 List<Vertex> getShortestPathTo(Vertex target) {     List<Vertex> path = new ArrayList<Vertex>();     for (Vertex vertex = target; vertex != null; vertex = vertex.previous) {         path.add(vertex);     }     Collections.reverse(path);     return path; } } 

and the vertex class:

public class Vertex implements Comparable<Vertex> {     public final String name;     public Edge[] adjacencies;     public double minDistance = Double.POSITIVE_INFINITY;     public Vertex previous;     public Location location;     public Vertex(String argName) { name = argName; }     public Vertex(String argName,Location l) { name = argName; location = l;}     public String toString() { return name; }     public int compareTo(Vertex other)     {         return Double.compare(minDistance, other.minDistance);     }  } 

When first the plugin is enabled I load all the vertexes from a config file looking something like this(It is the test one i am using)

Config file

I am adding vertexes and edges here(not sure if relevent but thought it might be?):

public void loadAllVertex() {     ConfigurationSection section = nodeConfig.config.getConfigurationSection("nodes");     for (String key: section.getKeys(false)) {         String locationString = nodeConfig.getString("nodes." + key + ".location");         if (locationString == null)             return;         String[] locationSplit = locationString.split(",");         if (locationSplit.length <=1) {             log.log(Level.SEVERE, "Location is not specified correctly in nodes.yml");             return;         }         Location l = new Location(Bukkit.getWorlds().get(0),Integer.parseInt(locationSplit[0]),Integer.parseInt(locationSplit[1]),Integer.parseInt(locationSplit[2]));         Vertex tmpVertex = new Vertex(key, l);         allNodes.add(tmpVertex);      }      for (Vertex v : allNodes) {         String path = "nodes." + v.name + ".connectedTo";         List<String> connectedTo = nodeConfig.getStringList(path,true);         List<Edge> edges = new ArrayList<>();          for (String sideNodeName : connectedTo) {             Vertex vertexCon = GraphUtils.getVertexByName(allNodes, sideNodeName);             if (vertexCon == null) {                 log.warning("The '" + sideNodeName + "' node is not defined");                 return;             }             //A.adjacencies = new Edge[]{ new Edge(M, 8) };             edges.add(new Edge(vertexCon,vertexCon.location.distance(v.location)));         }         Edge[] arrayEdges = new Edge[edges.size()];         arrayEdges = edges.toArray(arrayEdges);         v.adjacencies = arrayEdges;     }  } 

1 Answers

Answers 1

Think i found the error, so I never had any loops the first time I ran the compute path and findshortestpath so I finally figured out that I could not be resetting things correctly(should have been obvious I know) - I didn't update the vertexes afterwards. So I added a method to reset the mindistance and previous attributes and this seems to have done the trick.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment