BE-Graphe/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/DijkstraAlgorithm.java

112 wiersze
3,8 KiB
Java

package org.insa.graphs.algorithm.shortestpath;
import java.util.ArrayList;
import java.util.Collections;
import org.insa.graphs.algorithm.AbstractSolution.Status;
import org.insa.graphs.algorithm.utils.BinaryHeap;
import org.insa.graphs.model.Arc;
import org.insa.graphs.model.Graph;
import org.insa.graphs.model.Node;
import org.insa.graphs.model.Path;
public class DijkstraAlgorithm extends ShortestPathAlgorithm {
public DijkstraAlgorithm(ShortestPathData data) {
super(data);
}
@Override
protected ShortestPathSolution doRun() {
final ShortestPathData data = getInputData();
ShortestPathSolution solution = null;
// accès au graphe
Graph graph = data.getGraph();
int nbNodes = graph.size();
// Tableau des labels pour chaque sommet
Label[] labels = new Label[nbNodes];
// Tableau des arcs prédécesseurs pour reconstruire le chemin
Arc[] predecessorArcs = new Arc[nbNodes];
// Initialisation des labels
for (Node node : graph.getNodes()) {
labels[node.getId()] =
new Label(node, false, Double.POSITIVE_INFINITY, null);
}
// Origine : coût 0, non marqué, pas de père
labels[data.getOrigin().getId()].setCoutRealise(0);
BinaryHeap<Label> heap = new BinaryHeap<>();
heap.insert(labels[data.getOrigin().getId()]);
notifyOriginProcessed(data.getOrigin());
while (!heap.isEmpty()) {
Label LabelActuel = heap.deleteMin();
Node NodeActuel = LabelActuel.getSommetCourant();
// sommet traité
LabelActuel.setMarque(true);
// On a atteint la destination on s'arrête
if (NodeActuel.equals(data.getDestination())) {
notifyDestinationReached(NodeActuel);
break;
}
// Pour chaque successeur
for (Arc arc : NodeActuel.getSuccessors()) {
if (!data.isAllowed(arc))
continue; // ici c'est pour l'amélioration voiture ou a pied
Node succ = arc.getDestination();
Label succLabel = labels[succ.getId()];
if (succLabel.getMarque())
continue; // déjà traité
double newCost = LabelActuel.getCoutRealise() + data.getCost(arc);
if (newCost < succLabel.getCoutRealise()) {
// Mise à jour du coût et du prédécesseur
// Si le sommet a déjà un label dans le tas, on le retire
// avant de le mettre à jour
if (succLabel.getCoutRealise() != Double.POSITIVE_INFINITY) {
heap.remove(succLabel);
}
succLabel.setCoutRealise(newCost);
succLabel.setPere(arc);
predecessorArcs[succ.getId()] = arc;
// Insertion dans le tas car on est sûr qu'il n'est pas
heap.insert(succLabel);
notifyNodeReached(succ);
}
}
}
// Construction de la solution
if (predecessorArcs[data.getDestination().getId()] == null) {
solution = new ShortestPathSolution(data, Status.INFEASIBLE);
}
else {
// Reconstruire le chemin
ArrayList<Arc> arcs = new ArrayList<>();
Arc arc = predecessorArcs[data.getDestination().getId()];
while (arc != null) {
arcs.add(arc);
arc = predecessorArcs[arc.getOrigin().getId()];
}
Collections.reverse(arcs);// on inverse le chemin
solution = new ShortestPathSolution(data, Status.OPTIMAL,new Path(graph, arcs));
}
return solution;
}
}