On branch master

This commit is contained in:
Jdihadi Ahamdy 2020-05-31 10:10:06 +02:00
parent 43c08bf88e
commit 46722fd591
5 changed files with 373 additions and 120 deletions

View file

@ -1,15 +1,17 @@
package org.insa.graphs.algorithm.shortestpath;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import org.insa.graphs.algorithm.AbstractInputData;
import org.insa.graphs.algorithm.AbstractSolution.Status;
import org.insa.graphs.algorithm.utils.BinaryHeap;
import org.insa.graphs.algorithm.utils.Label;
import org.insa.graphs.model.Arc;
import org.insa.graphs.model.Graph;
import org.insa.algo.AbstractSolution.Status;
import org.insa.algo.utils.*;
import org.insa.graph.*;
import org.insa.graphs.model.Node;
import org.insa.graphs.model.Path;
public class DijkstraAlgorithm extends ShortestPathAlgorithm {
@ -19,29 +21,158 @@ public class DijkstraAlgorithm extends ShortestPathAlgorithm {
@Override
protected ShortestPathSolution doRun() {
// Récupération des différentes données du graph
ShortestPathData data = getInputData();
Graph graph = data.getGraph();
List<Node> nodes = graph.getNodes();
final int nbNodes = graph.size();
//On récupère l'index du node origine du chemin à déterminer
int index_origine = data.getOrigin().getId();
//On récupère l'index du node destination
int index_dest = data.getDestination().getId();
notifyOriginProcessed(data.getOrigin());
/////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////INITIALISATION/////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
BinaryHeap<Label> tas = new BinaryHeap<Label>();
ArrayList<Label> labels = new ArrayList<Label>();
//On initialise tous les labels à +infini, avec marque à false et pere à NULL
for (int i = 0; i < nbNodes; i++) {
labels.add(new Label(nodes.get(i)));
}
//On actualise le cout du label correspondant au node d'origine
labels.get(index_origine).setCost(0);
//On insère le label actualisé dans le tas
tas.insert(labels.get(index_origine));
/////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////INITIALISATION/////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////ITERATIONS//////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
//Définition d'une variable pour compter le nombre d'itérations pour le debogage
int nbIterations = 0;
while (!labels.get(index_dest).isMarked() && tas.size() != 0) {
//On récupère le label minimal dans le tas
Label label_min = tas.deleteMin();
//On marque le label minimal
labels.get(label_min.getNode().getId()).mark();
//Vérification du coût croissant des labels marqués
System.out.println("Coût du label marqué : " + label_min.getCost());
//Vérification de la taille du tas
System.out.println("Taille du tas : " + tas.size());
//Debogage
//Incrémentation du nombre d'itérations
nbIterations++;
//Verification du tas
if (tas.isValid()) {
System.out.println("Tas valide");
}
else {
System.out.println("Tas non valide");
}
//On récupère les arcs successeurs du label minimal
List<Arc> arcs = label_min.getNode().getSuccessors();
//Debogage
System.out.println("Nb successeurs du label : " + arcs.size());
for (int i = 0; i < arcs.size(); i++) {
//On vérifie que le chemin est autorisé
if (!data.isAllowed(arcs.get(i))) {
continue;
}
//On récupère l'index de la destination de l'arc actuel
int index_suiv = arcs.get(i).getDestination().getId();
if (!labels.get(index_suiv).isMarked())
{
double oldDistance = labels.get(index_suiv).getCost();
double newDistance = label_min.getCost() + data.getCost(arcs.get(i));
//Coloration des chemins au fur et à mesure
if (Double.isInfinite(oldDistance) && Double.isFinite(newDistance)) {
notifyNodeReached(arcs.get(i).getDestination());
}
if (newDistance < oldDistance) {
labels.get(index_suiv).setCost(newDistance);
labels.get(index_suiv).setFather(arcs.get(i));
if (Double.isFinite(oldDistance)) {
tas.remove(labels.get(index_suiv));
}
tas.insert(labels.get(index_suiv));
}
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////ITERATIONS//////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////CREATION DE LA SOLUTION////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
ShortestPathSolution solution = null;
// Initialisation
// du graphe
final ShortestPathData data = getInputData();
Graph graph = data.getGraph();
final int nbNodes = graph.size();
// des couts
double[] distances = new double[nbNodes];
Arrays.fill(distances, Double.POSITIVE_INFINITY);
distances[data.getOrigin().getId()] = 0;
// Notify observers about the first event (origin processed).
notifyOriginProcessed(data.getOrigin());
// Initialize array of predecessors.
Arc[] predecessorArcs = new Arc[nbNodes];
while (solution == null) { //Tant qu'il y a pas de solution
//La destination n'a pas de prédécesseur, le chemin est infaisable
if (!labels.get(index_dest).isMarked()) {
solution = new ShortestPathSolution(data, Status.INFEASIBLE);
}
// TODO:
else {
//La destination a été trouvée. On en informe l'utilisateur.
notifyDestinationReached(data.getDestination());
//On crée un nouveau chemin à partir des prédécesseurs
ArrayList<Arc> chemin = new ArrayList<>();
Arc arc = labels.get(index_dest).getFather();
while (arc != null) {
chemin.add(arc);
arc = labels.get(arc.getOrigin().getId()).getFather();
}
//Affichages pour le debogage
System.out.println("Nombre d'itérations : " + nbIterations);
System.out.println("Nombre d'arcs dans le plus court chemin : " + chemin.size());
//On inverse ce chemin
Collections.reverse(chemin);
//On crée la solution finale
solution = new ShortestPathSolution(data, Status.OPTIMAL, new Path(graph, chemin));
//Debogage
if (!solution.getPath().isValid()) {
System.out.println("Chemin trouvé non valide.");
}
else {
System.out.println("Chemin trouvé valide.");
}
if (data.getMode() == AbstractInputData.Mode.TIME) {
System.out.println("Durée chemin Path : " + solution.getPath().getMinimumTravelTime() + ", Dijkstra : " + labels.get(index_dest).getCost());
}
else {
System.out.println("Longueur chemin Path : " + solution.getPath().getLength() + ", Dijkstra : " + labels.get(index_dest).getCost());
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////CREATION DE LA SOLUTION////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
return solution;
}

View file

@ -138,25 +138,30 @@ public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
@Override
public void remove(E x) throws ElementNotFoundException {
int index;
int lastindex;
E lastItem;
if(this.isEmpty())
throw new ElementNotFoundException(x);
else {
index = this.array.indexOf(x);
if(index == -1 || index >= this.currentSize) {
throw new ElementNotFoundException(x);
}
else {
lastindex=--this.currentSize;
lastItem = this.array.get(lastindex);
this.array.set(index, lastItem);
this.percolateDown(index);
this.percolateUp(index);
}
}
}
int indexLast;
E lastElement;
if (this.isEmpty())
throw new ElementNotFoundException(x);
else {
index = this.array.indexOf(x);
/* Si on n'a pas trouve l'element, on souleve une exception */
if (index == -1 || index >= this.currentSize) {
throw new ElementNotFoundException(x);
}
/* Si l'element a ete trouve, on le supprime */
else {
indexLast=--this.currentSize;
/* Si l'element supprime n'etait pas le dernier */
if (indexLast>index) {
lastElement = this.array.get(indexLast);
this.array.set(index, lastElement);
this.percolateDown(index);
this.percolateUp(index);
}
}
}
}
@Override
public E findMin() throws EmptyPriorityQueueException {
@ -172,8 +177,7 @@ public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
this.arraySet(0, lastItem);
this.percolateDown(0);
return minItem;
}
}
/**
* Creates a multi-lines string representing a sorted view of this binary heap.
*
@ -219,5 +223,24 @@ public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
public String toString() {
return BinaryHeapFormatter.toStringTree(this, 8);
}
public boolean isValid() {
boolean valide = true;
for (int i = 0; i < this.currentSize && valide; i++) {
if (this.indexLeft(i) <= this.currentSize) {
if (this.array.get(this.indexLeft(i)).compareTo(this.array.get(i)) == -1) {
valide = false;
}
else {
if (this.indexLeft(i) + 1 < this.currentSize) {
if (this.array.get(this.indexLeft(i) + 1).compareTo(this.array.get(i)) == -1) {
valide = false;
}
}
}
}
}
return valide;
}
}

View file

@ -1,38 +1,68 @@
package org.insa.graphs.algorithm.utils;
import org.insa.graphs.model.Arc;
import org.insa.graphs.model.Node;
public class Label {
public class Label implements Comparable<Label> {
private Node sommet_courant;
private boolean marque;
protected double cout;
private Arc pere;
private boolean mark;
private int cost;
private Node father;
private Node nodes;
public Label(Node noeud) {
this.nodes=noeud;
this.mark=false;
this.cost=100000;
this.father=null;
public Label(Node sommet_courant) {
this.sommet_courant = sommet_courant;
marque = false;
cout = Double.POSITIVE_INFINITY;
pere = null;
}
public double getCost() {
return this.cout;
}
public double getTotalCost() {
return this.getCost();
}
public Node getNode() {
return this.sommet_courant;
}
public Arc getFather() {
return this.pere;
}
public boolean isMarked() {
return marque;
}
public void setFather(Arc pere) {
public int getCost() {
return this.cost;
this.pere = pere;
}
public boolean getMark() {
return this.mark;
public void mark() {
this.marque = true;
}
public Node getfather() {
return this.father;
public void setCost(double cout) {
this.cout = cout;
}
public boolean setMark() {
return this.mark=true;
/* Compare les Labels selon leur coût */
public int compareTo(Label autre) {
int resultat;
if (this.getTotalCost() < autre.getTotalCost()) {
resultat = -1;
}
else if (this.getTotalCost() == autre.getTotalCost()) {
resultat = 0;
}
else {
resultat = 1;
}
return resultat;
}
}

View file

@ -0,0 +1,29 @@
package org.insa.graphs.algorithm.utils;
import org.insa.graphs.model.Node;
import org.insa.graphs.model.Point;
import org.insa.graphs.algorithm.AbstractInputData;
import org.insa.graphs.algorithm.shortestpath.ShortestPathData;
public class LabelStar extends Label {
private float inf;
public LabelStar(Node sommet_courant, Node node_dest, ShortestPathData data) {
super(sommet_courant);
if (data.getMode() == AbstractInputData.Mode.LENGTH) {
this.inf = (float)Point.distance(sommet_courant.getPoint(),data.getDestination().getPoint());
}
else {
int vitesse = Math.max(data.getMaximumSpeed(), data.getGraph().getGraphInformation().getMaximumSpeed());
this.inf = (float)Point.distance(sommet_courant.getPoint(),data.getDestination().getPoint())/(vitesse*1000.0f/3600.0f);
}
}
/* Renvoie le coût de l'origine jusqu'au noeud + coût à vol d'oiseau du noeud jusqu'à la destination */
public double getTotalCost() {
return this.inf+this.cout;
}
}

View file

@ -30,36 +30,56 @@ public class Path {
* @throws IllegalArgumentException If the list of nodes is not valid, i.e. two
* consecutive nodes in the list are not connected in the graph.
*
* @deprecated Need to be implemented.
* Need to be implemented.
*/
public static Path createFastestPathFromNodes(Graph graph, List<Node> nodes)
throws IllegalArgumentException {
List<Arc> arcs = new ArrayList<Arc>();
if(nodes.size()==1) {
if (nodes.size() > 1) {
for (int num_node = 0; num_node < nodes.size()-1; num_node++) {
//On recupere les arcs partant du node actuel
List<Arc> successeurs = nodes.get(num_node).getSuccessors();
//On definit un booleen pour determiner si on a deja trouve un arc entre les deux nodes
boolean arc_trouve = false;
for (int num_arc = 0; num_arc < successeurs.size(); num_arc++) {
//On verifie que l'arc partant du node actuel arrive au suivant
if (successeurs.get(num_arc).getDestination().compareTo(nodes.get(num_node+1)) == 0) {
//Si cet arc arrive au node suivant, si aucun arc n'a encore ete trouve, on le choisit
if (!arc_trouve) {
arcs.add(successeurs.get(num_arc));
arc_trouve = true;
}
//Si un autre arc a deja ete trouve, on le remplace si la temps de trajet du nouvel arc est plus court
else if (arcs.get(num_node).getMinimumTravelTime() > successeurs.get(num_arc).getMinimumTravelTime())
{
arcs.set(num_node, successeurs.get(num_arc));
}
}
}
//Si, en ayant parcouru tous les successeurs, on ne trouve pas le node suivant, on renvoie une exception
if (!arc_trouve) {
throw(new IllegalArgumentException());
}
}
}
//Si le path passé en argument ne contient qu'un ou aucun node,
//on ne peut créer de path avec des arcs
else if (nodes.size() == 1){
return new Path(graph, nodes.get(0));
}
for(int i=0; i<nodes.size()-1; i++) { // Parcours des noeuds dans l'orde
Node node_actuel= nodes.get(i);
if(node_actuel.hasSuccessors()) { // Véridie si le noeud a une succeseur
List<Arc> arc_suiv = node_actuel.getSuccessors();
double travel_time = 10000000;
int num=0;
boolean successor_found = false ;
for(int j=0; j<arc_suiv.size();j++) {
if((arc_suiv.get(j).getDestination().compareTo(nodes.get(i+1)) == 0 ) && (arc_suiv.get(j).getMinimumTravelTime()< travel_time)) {
num=j;
travel_time=arc_suiv.get(num).getMinimumTravelTime();
successor_found = true;
}
}
if(successor_found== false) {
throw new IllegalArgumentException();
}
arcs.add(arc_suiv.get(num));
}else {
throw new IllegalArgumentException();
}
else {
return new Path(graph);
}
return new Path(graph, arcs);
}
@ -75,36 +95,56 @@ public class Path {
* @throws IllegalArgumentException If the list of nodes is not valid, i.e. two
* consecutive nodes in the list are not connected in the graph.
*
* @deprecated Need to be implemented.
* Need to be implemented.
*/
public static Path createShortestPathFromNodes(Graph graph, List<Node> nodes)
throws IllegalArgumentException {
List<Arc> arcs = new ArrayList<Arc>();
if(nodes.size()==1) {
if (nodes.size() > 1) {
for (int num_node = 0; num_node < nodes.size()-1; num_node++) {
//On recupere les arcs partant du node actuel
List<Arc> successeurs = nodes.get(num_node).getSuccessors();
//On definit un booleen pour determiner si on a deja trouve un arc entre les deux nodes
boolean arc_trouve = false;
for (int num_arc = 0; num_arc < successeurs.size(); num_arc++) {
//On verifie que l'arc partant du node actuel arrive au suivant
if (successeurs.get(num_arc).getDestination().compareTo(nodes.get(num_node+1)) == 0) {
//Si cet arc arrive au node suivant, si aucun arc n'a encore ete trouve, on le choisit
if (!arc_trouve) {
arcs.add(successeurs.get(num_arc));
arc_trouve = true;
}
//Si un autre arc a deja ete trouve, on le remplace si la distance du nouvel arc est plus courte
else if (arcs.get(num_node).getLength() > successeurs.get(num_arc).getLength())
{
arcs.set(num_node, successeurs.get(num_arc));
}
}
}
//Si, en ayant parcouru tous les successeurs, on ne trouve pas le node suivant, on renvoie une exception
if (!arc_trouve) {
throw(new IllegalArgumentException());
}
}
}
//Si le path passé en argument ne contient qu'un ou aucun node,
//on ne peut créer de path avec des arcs
else if (nodes.size() == 1){
return new Path(graph, nodes.get(0));
}
for(int i=0; i<nodes.size()-1; i++) { // Parcours des noeuds dans l'orde
Node node_actuel= nodes.get(i);
if(node_actuel.hasSuccessors()) { // Véridie si le noeud a une succeseur
List<Arc> arc_suiv = node_actuel.getSuccessors();
int num=0;
double length = 1000000;
boolean successor_found = false ;
for(int j=0; j<arc_suiv.size();j++) {
if((arc_suiv.get(j).getDestination().compareTo(nodes.get(i+1)) == 0) && (arc_suiv.get(j).getLength() < length)) {
num = j;
length = arc_suiv.get(num).getLength();
successor_found = true;
}
}
if(successor_found== false) {
throw new IllegalArgumentException();
}
arcs.add(arc_suiv.get(num));
}else {
throw new IllegalArgumentException();
}
else {
return new Path(graph);
}
return new Path(graph, arcs);
}
@ -246,7 +286,7 @@ public class Path {
*
* @return true if the path is valid, false otherwise.
*
* @deprecated Need to be implemented.
* Need to be implemented.
*/
public boolean isValid() {
if (this.isEmpty()) {
@ -292,7 +332,7 @@ public class Path {
* @return Time (in seconds) required to travel this path at the given speed (in
* kilometers-per-hour).
*
* @deprecated Need to be implemented.
* Need to be implemented.
*/
public double getTravelTime(double speed) {
double temps = 0.0;
@ -307,7 +347,7 @@ public class Path {
*
* @return Minimum travel time to travel this path (in seconds).
*
* @deprecated Need to be implemented.
* Need to be implemented.
*/
public double getMinimumTravelTime() {
double temps = 0;