algorithme de dijkstra + commentaires

This commit is contained in:
Cavailles Kevin 2020-04-02 21:37:47 +02:00
parent 4b9dbd1b30
commit dab81d1bca
5 changed files with 223 additions and 32 deletions

View file

@ -1,17 +1,121 @@
package org.insa.graphs.algorithm.shortestpath; package org.insa.graphs.algorithm.shortestpath;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.PriorityQueue;
import org.insa.graphs.algorithm.AbstractSolution.Status;
import org.insa.graphs.algorithm.utils.BinaryHeap;
import org.insa.graphs.model.Arc;
import org.insa.graphs.model.Graph;
import org.insa.graphs.model.Node;
import org.insa.graphs.model.Path;
public class DijkstraAlgorithm extends ShortestPathAlgorithm { public class DijkstraAlgorithm extends ShortestPathAlgorithm {
public DijkstraAlgorithm(ShortestPathData data) { public DijkstraAlgorithm(ShortestPathData data) {
super(data); super(data);
} }
@Override @Override
protected ShortestPathSolution doRun() { protected ShortestPathSolution doRun() {
final ShortestPathData data = getInputData(); final ShortestPathData data = getInputData();
ShortestPathSolution solution = null; Graph graph = data.getGraph();
// TODO:
return solution; final int nbNodes = graph.size();
}
// Create the heap and a static array to store the labels
org.insa.graphs.algorithm.utils.PriorityQueue<Label> labelsHeap = new BinaryHeap<>();
Label labelsList[] = new Label[nbNodes];
Arrays.fill(labelsList, null);
//Put the origin in the heap
Node origin = data.getOrigin();
labelsList[origin.getId()] = new Label(data.getOrigin(), 0, null);
labelsHeap.insert(new Label(origin, 0, null));
// Notify observers about the first event (origin processed).
notifyOriginProcessed(data.getOrigin());
// Initialize array of predecessors.
Arc[] predecessorArcs = new Arc[nbNodes];
Label current, next;
// While the heap has elements
while (!labelsHeap.isEmpty()) {
// Remove the min
current = labelsHeap.findMin();
try {
labelsHeap.remove(current);
} catch (Exception e) {
System.out.println("fatal error");
}
current.setMark();
// Iterate over the arc of the removed element
for (Arc arc : graph.get(current.getCurrent().getId()).getSuccessors()) {
if (!data.isAllowed(arc)) {
continue;
}
next = labelsList[arc.getDestination().getId()];
//If the destination of an arc does not exist or is not marked
if ( next != null && next.isMarked()) {
continue;
}
// Either create it or check if the associated cost can be reduced
if (next == null) {
next = new Label(arc.getDestination(),current.getCost() + data.getCost(arc), arc);
labelsList[arc.getDestination().getId()] = next;
labelsHeap.insert(next);
notifyNodeReached(arc.getDestination());
}else{
if (next.getCost() > current.getCost() + data.getCost(arc)) {
next.setCost(current.getCost() + data.getCost(arc));
next.setFather(arc);
notifyNodeReached(arc.getDestination());
}
}
}
}
ShortestPathSolution solution = null;
//Check if the destination has been reached from the source
if (labelsList[data.getDestination().getId()] == null) {
solution = new ShortestPathSolution(data, Status.INFEASIBLE);
} else {
// The destination has been found, notify the observers.
notifyDestinationReached(data.getDestination());
// Create the path from the array of predecessors...
ArrayList<Arc> arcs = new ArrayList<>();
Arc arc = labelsList[data.getDestination().getId()].getFather();
while (arc != null) {
arcs.add(arc);
arc = labelsList[arc.getOrigin().getId()].getFather();
}
// Reverse the path...
Collections.reverse(arcs);
// Create the final solution.
solution = new ShortestPathSolution(data, Status.OPTIMAL, new Path(graph, arcs));
}
return solution;
}
} }

View file

@ -0,0 +1,54 @@
package org.insa.graphs.algorithm.shortestpath;
import org.insa.graphs.model.Arc;
import org.insa.graphs.model.Node;
import org.insa.graphs.model.Path;
public class Label implements Comparable<Label>{
private Node sommetCourant;
private boolean marque;
private double cout;
private Arc pere;
public Label(Node sommetCourant, double cout, Arc pere) {
this.sommetCourant = sommetCourant;
this.marque = false;
this.cout = cout;
this.pere = pere;
}
public Node getCurrent() {
return this.sommetCourant;
}
public double getCost() {
return this.cout;
}
public Arc getFather() {
return this.pere;
}
public void setMark() {
this.marque = true;
}
public void setFather(Arc father) {
this.pere = father;
}
public void setCost(double cost) {
this.cout = cost;
}
public boolean isMarked() {
return this.marque;
}
@Override
public String toString() {
return ""+this.sommetCourant.getId();
}
@Override
public int compareTo(Label o) {
return (int) (this.getCost()-o.getCost() ) ;
}
}

View file

@ -1,6 +1,10 @@
package org.insa.graphs.algorithm.utils; package org.insa.graphs.algorithm.utils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
/** /**
* Implements a binary heap containing elements of type E. * Implements a binary heap containing elements of type E.
@ -11,6 +15,9 @@ import java.util.ArrayList;
* @author Mark Allen Weiss * @author Mark Allen Weiss
* @author DLB * @author DLB
*/ */
public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> { public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
// Number of elements in heap. // Number of elements in heap.
@ -50,6 +57,7 @@ public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
else { else {
this.array.set(index, value); this.array.set(index, value);
} }
} }
/** /**
@ -136,13 +144,20 @@ public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
} }
@Override @Override
/**
* Remove the element x from the array if it exists
* Raise ElementNotFoundException otherwise
*/
public void remove(E x) throws ElementNotFoundException { public void remove(E x) throws ElementNotFoundException {
if(this.isEmpty()){ if(this.isEmpty()){
throw new ElementNotFoundException(x); throw new ElementNotFoundException(x);
} }
int index = -1; int index = -1;
//Iterate over the array and check if the x exists
for(int i=0; i<this.currentSize;i++) { for(int i=0; i<this.currentSize;i++) {
if(this.array.get(i).equals(x)) { if(this.array.get(i).equals(x)) {
index = i; index = i;
@ -154,8 +169,10 @@ public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
throw new ElementNotFoundException(x); throw new ElementNotFoundException(x);
} }
//If it exists, it is replaced by the "last" element
E lastItem = this.array.get(--this.currentSize); E lastItem = this.array.get(--this.currentSize);
this.arraySet(index, lastItem); this.arraySet(index, lastItem);
//The switched element is then sorted
this.percolateDown(index); this.percolateDown(index);
this.percolateUp(index); this.percolateUp(index);

View file

@ -50,28 +50,38 @@ public class Launch {
final String mapName = "/Users/Kevin/Desktop/programmation/java_files/Maps/europe/france/insa.mapgr"; final String mapName = "/Users/Kevin/Desktop/programmation/java_files/Maps/europe/france/insa.mapgr";
final String pathName = "/Users/Kevin/Desktop/programmation/java_files/Paths/path_fr31insa_rangueil_insa.path"; final String pathName = "/Users/Kevin/Desktop/programmation/java_files/Paths/path_fr31insa_rangueil_insa.path";
// Create a graph reader.
final GraphReader reader = new BinaryGraphReader(
new DataInputStream(new BufferedInputStream(new FileInputStream(mapName))));
// TODO: Read the graph. // TODO: Read the graph.
final Graph graph = reader.read(); final Graph graph;
// Create the drawing: // Create the drawing:
final Drawing drawing = createDrawing(); final Drawing drawing;
// TODO: Draw the graph on the drawing.
drawing.drawGraph(graph); try (GraphReader reader = new BinaryGraphReader(new DataInputStream(
new BufferedInputStream(new FileInputStream(mapName))))) {
// TODO: Read the graph.
graph = reader.read();
// Create the drawing:
drawing = createDrawing();
// TODO: Draw the graph on the drawing.
drawing.drawGraph(graph);
}
// TODO: Create a PathReader. // TODO: Create a PathReader.
final PathReader pathReader = new BinaryPathReader( try (PathReader pathReader = new BinaryPathReader(
new DataInputStream( new BufferedInputStream(new FileInputStream(pathName)))); new DataInputStream( new BufferedInputStream(new FileInputStream(pathName))))) {
// TODO: Read the path. // TODO: Read the path.
final Path path = pathReader.readPath(graph); final Path path = pathReader.readPath(graph);
// TODO: Draw the path. // TODO: Draw the path.
drawing.drawPath(path); drawing.drawPath(path);
}
} }
} }

View file

@ -33,10 +33,6 @@ public class Path {
public static Path createFastestPathFromNodes(Graph graph, List<Node> nodes) public static Path createFastestPathFromNodes(Graph graph, List<Node> nodes)
throws IllegalArgumentException { throws IllegalArgumentException {
Arc currentArc = null;
List<Arc> arcs = new ArrayList<Arc>();
double travelTime = 9999;
if(nodes.size() == 0) { if(nodes.size() == 0) {
return new Path(graph); return new Path(graph);
} }
@ -44,6 +40,11 @@ public class Path {
return new Path(graph, nodes.get(0) ); return new Path(graph, nodes.get(0) );
} }
Arc currentArc = null;
List<Arc> arcs = new ArrayList<Arc>();
double travelTime = 9999;
//Get the arc with the minimum travel time for each node
for(int i=0; i<nodes.size()-1;i++) { for(int i=0; i<nodes.size()-1;i++) {
for(Arc a : nodes.get(i).getSuccessors()) { for(Arc a : nodes.get(i).getSuccessors()) {
if(a.getMinimumTravelTime() < travelTime if(a.getMinimumTravelTime() < travelTime
@ -52,6 +53,7 @@ public class Path {
travelTime = a.getMinimumTravelTime(); travelTime = a.getMinimumTravelTime();
} }
} }
//raise an exception if two consecutive arcs are not linked
if(currentArc == null) { if(currentArc == null) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
@ -78,9 +80,7 @@ public class Path {
public static Path createShortestPathFromNodes(Graph graph, List<Node> nodes) public static Path createShortestPathFromNodes(Graph graph, List<Node> nodes)
throws IllegalArgumentException { throws IllegalArgumentException {
Arc currentArc = null;
List<Arc> arcs = new ArrayList<Arc>();
float distanceMin = 9999;
if(nodes.size() == 0) { if(nodes.size() == 0) {
return new Path(graph); return new Path(graph);
@ -89,6 +89,11 @@ public class Path {
return new Path(graph, nodes.get(0) ); return new Path(graph, nodes.get(0) );
} }
Arc currentArc = null;
List<Arc> arcs = new ArrayList<Arc>();
float distanceMin = 9999;
//Get the arc with the minimal distance for each node
for(int i=0; i<nodes.size()-1;i++) { for(int i=0; i<nodes.size()-1;i++) {
for(Arc a : nodes.get(i).getSuccessors()) { for(Arc a : nodes.get(i).getSuccessors()) {
if(a.getLength() < distanceMin if(a.getLength() < distanceMin
@ -97,6 +102,7 @@ public class Path {
distanceMin = a.getLength(); distanceMin = a.getLength();
} }
} }
//raise an exception if two consecutive arcs are not linked
if(currentArc == null) { if(currentArc == null) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }