Dijkstra implementation
This commit is contained in:
parent
8f74486264
commit
f79d9148c0
2 changed files with 164 additions and 3 deletions
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue