112 wiersze
3,8 KiB
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;
|
|
}
|
|
|
|
}
|