private void checkExcepction(Collection<Vertex> v, Collection<Edge> e) { for (Edge edge : e) { // No edge from or to vertex labeled A if there is no vertex with // label A if (!v.contains(edge.getSource()) || !v.contains(edge.getDestination())) { throw new IllegalArgumentException(); } // Edge weights should not be negative if (edge.getWeight() < 0) { throw new IllegalArgumentException(); } // Collection of edges should not has the same directed edge more // than once // with a different weight for (Edge checkEdges : e) { if (checkEdges.getSource().equals(edge.getSource()) && checkEdges.getDestination().equals(edge.getDestination()) && checkEdges.getWeight() != edge.getWeight()) { throw new IllegalArgumentException(); } } } }
/** * Test whether vertex b is adjacent to vertex a (i.e. a -> b) in a directed graph. Assumes that * we do not have negative cost edges in the graph. * * @param a one vertex * @param b another vertex * @return cost of edge if there is a directed edge from a to b in the graph, return -1 otherwise. * @throws IllegalArgumentException if a or b do not exist. */ @Override public int edgeCost(Vertex a, Vertex b) { if (a == null || b == null || !totalVertices.contains(a) || !totalVertices.contains(b)) { throw new IllegalArgumentException(); } for (Edge edge : adj.get(a)) { if (edge.getDestination().equals(b)) { return edge.getWeight(); } } return -1; }
/* * Methode to calculate a weight for a way to the start point , it can be * one edge or a couple of edges */ private static int calculateWeightOfWay(Vertex firstVertex, Vertex secondVertex) { int currentWeight = (Integer) verticesMap.get(firstVertex.getId()).get(1); ArrayList<Edge<Vertex>> edgesOfFirstVertex = (ArrayList<Edge<Vertex>>) graph.getIncidentEdges(firstVertex.getId()); for (Edge<Vertex> e : edgesOfFirstVertex) { if (e.getVertexB().getId() == secondVertex.getId()) { int edgeWeightBetweenFirstandSecond = e.getWeight(); return edgeWeightBetweenFirstandSecond + currentWeight; } } System.out.println("no edge weight found"); return 0; }
/** * performs the Dijkstra algorithm * * @param graph a graph, in which the Dijkstra will be performed * @param queue a queue of vertices to help perform Dijkstra * @param startVertexID a start vertices id * @param destinationVertexID an end vertices id */ private static void performeDijkstra( Graph<Vertex, Edge<Vertex>> graph, ArrayList<Vertex> queue, int startVertexID, int destinationVertexID) { while (queue.size() != 0) { int lowest = 0; for (int i = 0; i < queue.size(); i++) { if (queue.get(i).getDistance() < queue.get(lowest).getDistance()) { lowest = i; } } Vertex lowestElementInQueue = queue.get(lowest); // stop the loop if the destination is reached if (lowestElementInQueue.getId() == destinationVertexID) break; queue.remove(lowestElementInQueue); Collection<Edge<Vertex>> edgesOfFirstVertex = graph.getIncidentEdges(lowestElementInQueue); if (edgesOfFirstVertex.size() != 0) { for (Edge<Vertex> edge : edgesOfFirstVertex) { Vertex neighbour = edge.getVertexB(); int weightOfEdge = edge.getWeight(); if (weightOfEdge < 0) { throw new IllegalArgumentException( "one edge of " + lowestElementInQueue.getId() + " is negative"); } relax(lowestElementInQueue, neighbour, weightOfEdge); } } } ResultsDisplay.printResults(graph); ResultsDisplay.printTheShortestWay(graph, startVertexID, destinationVertexID); }
/** * Returns the shortest path from a to b in the graph, or null if there is no such path. Assumes * all edge weights are nonnegative. Uses Dijkstra's algorithm. * * @param a the starting vertex * @param b the destination vertex * @return a Path where the vertices indicate the path from a to b in order and contains a (first) * and b (last) and the cost is the cost of the path. Returns null if b is not reachable from * a. * @throws IllegalArgumentException if a or b does not exist. */ public Path shortestPath(Vertex a, Vertex b) { List<Vertex> vertexList = new ArrayList<Vertex>(); VertexComparator vcp = new VertexComparator(); PriorityQueue<Vertex> vertexQueue = new PriorityQueue<Vertex>(10, vcp); // queue for unknow vertex // If the start and end vertex are equal // return a path containing one vertex and a cost of 0. if (a.equals(b)) { vertexList.add(a); return new Path(vertexList, 0); } // if the start and end vertex are not equal: // if there is no path starting from a, return null if (!adj.containsKey(a)) { return null; } // for (Vertex v : this.vertices() ) { // System.out.println(v.known); // } // initialize before searching path for (Vertex v : adj.keySet()) { // variables in adj.keySet() are actually pointers pointing to different memory with those in // this.vertices() // what we need is actually to change those in memory pointed by this.vertices() // have no idea why this.vertices.get() method did not work // thus I have to implement as below Vertex vn = v; // actually this is a bad initialization for (Vertex vi : this.vertices()) { if (vi.equals(v)) { vn = vi; } } vn.known = false; // set all vertex distance to infinity vn.distance = Integer.MAX_VALUE; // vn.distance = 99999; vertexQueue.add(vn); } // System.exit(1); // Set source vertex distance to 0 for (Vertex vn : this.vertices()) { if (vn.equals(a)) { vertexQueue.remove(vn); vn.distance = 0; vn.previous = vn; // update vn in vertexQueue vertexQueue.add(vn); } } // a.distance = 0; // a.previous = a; // vertexQueue.remove(a); // vertexList.add(a); Vertex end = b; for (Vertex vn : this.vertices()) { if (vn.equals(b)) { end = vn; } } // for (Vertex v : this.vertices() ) { // System.out.println(v.distance); // } System.out.println("start searching..."); // while ( (!vertexQueue.isEmpty()) && (end.known == false) ) { //while there are still unknow // vertex and vertex b is unknown while ((!vertexQueue .isEmpty())) { // while there are still unknow vertex and vertex b is unknown // System.out.println("elements in vertexQueue at beginning:"); // for (Vertex v : vertexQueue ) { // System.out.println(v.getLabel()); // System.out.println("distance: " + v.distance); // } Vertex nt = vertexQueue.poll(); // unknown node with smallest distance // System.out.println("marked " + nt + " as known."); // System.out.println("its current distance: " + nt.distance); nt.known = true; for (Edge e : adj.get(nt)) { // search for vertex with the same name as e.getDestination() in this.vertices() Vertex en = e.getDestination(); for (Vertex vn : this.vertices()) { if (vn.equals(e.getDestination())) { en = vn; } } if (!en.known) { if ((nt.distance + e.getWeight()) < en.distance) { // update en in vertexQueue vertexQueue.remove(en); en.distance = nt.distance + e.getWeight(); en.previous = nt; vertexQueue.add(en); } } } } System.out.println("finished computing shortest path."); // for (Vertex v : this.vertices() ) { // System.out.println(v.distance); // } // traverse to get path from a to b Vertex tmp = end; while (!tmp.equals(a)) { vertexList.add(0, tmp); // may need a heap here? tmp = tmp.previous; } vertexList.add(0, a); return new Path(vertexList, end.distance); // TODO: after searching for all possible path, return null if there is no path from a to b }