// License: GPL. For details, see LICENSE file. package public_transport; import java.util.Iterator; import java.util.Map; import java.util.TreeMap; import java.util.TreeSet; import java.util.Vector; public abstract class AStarAlgorithm { // The following abstract functions and subclasses must be overridden by a class using // AStarAlgorithm. public abstract static class Vertex implements Comparable<Vertex> { @Override public abstract int compareTo(Vertex v); } public abstract static class Edge { public abstract Vertex getBegin(); public abstract Vertex getEnd(); public abstract double getLength(); } public abstract Vector<Edge> getNeighbors(Vertex vertex); public abstract double estimateDistance(Vertex vertex); // end of interface to override ------------------------------------------- public AStarAlgorithm(Vertex begin, Vertex end) { this.begin = begin; this.end = end; openList = new TreeMap<>(); closedList = new TreeSet<>(); pathTail = new TreeMap<>(); } public Vertex determineCurrentStart() { Vertex minVertex = null; double minDist = 0; Iterator<Map.Entry<Vertex, Double>> iter = openList.entrySet().iterator(); while (iter.hasNext()) { Map.Entry<Vertex, Double> entry = iter.next(); double distance = entry.getValue().doubleValue() + estimateDistance(entry.getKey()); if (minVertex == null || distance < minDist) { minDist = distance; minVertex = entry.getKey(); } } if (minVertex != null) { System.out.print(openList.get(minVertex).doubleValue()); System.out.print("\t"); System.out.println(minDist); } return minVertex; } Vector<Edge> shortestPath() { // Travel through the network Vertex currentStart = begin; openList.put(currentStart, 0.0); while (currentStart != null && !currentStart.equals(end)) { double startDistance = openList.get(currentStart).doubleValue(); // Mark currentStart as visited. openList.remove(currentStart); closedList.add(currentStart); Iterator<Edge> neighbors = getNeighbors(currentStart).iterator(); while (neighbors.hasNext()) { Edge edge = neighbors.next(); // Don't walk back. if (closedList.contains(edge.getEnd())) continue; // Update entry in openList Double knownDistance = openList.get(edge.getEnd()); double distance = startDistance + edge.getLength(); if (knownDistance == null || distance < knownDistance.doubleValue()) { openList.put(edge.getEnd(), distance); pathTail.put(edge.getEnd(), edge); } } currentStart = determineCurrentStart(); } if (currentStart == null) return null; // Reconstruct the found path Vector<Edge> backwards = new Vector<>(); Vertex currentEnd = end; while (!currentEnd.equals(begin)) { backwards.add(pathTail.get(currentEnd)); currentEnd = pathTail.get(currentEnd).getBegin(); } Vector<Edge> result = new Vector<>(); for (int i = backwards.size() - 1; i >= 0; --i) { result.add(backwards.elementAt(i)); } return result; } protected Vertex begin; protected Vertex end; private TreeSet<Vertex> closedList; private TreeMap<Vertex, Double> openList; private TreeMap<Vertex, Edge> pathTail; }