Algo Marathon: chemins très centrés sur départ/arrivée
This commit is contained in:
parent
ae73970aff
commit
0979e10f41
1 changed files with 54 additions and 145 deletions
|
@ -2,10 +2,15 @@ package org.insa.graphs.algorithm.marathon;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.insa.graphs.algorithm.AbstractAlgorithm;
|
import org.insa.graphs.algorithm.AbstractAlgorithm;
|
||||||
|
import org.insa.graphs.algorithm.ArcInspector;
|
||||||
|
import org.insa.graphs.algorithm.ArcInspectorFactory;
|
||||||
import org.insa.graphs.algorithm.AbstractSolution.Status;
|
import org.insa.graphs.algorithm.AbstractSolution.Status;
|
||||||
|
import org.insa.graphs.algorithm.shortestpath.DijkstraAlgorithm;
|
||||||
import org.insa.graphs.algorithm.shortestpath.Label;
|
import org.insa.graphs.algorithm.shortestpath.Label;
|
||||||
|
import org.insa.graphs.algorithm.shortestpath.ShortestPathAlgorithm;
|
||||||
import org.insa.graphs.algorithm.shortestpath.ShortestPathData;
|
import org.insa.graphs.algorithm.shortestpath.ShortestPathData;
|
||||||
import org.insa.graphs.algorithm.shortestpath.ShortestPathObserver;
|
import org.insa.graphs.algorithm.shortestpath.ShortestPathObserver;
|
||||||
import org.insa.graphs.algorithm.shortestpath.ShortestPathSolution;
|
import org.insa.graphs.algorithm.shortestpath.ShortestPathSolution;
|
||||||
|
@ -14,15 +19,23 @@ import org.insa.graphs.model.Arc;
|
||||||
import org.insa.graphs.model.Graph;
|
import org.insa.graphs.model.Graph;
|
||||||
import org.insa.graphs.model.Node;
|
import org.insa.graphs.model.Node;
|
||||||
import org.insa.graphs.model.Path;
|
import org.insa.graphs.model.Path;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
public class MarathonAlgorithm extends AbstractAlgorithm<ShortestPathObserver> {
|
|
||||||
|
public class MarathonAlgorithm extends ShortestPathAlgorithm {
|
||||||
|
|
||||||
protected double pathCost;
|
protected double pathCost;
|
||||||
|
private static final int distanceMarathon = 42195; // en mètres
|
||||||
|
public static Random rand = new Random();
|
||||||
|
|
||||||
protected MarathonAlgorithm(ShortestPathData data) {
|
protected MarathonAlgorithm(ShortestPathData data) {
|
||||||
super(data);
|
super(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Label createLabel(Node node) {
|
||||||
|
return new Label(node);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ShortestPathSolution run() {
|
public ShortestPathSolution run() {
|
||||||
return (ShortestPathSolution) super.run();
|
return (ShortestPathSolution) super.run();
|
||||||
|
@ -35,159 +48,55 @@ public class MarathonAlgorithm extends AbstractAlgorithm<ShortestPathObserver> {
|
||||||
final Graph graph = data.getGraph();
|
final Graph graph = data.getGraph();
|
||||||
final int nbNodes = graph.size();
|
final int nbNodes = graph.size();
|
||||||
|
|
||||||
// List of sommets, but with type Label
|
DijkstraAlgorithm dijkstra = new DijkstraAlgorithm(data);
|
||||||
ArrayList<Label> labels = new ArrayList<Label>(nbNodes);
|
ShortestPathSolution path = dijkstra.run();
|
||||||
|
|
||||||
// Heap of sommets
|
while (path.getPath().getLength() < getDistance()) {
|
||||||
BinaryHeap<Label> tas = new BinaryHeap<Label>();
|
// Recuperation indices
|
||||||
|
// TODO : A MODIFIER POUR AMELIORER LA COHERENCE DU CHEMIN
|
||||||
// Notify observers about the first event (origin processed).
|
int longueurPath = path.getPath().size();
|
||||||
notifyOriginProcessed(data.getOrigin());
|
List<Arc> pathMax = path.getPath().getArcs();
|
||||||
|
float max = 0;
|
||||||
// Init Dijkstra
|
int indiceArcToRemove = 0; //Math.abs(rand.nextInt() % (longueurPath - 1));
|
||||||
for (Node node : graph.getNodes()) {
|
for (int i = 0; i < pathMax.size(); i++) {
|
||||||
// Luckily they are ordered by id.
|
if (pathMax.get(i).getLength() > max) {
|
||||||
// ArrayList.set only works if the value is already initialized (because why Java?)
|
max = pathMax.get(i).getLength();
|
||||||
labels.add(this.createLabel(node));
|
indiceArcToRemove = i;
|
||||||
}
|
|
||||||
|
|
||||||
Label s = labels.get(data.getOrigin().getId());
|
|
||||||
|
|
||||||
// Add origin in the heap
|
|
||||||
// Label s = origin;//labels.get(0);
|
|
||||||
s.setPathCost(0);
|
|
||||||
tas.insert(s);
|
|
||||||
|
|
||||||
// On considère le sommet x à chaque itération
|
|
||||||
Label x = s;
|
|
||||||
|
|
||||||
final int dest_id = data.getDestination().getId();
|
|
||||||
while (!tas.isEmpty() && !(labels.get(dest_id).getNode().equals(x.getNode()))) {
|
|
||||||
x = tas.deleteMin();
|
|
||||||
x.mark();
|
|
||||||
notifyNodeMarked(x.getNode());
|
|
||||||
// System.out.println(x.getCost()); // Pour vérifier une croissance des noeuds marqués
|
|
||||||
// We create a list of node successors of x, instead of a list of Arcs.
|
|
||||||
double arc_cost = 0;
|
|
||||||
for (Arc successorArc : x.getNode().getSuccessors()) {
|
|
||||||
Label successor = labels.get(successorArc.getDestination().getId());
|
|
||||||
arc_cost = Double.MAX_VALUE;
|
|
||||||
if (!successor.isMarked() && data.isAllowed(successorArc)) {
|
|
||||||
// This loop serves to get the length of the arc as
|
|
||||||
// we know its origin and destination
|
|
||||||
for (Arc arc : x.getNode().getSuccessors()) {
|
|
||||||
|
|
||||||
if (successor.getNode().equals(arc.getDestination()) && data.getCost(arc) == data.getCost(successorArc)) {
|
|
||||||
// data.getcost(arc) returns a cost considering the mode chosen:
|
|
||||||
// TIME or LENGTH
|
|
||||||
// Similar to using getLength / getMinimumTravelTime
|
|
||||||
arc_cost = Math.min(data.getCost(arc), arc_cost);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final double possible_path_cost = x.getCost() + arc_cost;
|
// Recuperation Arc à supprimer
|
||||||
if (successor.getCost() > possible_path_cost) {
|
Arc arcToRemove = path.getPath().getArcs().get(indiceArcToRemove);
|
||||||
// Mise à jour du label
|
Node originArcToRemove = arcToRemove.getOrigin();
|
||||||
successor.setPathCost(possible_path_cost);
|
Node destinationArcToRemove = arcToRemove.getDestination();
|
||||||
successor.setParentArc(successorArc);
|
|
||||||
// Si le noeud n'a pas déjà été rajouté au tas, on le rajoute
|
// On le supprime dans une copie du tableau (getter Collections.unmodifiable dans Path.java)
|
||||||
// isReached permet de vérifier en complexité O(1)
|
path.getPath().getArcs().remove(indiceArcToRemove);
|
||||||
// C'est un léger coût en mémoire pour un gain en vitesse
|
originArcToRemove.removeArc(arcToRemove);
|
||||||
if (successor.isReached()) {
|
|
||||||
// removing then inserting resorts the binary heap
|
// Creations du chemin entre les 2 noeuds dont l'arc a été supprimé
|
||||||
tas.remove(successor);
|
ArcInspector arcInspector = ArcInspectorFactory.getAllFilters().get(0);
|
||||||
} else {
|
ShortestPathData newData = new ShortestPathData(graph, originArcToRemove, destinationArcToRemove, arcInspector);
|
||||||
successor.markReached();
|
DijkstraAlgorithm newDijkstra = new DijkstraAlgorithm(newData);
|
||||||
notifyNodeReached(successor.getNode());
|
ShortestPathSolution newPath = newDijkstra.run();
|
||||||
}
|
|
||||||
tas.insert(successor);
|
if (newPath.getPath() != null) {
|
||||||
}
|
// Ajout du path trouvé à l'indice où on l'a enlevé
|
||||||
}
|
path.getPath().getArcs().addAll(newPath.getPath().getArcs());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (labels.get(data.getDestination().getId()).getParentArc() == null) {
|
return path;
|
||||||
this.pathCost = 0;
|
|
||||||
solution = new ShortestPathSolution(data, Status.INFEASIBLE);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Create the path ...
|
|
||||||
ArrayList<Arc> arcs_path = new ArrayList<>();
|
|
||||||
|
|
||||||
Arc arc = labels.get(data.getDestination().getId()).getParentArc();
|
|
||||||
|
|
||||||
// We will find the path using the parent nodes, from the destination to the
|
|
||||||
// origin
|
|
||||||
while (arc != null && arc.getDestination().getId() != data.getOrigin().getId()) {
|
|
||||||
arcs_path.add(arc);
|
|
||||||
arc = labels.get(arc.getOrigin().getId()).getParentArc();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyDestinationReached(data.getDestination());
|
|
||||||
|
|
||||||
// Reverse the path...
|
|
||||||
Collections.reverse(arcs_path);
|
|
||||||
|
|
||||||
// Create the final solution.
|
|
||||||
solution = new ShortestPathSolution(data, Status.OPTIMAL, new Path(graph, arcs_path));
|
|
||||||
|
|
||||||
this.pathCost = labels.get(data.getDestination().getId()).getCost();
|
|
||||||
}
|
|
||||||
return solution;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ShortestPathData getInputData() {
|
|
||||||
return (ShortestPathData) super.getInputData();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify all observers that the origin has been processed.
|
|
||||||
*
|
|
||||||
* @param node Origin.
|
|
||||||
*/
|
|
||||||
public void notifyOriginProcessed(Node node) {
|
|
||||||
for (ShortestPathObserver obs: getObservers()) {
|
|
||||||
obs.notifyOriginProcessed(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify all observers that a node has been reached for the first time.
|
|
||||||
*
|
|
||||||
* @param node Node that has been reached.
|
|
||||||
*/
|
|
||||||
public void notifyNodeReached(Node node) {
|
|
||||||
for (ShortestPathObserver obs: getObservers()) {
|
|
||||||
obs.notifyNodeReached(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify all observers that a node has been marked, i.e. its final value has
|
|
||||||
* been set.
|
|
||||||
*
|
|
||||||
* @param node Node that has been marked.
|
|
||||||
*/
|
|
||||||
public void notifyNodeMarked(Node node) {
|
|
||||||
for (ShortestPathObserver obs: getObservers()) {
|
|
||||||
obs.notifyNodeMarked(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify all observers that the destination has been reached.
|
|
||||||
*
|
|
||||||
* @param node Destination.
|
|
||||||
*/
|
|
||||||
public void notifyDestinationReached(Node node) {
|
|
||||||
for (ShortestPathObserver obs: getObservers()) {
|
|
||||||
obs.notifyDestinationReached(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getCostPath() {
|
public double getCostPath() {
|
||||||
return this.pathCost;
|
return this.pathCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int getDistance() {
|
||||||
|
return distanceMarathon;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue