diff --git a/DeLorean.java b/DeLorean.java new file mode 100644 index 0000000..9edde28 --- /dev/null +++ b/DeLorean.java @@ -0,0 +1,77 @@ +// pseudo code du rapport sur le problme ouvert + + +public class DeLoreanShortestPath extends ShortestPathAlgorithm { + public DijkstraAlgorithm(ShortestPathData data) { + super(data); + } + + ShortestPathSolution solution; + + // on pourra par exemple mettre le graphe des stations dans data + final ShortestPathData data = getInputData(); + Graph gr = data.getGraph(); + StationGraph grS = data.getStationGraph(); + double maximumDist = ... //(ici 200000, on pourrait passer cette variable dans data puisque certains voitures n'auront pas la même autonomie) + + /*On part du principe ici que le coût en temps prend déjà en compte les 10 minutes de rechargement. Il suffirait si ce n'est pas le cas de regarder si la destination de l'arc est la destination finale et si ce n'est pas le cas de rajouter 10 au coût temporel*/ + + // on récupère la destination et l'origine + NodeStation nodeA = getNodeStationFromNode(...) + NodeStation nodeB = getNodeStationFromNode(...) + + //On récupère la liste des nodes correspondantes aux stations (stockée dans notre graphe des stations). + arrayList list = getNodeStationsFromNode(...) + + /* + int UpdateGraphIsodistance(Node,double,Graph) + est une méthode de la classe StationGraph qui met à jour le StationGraph par rapport à l'Isodistance autour de A dans le graphe graph. Elle renvoie le nombre d'arrêtes crées (-1 si aucune).*/ + // on calcule l'Isodistance de A + if (grS.UpdateIsodistance(NodeA,maximumDist,gr) != -1){ + + // A.hasSuccessor(B) itère sur les successeurs d'un NodeStation (A) et vérifie si l'un d'entre eux est B + if(!NodeA.hasSuccessor(NodeB)){ + // on calcule l'Isodistance de B + if (grS.UpdateIsodistance(NodeB,maximumDist,gr) != -1){ + + /*StationAStarAlgorithm(ShortestPathData, double) hérite de AStar et ne fait que s'adapter aux classes "Station" pour rechercher quel est le plus court chemin sur le graphe des stations*/ + + StationAStarAlgorithm AAlgo = new StationAStarAlgorithm(data); + StationPath aStarResult = AAlgo.doRun(); + arrayList way = aStarResult.getStationArc(); + Path[] pathArray = new Path[way.size()]; + + int i = 0; + for(ArcStation i : way){ + if (data.getMode() == AbstractInputData.Mode.TIME) { + pathArray[i] = way.getTimePath() + // à noter qu'on pourrait également retourner le path renvoyé par un ModifiedAStarAlgorithm lancé en temps si le choix a été fait de ne pas stocker dans les arc le chemin correspondant. + } else { + pathArray[i] = way.getLengthPath() + } + } + // à noter également que si l'on choisit de stocker des listes d'Arc plutôt que des Path il suffira de faire remplacer le Path.concatenate(...) par un new Path(gr, arcs) + + + // il nous faut maintenant concaténer les chemins entre chaque station + solution = new ShortestPathSolution(data, AbstractSolution.Status.OPTIMAL, Path.concatenate(pathArray)); + + + } else { + // aucune solution car aucune NodeS dans l'isodistance de B + + solution = new ShortestPathSolution(data, AbstractSolution.Status.INFEASIBLE); + } + } else { + /*ModifiedAStarAlgorithm(ShortestPathData, double) hérite de AStar et ne change que le fait qu'un arc n'est inséré que si son coût depuis l'origine est inférieur à la valeur passée en argument du constructeur */ + + + // pas besoin de stations car B est dans l'isodistance de A + ModifiedAStarAlgorithm AAlgo = new ModifiedAStarAlgorithm(data, maximumDist); + solution = AAlgo.doRun(); + } + } else { + // aucune solution car aucune NodeS dans l'isodistance de A + solution = new ShortestPathSolution(data, AbstractSolution.Status.INFEASIBLE); + } +} \ No newline at end of file diff --git a/UML1.png b/UML1.png new file mode 100644 index 0000000..baf9fa9 Binary files /dev/null and b/UML1.png differ diff --git a/UML2.png b/UML2.png new file mode 100644 index 0000000..4c5ffdd Binary files /dev/null and b/UML2.png differ diff --git a/be-graphes-algos/.classpath b/be-graphes-algos/.classpath index 4559ca0..9ba41a2 100644 --- a/be-graphes-algos/.classpath +++ b/be-graphes-algos/.classpath @@ -23,5 +23,22 @@ + + + + + + + + + + + + + + + + + diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/AStarAlgorithm.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/AStarAlgorithm.java index c510dba..da3f4ab 100644 --- a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/AStarAlgorithm.java +++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/AStarAlgorithm.java @@ -19,15 +19,23 @@ public class AStarAlgorithm extends DijkstraAlgorithm { super(data); } + + // only difference with Dijkstra : using different labels @Override protected void initLabel(){ int i = 0; + + // usefull for the estimated crowlength time, + // if there are no maximal speed we use 130 km/h double maxSpeed = 130; + if (data.getMode() == AbstractInputData.Mode.TIME){ if (gr.getGraphInformation().hasMaximumSpeed()){ maxSpeed = gr.getGraphInformation().getMaximumSpeed(); } } + + // initialization close to Dijkstra's for (Node l : gr.getNodes()){ if (data.getMode() == AbstractInputData.Mode.TIME){ labels[i] = new LabelStar(l, false, null,data.getDestination(), maxSpeed); diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/DijkstraAlgorithm.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/DijkstraAlgorithm.java index bfd0ca2..5f963f1 100644 --- a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/DijkstraAlgorithm.java +++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/DijkstraAlgorithm.java @@ -15,15 +15,22 @@ import java.util.List; public class DijkstraAlgorithm extends ShortestPathAlgorithm { + /* === Used for testing purposes === + private long nodes = 0; + */ + public DijkstraAlgorithm(ShortestPathData data) { super(data); } + final ShortestPathData data = getInputData(); Graph gr = data.getGraph(); // array containing all the labels Label[] labels = new Label[gr.size()]; + + // initialization (separate so that it can be overridden by the A*) protected void initLabel(){ int i = 0; for (Node l : gr.getNodes()){ @@ -45,27 +52,41 @@ public class DijkstraAlgorithm extends ShortestPathAlgorithm { // initialization of the heap & the first node BinaryHeap + + + + + + + + + + + + + + + + + diff --git a/be-graphes-gui/src/main/java/org/insa/graphs/gui/simple/Launch.java b/be-graphes-gui/src/main/java/org/insa/graphs/gui/simple/Launch.java index 46bb5d5..fdfab6a 100644 --- a/be-graphes-gui/src/main/java/org/insa/graphs/gui/simple/Launch.java +++ b/be-graphes-gui/src/main/java/org/insa/graphs/gui/simple/Launch.java @@ -22,10 +22,15 @@ import org.insa.graphs.model.io.GraphReader; import org.insa.graphs.model.io.PathReader; // for colouring +import java.time.Duration; import java.util.Random; import java.awt.Color; +import java.util.concurrent.TimeUnit; public class Launch { + private static int verbose = 1; + private static long timeA = 0; + private static long timeD = 0; /** @@ -52,6 +57,8 @@ public class Launch { return basicDrawing; } + + // generates a path with the chosen algorithm public static Path createTestPath(Graph graph,int idOrigin,int idDest,String algo){ Node A = graph.get(idOrigin); Node B = graph.get(idDest); @@ -60,31 +67,37 @@ public class Launch { ShortestPathSolution sol; ShortestPathData data= new ShortestPathData(graph,A,B,ins); - switch (algo){ + switch (algo){ // we chose the algo we want case "A*": AStarAlgorithm AAlgo = new AStarAlgorithm(data); sol = AAlgo.doRun(); resu = sol.getPath(); + break; case "D": DijkstraAlgorithm DAlgo = new DijkstraAlgorithm(data); sol = DAlgo.doRun(); resu = sol.getPath(); + break; + case "BF": BellmanFordAlgorithm BF = new BellmanFordAlgorithm(data); sol = BF.doRun(); resu = sol.getPath(); + break; default: - System.out.println("no known algorithm"); + if (verbose == 1) { System.out.println("no known algorithm");} break; } - return resu; } public static int comparePath(Path p1, Path p2,boolean time){ + // true if both are null or if they have + // - the same time cost + // - the same length if (p1 == null){ if (p2 == null){ return 1; @@ -96,66 +109,102 @@ public class Launch { return 0; } } - if(time) - if (Double.compare(p1.getMinimumTravelTime(),p2.getMinimumTravelTime())==0) { + + + if(time) { + if (Double.compare(p1.getMinimumTravelTime(), p2.getMinimumTravelTime()) == 0) { return 1; - } - else - { + } else { return 0; } - else - if (Float.compare(p1.getLength(),p2.getLength())==0) { + }else{ + if (Float.compare(p1.getLength(), p2.getLength()) == 0) { return 1; - } - else - { + } else { return 0; } + } + } + + private static void displayResult(String algo, int justeD, int nbTest, long time){ + if (verbose == 1) { + System.out.println( + algo + " : number of good tests : " + Integer.toString(justeD) + "/" + + Integer.toString(nbTest * 2) + ". Total execution time : " + Long.toString(time) + "ms"); + } } - - private static int test(Graph graph, String testType,Drawing drawing){ - int Id1 = (int) Math.floor(Math.random()*graph.size()); - int Id2 = (int) Math.floor(Math.random()*graph.size()); + private static int test(Graph graph, String testType,Drawing drawing, int id1, int id2){ int resu = 0; - System.out.println("testing with nodes " + Id1 + " and " + Id2); - if (comparePath(createTestPath(graph, Id1, Id2, testType),createTestPath(graph, Id1, Id2, "BF"), true) == 0) { - resu++; + long endTime; + long startTime; + if (verbose == 1) { System.out.print("testing " + testType +" with nodes " + id1 + " and " + id2);} + + Path pathAlgo = null; + + if (testType == "A*"){ + + // times the run of the algorithm + + startTime = System.currentTimeMillis(); + pathAlgo = createTestPath(graph, id1, id2, "A*"); + endTime = System.currentTimeMillis(); + + if (verbose == 2){System.out.println(endTime-startTime);} + timeA += (endTime-startTime); + } else { + + // times the run of the algorithm + + startTime = System.currentTimeMillis(); + pathAlgo = createTestPath(graph, id1, id2, "D"); + endTime = System.currentTimeMillis(); + timeD += (endTime-startTime); + if (verbose == 2){if (pathAlgo != null) {System.out.print(pathAlgo.getLength()+","+(endTime-startTime) + ",");}} } - else - { + + Path pathBF = createTestPath(graph, id1, id2, "BF"); + + + // tests if the results are the same in terms of time and length + if (comparePath(pathAlgo, pathBF, true) == 1) { resu++; } - if (comparePath(createTestPath(graph, Id1, Id2, "D"),createTestPath(graph, Id1, Id2, "BF"), false) == 0) { + if (comparePath(pathAlgo, pathBF,false) == 1) { resu++; } - else - { - resu++; - } - Path drawPath = createTestPath(graph, Id1, Id2, "BF"); + + // draw the path created on the map (purely visual) + Path drawPath = pathAlgo; if (drawPath != null){ if (!drawPath.isEmpty()){ - - Random rand = new Random(); - float r = rand.nextFloat(); - float g = rand.nextFloat(); - float b = rand.nextFloat(); - drawing.drawPath(drawPath,new Color(r, g, b)); + try { + if (testType == "A*") { + drawing.drawPath(drawPath, new Color(150, 0, 150)); + } else { + drawing.drawPath(drawPath, new Color(20, 200, 20)); + } + } catch (Exception e) {} + if (verbose == 1) { System.out.println(" ... Done (length : " + Float.toString(drawPath.getLength()) + " found in " + Long.toString(endTime-startTime) + " ms)");} } } return resu; } + + + + public static void main(String[] args) throws Exception { // Visit these directory to see the list of available files on Commetud. - final String mapName = "/home/rlacroix/Bureau/3MIC/Be Graphe/mapinsa/insa.mapgr"; + //final String mapName = "/home/rlacroix/Bureau/3MIC/Be Graphe/mapinsa/insa.mapgr"; + //final String mapName = "/home/rlacroix/Bureau/3MIC/Be Graphe/mapinsa/carre-dense.mapgr"; + final String mapName = "/home/rlacroix/Bureau/3MIC/Be Graphe/mapinsa/california.mapgr"; //final String pathName = "/home/rlacroix/Bureau/3MIC/Be Graphe/mapinsa/path_fr31insa_rangueil_r2.path"; // Create a graph reader. @@ -171,6 +220,8 @@ public class Launch { // TODO: Draw the graph on the drawing. drawing.drawGraph(graph); + + // TODO: Create a PathReader. //final PathReader pathReader = new BinaryPathReader( // new DataInputStream(new BufferedInputStream(new FileInputStream(pathName)))); @@ -181,20 +232,35 @@ public class Launch { // TODO: Draw the path. //drawing.drawPath(path); - System.out.println("==TESTS=="); - int nbTest = 10000; - int juste = 0; + int nbTest = 2000; + int justeD = 0; + int justeA = 0; + + if (verbose == 1) { System.out.println("== LAUNCHING " + nbTest + " TESTS ==");} for (int i = 0; i < nbTest; i++){ + // picks two nodes at random + int id1 = (int) Math.floor(Math.random()*graph.size()); + int id2 = (int) Math.floor(Math.random()*graph.size()); + if (i%10 == 0){ + // cleans the board every 10 runs and display the comparative runtimes drawing.clearOverlays(); + displayResult("Dijkstra",justeD,i,timeD); + displayResult("A*",justeA,i,timeA); + if (verbose == 1) { System.out.println("A* takes "+ Long.toString(100*(timeA+1)/(timeD+1)) +"% of Dijkstra's execution time");} } - juste += test(graph,"A*",drawing); + if (verbose == 1) { System.out.println("Test number " + Integer.toString(i));} + justeD += test(graph,"D",drawing, id1, id2); + justeA += test(graph,"A*",drawing,id1, id2); } - System.out.println( - "number of good tests : " + Integer.toString(juste) + "/" + Integer.toString(nbTest*2) - ); + if (verbose == 1) { System.out.println("===== Final Results =====");} + displayResult("Dijkstra",justeD,nbTest,timeD); + displayResult("A*",justeA,nbTest,timeA); + if (verbose == 1) { System.out.println("A* takes "+ Long.toString(100*timeA/timeD) +"% of Dijkstra's execution time");} + + } } diff --git a/be-graphes-model/.classpath b/be-graphes-model/.classpath index 4559ca0..9ba41a2 100644 --- a/be-graphes-model/.classpath +++ b/be-graphes-model/.classpath @@ -23,5 +23,22 @@ + + + + + + + + + + + + + + + + + diff --git a/be-graphes-model/src/main/java/org/insa/graphs/model/Path.java b/be-graphes-model/src/main/java/org/insa/graphs/model/Path.java index a3b6fba..0c94f22 100644 --- a/be-graphes-model/src/main/java/org/insa/graphs/model/Path.java +++ b/be-graphes-model/src/main/java/org/insa/graphs/model/Path.java @@ -36,16 +36,19 @@ public class Path { if (nodes.size() == 1) { return new Path(graph, nodes.get(0)); } - if (nodes.size() == 1) { - return new Path(graph); - } + List arcs = new ArrayList(); - for (int i = 0 ; i < nodes.size(); i++) { + + // we iterate over the list of nodes + for (int i = 0 ; i < nodes.size(); i++) { Node currNode = nodes.get(i); - if (i < nodes.size() -1) { + + if (i < nodes.size() -1) { // if it's not the last Node nextNode = nodes.get(i+1); if (currNode.hasSuccessors()) { Arc better = null; + + // we compare all the edges to pick the best one for (Arc j : currNode.getSuccessors()) { if (j.getDestination() == nextNode) { if (better == null || better.getMinimumTravelTime() > j.getMinimumTravelTime()) { @@ -53,6 +56,8 @@ public class Path { } } } + + // If it exists we add it else we throw an exception if (better == null) { throw (new IllegalArgumentException()); } else { @@ -80,19 +85,23 @@ public class Path { */ public static Path createShortestPathFromNodes(Graph graph, List nodes) throws IllegalArgumentException { + // if (nodes.size() == 1) { return new Path(graph, nodes.get(0)); } - if (nodes.size() == 1) { - return new Path(graph); - } + List arcs = new ArrayList(); + + // we iterate over the list of nodes for (int i = 0 ; i < nodes.size(); i++) { Node currNode = nodes.get(i); - if (i < nodes.size() -1) { + + if (i < nodes.size() -1) { // if it's not the last Node nextNode = nodes.get(i+1); if (currNode.hasSuccessors()) { Arc better = null; + + // we compare all the edges to pick the best one for (Arc j : currNode.getSuccessors()) { if (j.getDestination() == nextNode) { if (better == null || better.getLength() > j.getLength()) { @@ -100,6 +109,8 @@ public class Path { } } } + + // If it exists we add it else we throw an exception if (better == null) { throw (new IllegalArgumentException()); } else { @@ -253,17 +264,14 @@ public class Path { */ public boolean isValid() { Arc old = null; - // it is empty if (this.isEmpty()) { + // it is empty so true return true; } - // Origin is ok if ((this.origin != null) && (this.arcs.size() == 0)) { + // only origin is ok: single node (without arcs) return true; } - if (this.arcs.size() == 0) { - return false; - } // destination of the first one is the origin of the second node if (this.arcs.get(0).getOrigin() == this.origin) { for (Arc a : this.arcs) { @@ -292,6 +300,7 @@ public class Path { */ public float getLength() { float acc = 0; + // sum all of the lengths for (Arc l : this.arcs) { acc += l.getLength(); } @@ -309,7 +318,7 @@ public class Path { * */ public double getTravelTime(double speed) { - double speed2 = speed * 1000/3600; + double speed2 = speed * 1000/3600; // conversion from km/h to m/s return (this.getLength()/speed2); } @@ -322,6 +331,7 @@ public class Path { */ public double getMinimumTravelTime() { float acc = 0; + // sum all of the minimum travel times for (Arc l : this.arcs) { acc += l.getMinimumTravelTime(); } diff --git a/img.png b/img.png deleted file mode 100644 index e480af9..0000000 Binary files a/img.png and /dev/null differ diff --git a/img2.png b/img2.png deleted file mode 100644 index bf590e9..0000000 Binary files a/img2.png and /dev/null differ diff --git a/reponses.md b/reponses.md index e703154..412d38a 100644 --- a/reponses.md +++ b/reponses.md @@ -4,9 +4,9 @@ On a une liste de liste et non une matrice. L'avantage est de prendre bien moins ## Diagram UML Diagrame UML :
- + ## deuxieme diagram UML Diagrame UML :
- +