perf(dijkstra): create labels dynamically

This commit is contained in:
Paul Alnet 2024-05-25 21:20:03 +02:00
parent 8fa1d62d02
commit a5b553e712

View file

@ -12,6 +12,8 @@ import org.insa.graphs.model.Path;
public class DijkstraAlgorithm extends ShortestPathAlgorithm { public class DijkstraAlgorithm extends ShortestPathAlgorithm {
Label[] labels;
public DijkstraAlgorithm(ShortestPathData data) { public DijkstraAlgorithm(ShortestPathData data) {
super(data); super(data);
} }
@ -20,6 +22,12 @@ public class DijkstraAlgorithm extends ShortestPathAlgorithm {
return new Label(node); return new Label(node);
} }
protected Label getLabel(Node node) {
if (labels[node.getId()] == null)
labels[node.getId()] = createLabel(node);
return labels[node.getId()];
}
@Override @Override
protected ShortestPathSolution doRun() { protected ShortestPathSolution doRun() {
@ -31,7 +39,7 @@ public class DijkstraAlgorithm extends ShortestPathAlgorithm {
final int nbNodes = graph.size(); final int nbNodes = graph.size();
// List of sommets, but with type Label // List of sommets, but with type Label
ArrayList<Label> labels = new ArrayList<Label>(nbNodes); labels = new Label[nbNodes];
// Heap of sommets // Heap of sommets
BinaryHeap<Label> tas = new BinaryHeap<Label>(); BinaryHeap<Label> tas = new BinaryHeap<Label>();
@ -39,25 +47,21 @@ public class DijkstraAlgorithm extends ShortestPathAlgorithm {
// Notify observers about the first event (origin processed). // Notify observers about the first event (origin processed).
notifyOriginProcessed(data.getOrigin()); notifyOriginProcessed(data.getOrigin());
// Init Dijkstra // Init Dijkstra : for performance reasons we create labels on the fly,
for (Node node : graph.getNodes()) { // instead of at initialization
// Luckily they are ordered by id.
// ArrayList.set only works if the value is already initialized (because why Java?)
labels.add(this.createLabel(node));
}
Label s = labels.get(data.getOrigin().getId()); final Label s = getLabel(data.getOrigin());
// Add origin in the heap // Add origin in the heap
// Label s = origin;//labels.get(0); // Label s = origin;
s.setPathCost(0); s.setPathCost(0);
tas.insert(s); tas.insert(s);
// On considère le sommet x à chaque itération // On considère le sommet x à chaque itération
Label x = s; Label x = s;
final int dest_id = data.getDestination().getId(); final Node dest = data.getDestination();
while (!tas.isEmpty() && !(labels.get(dest_id).getNode().equals(x.getNode()))) { while (!tas.isEmpty() && !(x.getNode().equals(dest))) {
x = tas.deleteMin(); x = tas.deleteMin();
x.mark(); x.mark();
notifyNodeMarked(x.getNode()); notifyNodeMarked(x.getNode());
@ -65,7 +69,7 @@ public class DijkstraAlgorithm extends ShortestPathAlgorithm {
// We create a list of node successors of x, instead of a list of Arcs. // We create a list of node successors of x, instead of a list of Arcs.
double arc_cost = 0; double arc_cost = 0;
for (Arc successorArc : x.getNode().getSuccessors()) { for (Arc successorArc : x.getNode().getSuccessors()) {
Label successor = labels.get(successorArc.getDestination().getId()); Label successor = getLabel(successorArc.getDestination());
arc_cost = Double.MAX_VALUE; arc_cost = Double.MAX_VALUE;
if (!successor.isMarked() && data.isAllowed(successorArc)) { if (!successor.isMarked() && data.isAllowed(successorArc)) {
// This loop serves to get the length of the arc as // This loop serves to get the length of the arc as
@ -101,7 +105,7 @@ public class DijkstraAlgorithm extends ShortestPathAlgorithm {
} }
} }
if (labels.get(data.getDestination().getId()).getParentArc() == null) { if (getLabel(data.getDestination()).getParentArc() == null) {
this.pathCost = 0; this.pathCost = 0;
solution = new ShortestPathSolution(data, Status.INFEASIBLE); solution = new ShortestPathSolution(data, Status.INFEASIBLE);
} }
@ -109,13 +113,13 @@ public class DijkstraAlgorithm extends ShortestPathAlgorithm {
// Create the path ... // Create the path ...
ArrayList<Arc> arcs_path = new ArrayList<>(); ArrayList<Arc> arcs_path = new ArrayList<>();
Arc arc = labels.get(data.getDestination().getId()).getParentArc(); Arc arc = getLabel(data.getDestination()).getParentArc();
// We will find the path using the parent nodes, from the destination to the // We will find the path using the parent nodes, from the destination to the
// origin // origin
while (arc != null && arc.getDestination().getId() != data.getOrigin().getId()) { while (arc != null && arc.getDestination().getId() != data.getOrigin().getId()) {
arcs_path.add(arc); arcs_path.add(arc);
arc = labels.get(arc.getOrigin().getId()).getParentArc(); arc = getLabel(arc.getOrigin()).getParentArc();
} }
notifyDestinationReached(data.getDestination()); notifyDestinationReached(data.getDestination());
@ -126,7 +130,7 @@ public class DijkstraAlgorithm extends ShortestPathAlgorithm {
// Create the final solution. // Create the final solution.
solution = new ShortestPathSolution(data, Status.OPTIMAL, new Path(graph, arcs_path)); solution = new ShortestPathSolution(data, Status.OPTIMAL, new Path(graph, arcs_path));
this.pathCost = labels.get(data.getDestination().getId()).getCost(); this.pathCost = getLabel(data.getDestination()).getCost();
} }
return solution; return solution;
} }