amélioration: Meilleur héritage de AStar et Dijkstra
This commit is contained in:
parent
5a9e842f39
commit
b81286e6ba
2 changed files with 53 additions and 85 deletions
|
|
@ -14,46 +14,27 @@ public class AStarAlgorithm extends DijkstraAlgorithm {
|
||||||
super(data);
|
super(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void initializeHeap(ShortestPathData data) {
|
|
||||||
System.out.println("==> Initialisation du tas binaire (LabelStar)");
|
|
||||||
final HashMap<Integer, Label> labels = new HashMap<>(); // clé-valeur pour retrouver le label associé à un noeud à partir de son id
|
|
||||||
final BinaryHeap<Label> heap = new BinaryHeap<>(); // tas binaire pour retrouver le min en temps constant
|
|
||||||
final Double estimation = data.getDestination().getPoint().distanceTo(data.getOrigin().getPoint());
|
|
||||||
// Au lieu de mettre des Labels, on met des LabelStar, comme ça la comparaison prend en compte l'estimation
|
|
||||||
final LabelStar label = new LabelStar(data.getOrigin(), null, 0.0, false, estimation);
|
|
||||||
heap.insert(label);
|
|
||||||
labels.put(data.getOrigin().getId(), label);
|
|
||||||
System.out.println("==> Tas initialisé (LabelStar)");
|
|
||||||
|
|
||||||
this.heap = heap;
|
|
||||||
this.labels = labels;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Label createLabel(Node node) {
|
protected Label createLabel(Node node) {
|
||||||
return new LabelStar(node);
|
final LabelStar labelStar = new LabelStar(node);
|
||||||
}
|
final ShortestPathData data = (ShortestPathData)this.data;
|
||||||
|
final Double distance = data.getDestination().getPoint().distanceTo(node.getPoint()); // en mètres
|
||||||
|
|
||||||
@Override
|
switch (data.getMode()) {
|
||||||
protected void updateLabel(Label label, Arc arc) {
|
case LENGTH:
|
||||||
//System.out.println("==> updateLabel(" + label + ")");
|
labelStar.setCoutEstime(distance); // en mètres
|
||||||
final Label originLabel = this.labels.get(arc.getOrigin().getId());
|
break;
|
||||||
label.setCoutRealise(originLabel.getCoutRealise() + data.getCost(arc));
|
|
||||||
label.setArc(arc);
|
|
||||||
|
|
||||||
// Distance entre l'objectif final et là ou on en est
|
case TIME:
|
||||||
final Double distance = ((ShortestPathData)this.data).getDestination().getPoint().distanceTo(arc.getDestination().getPoint()); // en m
|
final Double speed = 1.5*(data.getMaximumSpeed()/3.6); // km/h converti en m/s, +50% pour garantir que l'estimation est une bonne strictement inférieure
|
||||||
if (((ShortestPathData)this.data).getMode() == Mode.LENGTH) {
|
labelStar.setCoutEstime(distance/speed); // en secondes
|
||||||
((LabelStar)label).setCoutEstime(distance); // en m
|
break;
|
||||||
} else { // TIME
|
|
||||||
final Double speed = ((ShortestPathData)this.data).getMaximumSpeed()/3.6; // en m/s
|
default:
|
||||||
((LabelStar)label).setCoutEstime(distance/speed); // en sec
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return labelStar;
|
||||||
this.heap.insert(label);
|
|
||||||
this.labels.put(arc.getDestination().getId(), label);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package org.insa.graphs.algorithm.shortestpath;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.insa.graphs.algorithm.AbstractSolution.Status;
|
import org.insa.graphs.algorithm.AbstractSolution.Status;
|
||||||
import org.insa.graphs.algorithm.utils.BinaryHeap;
|
import org.insa.graphs.algorithm.utils.BinaryHeap;
|
||||||
|
|
@ -18,92 +19,80 @@ public class DijkstraAlgorithm extends ShortestPathAlgorithm {
|
||||||
super(data);
|
super(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected HashMap<Integer, Label> labels = new HashMap<>();
|
protected HashMap<Integer, Label> labels; // clé-valeur pour retrouver le label associé à un noeud à partir de son id
|
||||||
protected BinaryHeap<Label> heap = new BinaryHeap<>();
|
protected BinaryHeap<Label> heap; // tas binaire pour retrouver le min en temps constant
|
||||||
|
|
||||||
// L'initialisation du tas et de la hashmap sont déportés dans une fonction, afin de pouvoir override cette dernière pour l'algo A*
|
|
||||||
// On retourne un Tuple (classe crée pour l'occasion dans le package utils) avec le tas binaire et la hashmap.
|
|
||||||
protected void initializeHeap(ShortestPathData data) {
|
|
||||||
System.out.println("==> Initialisation du tas binaire (Label)");
|
|
||||||
final HashMap<Integer, Label> labels = new HashMap<>(); // clé-valeur pour retrouver le label associé à un noeud à partir de son id
|
|
||||||
final BinaryHeap<Label> heap = new BinaryHeap<>(); // tas binaire pour retrouver le min en temps constant
|
|
||||||
final Label label = new Label(data.getOrigin(), null, 0.0, false);
|
|
||||||
heap.insert(label);
|
|
||||||
labels.put(data.getOrigin().getId(), label);
|
|
||||||
System.out.println("==> Tas initialisé (Label)");
|
|
||||||
|
|
||||||
this.heap = heap;
|
|
||||||
this.labels = labels;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fonction pour créer un label inexistant, à override pour utiliser les LabelStar
|
// Fonction pour créer un label inexistant, à override pour utiliser les LabelStar
|
||||||
protected Label createLabel(Node node) {
|
protected Label createLabel(Node node) {
|
||||||
return new Label(node);
|
return new Label(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fonction de MAJ d'un label, à override pour mettre a jour l'estimation du labelstar
|
|
||||||
protected void updateLabel(Label label, Arc arc) {
|
|
||||||
//System.out.println("==> updateLabel(" + label + ")");
|
|
||||||
final Label originLabel = this.labels.get(arc.getOrigin().getId());
|
|
||||||
label.setCoutRealise(originLabel.getCoutRealise() + data.getCost(arc));
|
|
||||||
label.setArc(arc);
|
|
||||||
this.heap.insert(label);
|
|
||||||
this.labels.put(arc.getDestination().getId(), label);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ShortestPathSolution doRun() {
|
protected ShortestPathSolution doRun() {
|
||||||
final ShortestPathData data = getInputData();
|
final ShortestPathData data = getInputData();
|
||||||
|
|
||||||
this.initializeHeap(data);
|
this.labels = new HashMap<>();
|
||||||
|
this.heap = new BinaryHeap<>();
|
||||||
|
|
||||||
|
Label currentLabel = this.createLabel(data.getOrigin());
|
||||||
|
currentLabel.setCoutRealise(0D);
|
||||||
|
this.heap.insert(currentLabel);
|
||||||
|
this.labels.put(data.getOrigin().getId(), currentLabel);
|
||||||
|
|
||||||
System.out.println("==> Dijkstra commence");
|
|
||||||
notifyOriginProcessed(data.getOrigin());
|
|
||||||
Label currentLabel = null;
|
|
||||||
boolean destinationReached = false;
|
boolean destinationReached = false;
|
||||||
while (!destinationReached && !this.heap.isEmpty() && (currentLabel=this.heap.deleteMin()) != null) {
|
notifyOriginProcessed(data.getOrigin());
|
||||||
//System.out.println(currentLabel instanceof LabelStar ? ((LabelStar)currentLabel).toString() : currentLabel.toString());
|
while (!destinationReached && !this.heap.isEmpty() && currentLabel != null) {
|
||||||
if (currentLabel.getTotalCost() == Double.MAX_VALUE)
|
if (currentLabel.getTotalCost() == Double.MAX_VALUE)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
final Node currentNode = currentLabel.getNode();
|
||||||
|
//System.out.println("currentNode = " + currentNode);
|
||||||
|
|
||||||
currentLabel.setMarque(true);
|
currentLabel.setMarque(true);
|
||||||
|
notifyNodeMarked(currentNode);
|
||||||
// On constate que les coûts des sommets marqués est bel et bien croissant
|
// On constate que les coûts des sommets marqués est bel et bien croissant
|
||||||
//System.out.println("-> Sommet marqué: " + currentLabel.getCoutRealise());
|
// System.out.println("-> Sommet marqué: " + currentLabel.getCoutRealise());
|
||||||
notifyNodeMarked(currentLabel.getNode());
|
|
||||||
|
|
||||||
// Si on atteint notre destination, on arrête l'algo
|
// Si on atteint notre destination, on arrête l'algo
|
||||||
if (currentLabel.getNode().equals(data.getDestination())) {
|
if (currentNode.equals(data.getDestination())) {
|
||||||
destinationReached = true;
|
destinationReached = true;
|
||||||
} else {
|
} else {
|
||||||
for (Arc arc : currentLabel.getNode().getSuccessors()) {
|
for (final Arc arc : currentNode.getSuccessors()) {
|
||||||
if (data.isAllowed(arc)) {
|
if (data.isAllowed(arc)) {
|
||||||
Label successorLabel = this.labels.get(arc.getDestination().getId());
|
final Node successorNode = arc.getDestination();
|
||||||
if (successorLabel == null) successorLabel = this.createLabel(arc.getDestination());
|
//System.out.println("successorNode = " + successorNode);
|
||||||
|
final Label successorLabel = Optional.ofNullable(this.labels.get(successorNode.getId())).orElse(this.createLabel(successorNode));
|
||||||
|
//System.out.println("successorLabel = " + successorLabel);
|
||||||
|
|
||||||
if (successorLabel.getTotalCost() > currentLabel.getTotalCost() + data.getCost(arc)) {
|
if (successorLabel.getTotalCost() > currentLabel.getTotalCost() + data.getCost(arc)) {
|
||||||
try {
|
try {
|
||||||
heap.remove(successorLabel);
|
this.heap.remove(successorLabel);
|
||||||
} catch(ElementNotFoundException e) {
|
} catch(ElementNotFoundException e) {
|
||||||
// BinaryHeap#remove a échoué, donc ça veut dire qu'on doit juste insérer, pas mettre à jour, mais ça ne change rien au niveau du code
|
// BinaryHeap#remove a échoué, donc ça veut dire qu'on doit juste insérer, pas mettre à jour, mais ça ne change rien au niveau du code
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateLabel(successorLabel, arc);
|
notifyNodeReached(successorNode);
|
||||||
notifyNodeReached(arc.getDestination());
|
|
||||||
|
successorLabel.setCoutRealise(currentLabel.getCoutRealise() + data.getCost(arc));
|
||||||
|
successorLabel.setArc(arc);
|
||||||
|
this.heap.insert(successorLabel);
|
||||||
|
this.labels.put(successorNode.getId(), successorLabel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
currentLabel = heap.deleteMin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ShortestPathSolution solution = null;
|
ShortestPathSolution solution = null;
|
||||||
if (destinationReached) {
|
if (destinationReached) {
|
||||||
notifyDestinationReached(data.getDestination());
|
notifyDestinationReached(data.getDestination());
|
||||||
System.out.println("==> Dijkstra termine et a trouvé");
|
|
||||||
|
|
||||||
// On part de la fin, et on remonte petit à petit vers le sommet d'origine
|
// On part de la fin, et on remonte petit à petit vers le sommet d'origine
|
||||||
System.out.println("==> On recompose le chemin");
|
final List<Arc> arcs = new ArrayList<>();
|
||||||
|
Node currentNode = data.getDestination();
|
||||||
List<Arc> arcs = new ArrayList<>();Node currentNode = data.getDestination();
|
while (currentNode != data.getOrigin()) {
|
||||||
while(currentNode != data.getOrigin()) {
|
|
||||||
final Arc arc = labels.get(currentNode.getId()).getArc();
|
final Arc arc = labels.get(currentNode.getId()).getArc();
|
||||||
if (arc != null) {
|
if (arc != null) {
|
||||||
arcs.add(arc);
|
arcs.add(arc);
|
||||||
|
|
@ -112,12 +101,10 @@ public class DijkstraAlgorithm extends ShortestPathAlgorithm {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
System.out.println("==> Fini");
|
|
||||||
|
|
||||||
Path path = new Path(data.getGraph(), arcs.reversed());
|
final Path path = new Path(data.getGraph(), arcs.reversed());
|
||||||
solution = new ShortestPathSolution(data, Status.OPTIMAL, path);
|
solution = new ShortestPathSolution(data, Status.OPTIMAL, path);
|
||||||
} else {
|
} else {
|
||||||
System.out.println("==> Dijkstra termine mais n'a pas trouvé");
|
|
||||||
solution = new ShortestPathSolution(data, Status.INFEASIBLE);
|
solution = new ShortestPathSolution(data, Status.INFEASIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue