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;
|
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 class DijkstraAlgorithm extends ShortestPathAlgorithm {
|
||||||
|
|
||||||
public DijkstraAlgorithm(ShortestPathData data) {
|
public DijkstraAlgorithm(ShortestPathData data) {
|
||||||
|
@ -8,10 +21,77 @@ public class DijkstraAlgorithm extends ShortestPathAlgorithm {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ShortestPathSolution doRun() {
|
protected ShortestPathSolution doRun() {
|
||||||
|
// Retreive the graph
|
||||||
final ShortestPathData data = getInputData();
|
final ShortestPathData data = getInputData();
|
||||||
ShortestPathSolution solution = null;
|
Graph graph = data.getGraph();
|
||||||
// TODO:
|
|
||||||
return solution;
|
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