ajout: Implémentation de AStar

This commit is contained in:
Brendan Saint Germes 2026-05-28 11:54:51 +02:00
parent 5fc064e863
commit 5a9e842f39
6 changed files with 157 additions and 26 deletions

View file

@ -78,7 +78,7 @@ public class ArcInspectorFactory {
public static class OnlyPedestrianByTime implements ArcInspector {
static final int maxPedestrianSpeed = 5;
public static final int maxPedestrianSpeed = 5;
@Override
public boolean isAllowed(Arc arc) {

View file

@ -1,9 +1,59 @@
package org.insa.graphs.algorithm.shortestpath;
import java.util.HashMap;
import org.insa.graphs.algorithm.ArcInspectorFactory;
import org.insa.graphs.algorithm.AbstractInputData.Mode;
import org.insa.graphs.algorithm.utils.BinaryHeap;
import org.insa.graphs.model.Arc;
import org.insa.graphs.model.Node;
public class AStarAlgorithm extends DijkstraAlgorithm {
public AStarAlgorithm(ShortestPathData 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
protected Label createLabel(Node node) {
return new LabelStar(node);
}
@Override
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);
// Distance entre l'objectif final et ou on en est
final Double distance = ((ShortestPathData)this.data).getDestination().getPoint().distanceTo(arc.getDestination().getPoint()); // en m
if (((ShortestPathData)this.data).getMode() == Mode.LENGTH) {
((LabelStar)label).setCoutEstime(distance); // en m
} else { // TIME
final Double speed = ((ShortestPathData)this.data).getMaximumSpeed()/3.6; // en m/s
((LabelStar)label).setCoutEstime(distance/speed); // en sec
}
this.heap.insert(label);
this.labels.put(arc.getDestination().getId(), label);
}
}

View file

@ -18,25 +18,52 @@ public class DijkstraAlgorithm extends ShortestPathAlgorithm {
super(data);
}
@Override
protected ShortestPathSolution doRun() {
final ShortestPathData data = getInputData();
protected HashMap<Integer, Label> labels = new HashMap<>();
protected BinaryHeap<Label> heap = new BinaryHeap<>();
System.out.println("==> Initialisation du tas binaire");
// 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 initialisté");
System.out.println("==> Tas initialisé (Label)");
this.heap = heap;
this.labels = labels;
}
// Fonction pour créer un label inexistant, à override pour utiliser les LabelStar
protected Label createLabel(Node 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
protected ShortestPathSolution doRun() {
final ShortestPathData data = getInputData();
this.initializeHeap(data);
System.out.println("==> Dijkstra commence");
notifyOriginProcessed(data.getOrigin());
Label currentLabel = null;
boolean destinationReached = false;
while (!destinationReached && !heap.isEmpty() && (currentLabel=heap.deleteMin()) != null) {
if (currentLabel.getCoutRealise() == Double.MAX_VALUE)
while (!destinationReached && !this.heap.isEmpty() && (currentLabel=this.heap.deleteMin()) != null) {
//System.out.println(currentLabel instanceof LabelStar ? ((LabelStar)currentLabel).toString() : currentLabel.toString());
if (currentLabel.getTotalCost() == Double.MAX_VALUE)
break;
currentLabel.setMarque(true);
@ -50,21 +77,16 @@ public class DijkstraAlgorithm extends ShortestPathAlgorithm {
} else {
for (Arc arc : currentLabel.getNode().getSuccessors()) {
if (data.isAllowed(arc)) {
Label successorLabel = labels.get(arc.getDestination().getId());
if (successorLabel == null) successorLabel = new Label(arc.getDestination());
if (successorLabel.getCoutRealise() > currentLabel.getCoutRealise() + data.getCost(arc)) {
Label successorLabel = this.labels.get(arc.getDestination().getId());
if (successorLabel == null) successorLabel = this.createLabel(arc.getDestination());
if (successorLabel.getTotalCost() > currentLabel.getTotalCost() + data.getCost(arc)) {
try {
heap.remove(successorLabel);
} 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
}
successorLabel.setCoutRealise(currentLabel.getCoutRealise() + data.getCost(arc));
successorLabel.setArc(arc);
heap.insert(successorLabel);
labels.put(arc.getDestination().getId(), successorLabel);
this.updateLabel(successorLabel, arc);
notifyNodeReached(arc.getDestination());
}
}

View file

@ -32,17 +32,34 @@ public class Label implements Comparable<Label> {
public void setArc(Arc arc) { this.arc = arc; }
public void setMarque(boolean marque) { this.marque = marque; }
//public Double getCost() {
// return this.coutRealise;
//}
// Méthode destinée à être override dans LabelStar
public Double getTotalCost() {
return this.getCoutRealise();
}
@Override
public int compareTo(Label l) {
// si deux nodes ont le même coût, on prend celui à l'id le plus petit
if (this.getCoutRealise().compareTo(l.getCoutRealise()) == 0)
public int compareTo(Label l) {
/*if (this instanceof LabelStar && l instanceof LabelStar) {
System.out.println("==> Comparaison LabelStar vs LabelStar");
} else {
System.out.println("==> Comparaison Label vs Label");
}
System.out.println(this);
System.out.println(l);*/
// si deux nodes ont le même coût, on compare leur estimation (si LabelStar)
int cmp1 = this.getTotalCost().compareTo(l.getTotalCost());
if (cmp1 == 0) {
// si on compare des LabelStar, on compare l'estimation
if (this instanceof LabelStar && l instanceof LabelStar) {
int cmp2 = ((LabelStar)this).getCoutEstime().compareTo(((LabelStar)l).getCoutEstime());
if (cmp2 != 0) return cmp2;
}
// Soit ce n'est pas des LabelStar, soit ils ont meme cout total ET meme estimation
return ((Integer) this.getNode().getId()).compareTo((Integer) l.getNode().getId());
else
return this.getCoutRealise().compareTo(l.getCoutRealise());
} else {
return this.getTotalCost().compareTo(l.getTotalCost());
}
}
@Override

View file

@ -0,0 +1,31 @@
package org.insa.graphs.algorithm.shortestpath;
import org.insa.graphs.model.Arc;
import org.insa.graphs.model.Node;
public class LabelStar extends Label {
private Double coutEstime;
public LabelStar(Node node) {
super(node);
this.coutEstime = 0D;
}
public LabelStar(Node node, Arc arc, Double coutRealise, boolean marque, Double coutEstime){
super(node, arc, coutRealise, marque);
this.coutEstime = coutEstime;
}
public Double getCoutEstime() { return this.coutEstime; }
public void setCoutEstime(Double val) { this.coutEstime = val; }
@Override
public Double getTotalCost() {
return this.getCoutRealise() + this.getCoutEstime();
}
@Override
public String toString() {
return "LabelStar(Node=" + this.getNode().getId() + "; Coût=" + this.getCoutRealise() + "; Marque=" + (this.getMarque() ? "OUI" : "NON") + "; Coût estimé=" + this.getCoutEstime() + ") [" + this.hashCode() + "]";
}
}

View file

@ -0,0 +1,11 @@
package org.insa.graphs.algorithm.shortestpath;
public class AStarTest extends ShortestPathAlgorithmTest {
@Override
public ShortestPathSolution runAlgo(ShortestPathData algoData) {
final AStarAlgorithm algo = new AStarAlgorithm(algoData);
return algo.doRun();
}
}