Dijkstra implementation

This commit is contained in:
Yohan Simard 2020-04-03 12:52:55 +02:00
parent 8f74486264
commit f79d9148c0
2 changed files with 164 additions and 3 deletions

View file

@ -1,5 +1,18 @@
package org.insa.graphs.algorithm.shortestpath;
import org.insa.graphs.algorithm.AbstractSolution;
import org.insa.graphs.algorithm.utils.BinaryHeap;
import org.insa.graphs.algorithm.utils.ElementNotFoundException;
import org.insa.graphs.algorithm.utils.PriorityQueue;
import org.insa.graphs.model.Arc;
import org.insa.graphs.model.Graph;
import org.insa.graphs.model.Node;
import org.insa.graphs.model.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class DijkstraAlgorithm extends ShortestPathAlgorithm {
public DijkstraAlgorithm(ShortestPathData data) {
@ -8,10 +21,77 @@ public class DijkstraAlgorithm extends ShortestPathAlgorithm {
@Override
protected ShortestPathSolution doRun() {
// Retreive the graph
final ShortestPathData data = getInputData();
ShortestPathSolution solution = null;
// TODO:
return solution;
Graph graph = data.getGraph();
final int nbNodes = graph.size();
// Construct a binary heap for Label (comparison is based on their cost)
PriorityQueue<Label> heap = new BinaryHeap<>();
// Generate the labels associated with all the nodes of the graph
List<Label> labels = Label.generateLabels(graph);
// Initialize labels and heap with the origin node, then notify observers
Node origin = data.getOrigin();
int originId = origin.getId();
labels.get(originId).mark();
labels.get(originId).updateCost(0, null);
heap.insert(labels.get(originId));
notifyOriginProcessed(data.getOrigin());
while (!heap.isEmpty()) {
// Get the node with the minimum cost
Label currentLabel = heap.deleteMin();
currentLabel.mark();
Node currentNode = currentLabel.getNode();
for (Arc arc : currentNode.getSuccessors()) {
Node dest = arc.getDestination();
Label destLabel = labels.get(dest.getId());
if (data.isAllowed(arc) && !destLabel.isMarked()) {
// Compute the cost to dest through currentNode, and compare it to the current one
double arcCost = data.getCost(arc);
double newCost = currentLabel.getCost() + arcCost;
double oldCost = destLabel.getCost();
if (newCost < oldCost) {
try {
heap.remove(destLabel);
} catch (ElementNotFoundException ignored) {
}
destLabel.updateCost(newCost, arc);
heap.insert(destLabel);
if (Double.isInfinite(oldCost))
notifyNodeReached(dest);
}
}
}
}
Node destination = data.getDestination();
Label destinationLabel = labels.get(destination.getId());
// If path not found
if (Double.isInfinite(destinationLabel.getCost())) {
return new ShortestPathSolution(data, AbstractSolution.Status.INFEASIBLE);
}
// The destination has been found, notify the observers.
notifyDestinationReached(destination);
List<Arc> path = new ArrayList<>();
Label currentLabel = labels.get(destination.getId());
while (!currentLabel.getNode().equals(origin)) {
Arc arc = currentLabel.getParent();
path.add(arc);
currentLabel = labels.get(arc.getOrigin().getId());
}
Collections.reverse(path);
return new ShortestPathSolution(data, AbstractSolution.Status.OPTIMAL, new Path(graph, path));
}
}

View file

@ -0,0 +1,81 @@
package org.insa.graphs.algorithm.shortestpath;
import org.insa.graphs.model.Arc;
import org.insa.graphs.model.Graph;
import org.insa.graphs.model.Node;
import java.util.ArrayList;
import java.util.List;
public class Label implements Comparable<Label> {
private Node node;
private boolean marked;
private double cost;
private Arc parent;
/**
* Initalizes a Label (not yet marked, with infinite cost)
*
* @param node The node associated with the label
*/
public Label(Node node) {
this.node = node;
marked = false;
cost = Double.POSITIVE_INFINITY;
parent = null;
}
/**
* Generates a list of labels associated with a graph
*
* @param graph the graph used to construct the labels
* @return A list of labels in the same order as graph.getNodes()
*/
public static List<Label> generateLabels(Graph graph) {
List<Node> nodes = graph.getNodes();
List<Label> labels = new ArrayList<>();
for (Node node : nodes) {
labels.add(new Label(node));
}
return labels;
}
/**
* Marks a Label
*/
public void mark() {
marked = true;
}
/**
* Updates cost and parent
*
* @param pathCost the cost of the current path to the node
* @param predecessor the previous node in the current path
*/
public void updateCost(double pathCost, Arc predecessor) {
cost = pathCost;
parent = predecessor;
}
public Node getNode() {
return node;
}
public boolean isMarked() {
return marked;
}
public double getCost() {
return cost;
}
public Arc getParent() {
return parent;
}
@Override
public int compareTo(Label o) {
return Double.compare(cost, o.cost);
}
}