Compare commits
18 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d53cc298d9 | |||
| fa87e8d63b | |||
|
|
f42e7edf5f | ||
|
|
52a8945a91 | ||
|
|
f80f2a348c | ||
|
|
fcfa9e05eb | ||
| 8726dded7e | |||
| c3e188aab2 | |||
|
|
a9165c3bfc | ||
|
|
ae6bf5d339 | ||
| 6f126202ca | |||
| 684c8ea6ac | |||
| 6613be4663 | |||
| b65f6c27ca | |||
|
|
472b578692 | ||
|
|
ac08a9ded0 | ||
| 941ff07d89 | |||
| 2f523b12c3 |
6 changed files with 206 additions and 26 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -19,3 +19,4 @@ doc
|
||||||
*.mapgr
|
*.mapgr
|
||||||
*.path
|
*.path
|
||||||
*.tgz
|
*.tgz
|
||||||
|
/.metadata/
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,14 @@
|
||||||
package org.insa.graphs.algorithm.shortestpath;
|
package org.insa.graphs.algorithm.shortestpath;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
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.Path;
|
||||||
|
|
||||||
public class DijkstraAlgorithm extends ShortestPathAlgorithm {
|
public class DijkstraAlgorithm extends ShortestPathAlgorithm {
|
||||||
|
|
||||||
public DijkstraAlgorithm(ShortestPathData data) {
|
public DijkstraAlgorithm(ShortestPathData data) {
|
||||||
|
|
@ -12,11 +21,63 @@ public class DijkstraAlgorithm extends ShortestPathAlgorithm {
|
||||||
// retrieve data from the input problem (getInputData() is inherited from the
|
// retrieve data from the input problem (getInputData() is inherited from the
|
||||||
// parent class ShortestPathAlgorithm)
|
// parent class ShortestPathAlgorithm)
|
||||||
final ShortestPathData data = getInputData();
|
final ShortestPathData data = getInputData();
|
||||||
|
Graph graph = data.getGraph();
|
||||||
|
|
||||||
|
final int nbNodes = graph.size();
|
||||||
|
|
||||||
// variable that will contain the solution of the shortest path problem
|
// variable that will contain the solution of the shortest path problem
|
||||||
ShortestPathSolution solution = null;
|
ShortestPathSolution solution = null;
|
||||||
|
|
||||||
// TODO: implement the Dijkstra algorithm
|
// Initialize array of labels.
|
||||||
|
ArrayList<Label> labelsList = new ArrayList<Label>();
|
||||||
|
for (int i=0; i<nbNodes; i++) {
|
||||||
|
labelsList.add(new Label(graph.get(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Set cost of origin to zero
|
||||||
|
Label destinationNodeLabel = labelsList.get(data.getDestination().getId());
|
||||||
|
Label concurentNodeLabel = labelsList.get(data.getOrigin().getId());
|
||||||
|
concurentNodeLabel.setCoutRealise(0);
|
||||||
|
|
||||||
|
notifyOriginProcessed(data.getOrigin());
|
||||||
|
|
||||||
|
BinaryHeap<Label> labelsHeap = new BinaryHeap<Label>();
|
||||||
|
labelsHeap.insert(concurentNodeLabel);
|
||||||
|
|
||||||
|
boolean found = false;
|
||||||
|
while (!found && !labelsHeap.isEmpty()) {
|
||||||
|
concurentNodeLabel = labelsHeap.deleteMin();
|
||||||
|
if (!concurentNodeLabel.getMarque()) {
|
||||||
|
notifyNodeReached(concurentNodeLabel.getSommetCourant());
|
||||||
|
concurentNodeLabel.setMarque();
|
||||||
|
for (Arc arc : concurentNodeLabel.getSommetCourant().getSuccessors()) {
|
||||||
|
Label successorLabel = labelsList.get(arc.getDestination().getId());
|
||||||
|
Float newCost = arc.getLength() + concurentNodeLabel.getCost();
|
||||||
|
if (newCost < successorLabel.getCost()) {
|
||||||
|
successorLabel.setPere(arc);
|
||||||
|
successorLabel.setCoutRealise(newCost);
|
||||||
|
labelsHeap.insert(successorLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (destinationNodeLabel.getMarque()) {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyDestinationReached(data.getDestination());
|
||||||
|
|
||||||
|
ArrayList<Arc> pathArcs = new ArrayList<Arc>();
|
||||||
|
concurentNodeLabel = destinationNodeLabel;
|
||||||
|
while(concurentNodeLabel.getPere() != null) {
|
||||||
|
pathArcs.add(0, concurentNodeLabel.getPere());
|
||||||
|
concurentNodeLabel = labelsList.get(concurentNodeLabel.getPere().getOrigin().getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collections.reverse(pathArcs);
|
||||||
|
|
||||||
|
solution = new ShortestPathSolution(data, Status.OPTIMAL, new Path(graph, pathArcs));
|
||||||
|
|
||||||
// when the algorithm terminates, return the solution that has been found
|
// when the algorithm terminates, return the solution that has been found
|
||||||
return solution;
|
return solution;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
package org.insa.graphs.algorithm.shortestpath;
|
||||||
|
|
||||||
|
import org.insa.graphs.model.Arc;
|
||||||
|
import org.insa.graphs.model.Node;
|
||||||
|
|
||||||
|
public class Label implements Comparable<Label> {
|
||||||
|
|
||||||
|
private Node sommetCourant;
|
||||||
|
|
||||||
|
private Boolean marque;
|
||||||
|
|
||||||
|
private float coutRealise;
|
||||||
|
|
||||||
|
private Arc pere;
|
||||||
|
|
||||||
|
public Label(Node sommetCourant) {
|
||||||
|
this.sommetCourant = sommetCourant;
|
||||||
|
this.marque = false;
|
||||||
|
this.coutRealise = Float.POSITIVE_INFINITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node getSommetCourant() {
|
||||||
|
return sommetCourant;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getMarque() {
|
||||||
|
return marque;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMarque() {
|
||||||
|
this.marque = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Arc getPere() {
|
||||||
|
return pere;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPere(Arc pere) {
|
||||||
|
this.pere = pere;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public double getCoutRealise() {
|
||||||
|
// return coutRealise;
|
||||||
|
// }
|
||||||
|
|
||||||
|
public void setCoutRealise(float nouveauCout) {
|
||||||
|
this.coutRealise = nouveauCout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getCost() {
|
||||||
|
return coutRealise;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Label o) {
|
||||||
|
return Double.compare(this.coutRealise, o.getCost()) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -134,7 +134,13 @@ public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove(E x) throws ElementNotFoundException {
|
public void remove(E x) throws ElementNotFoundException {
|
||||||
// TODO:
|
int index = this.array.indexOf(x);
|
||||||
|
if (index == -1 || index >= this.currentSize) { throw new ElementNotFoundException(x); }
|
||||||
|
E lastItem = this.array.get(--this.currentSize);
|
||||||
|
this.arraySet(index, lastItem);
|
||||||
|
this.percolateUp(index);
|
||||||
|
index = this.array.indexOf(lastItem);
|
||||||
|
this.percolateDown(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import org.insa.graphs.gui.drawing.components.BasicDrawing;
|
||||||
import org.insa.graphs.model.Graph;
|
import org.insa.graphs.model.Graph;
|
||||||
import org.insa.graphs.model.Path;
|
import org.insa.graphs.model.Path;
|
||||||
import org.insa.graphs.model.io.BinaryGraphReader;
|
import org.insa.graphs.model.io.BinaryGraphReader;
|
||||||
|
import org.insa.graphs.model.io.BinaryPathReader;
|
||||||
import org.insa.graphs.model.io.GraphReader;
|
import org.insa.graphs.model.io.GraphReader;
|
||||||
import org.insa.graphs.model.io.PathReader;
|
import org.insa.graphs.model.io.PathReader;
|
||||||
|
|
||||||
|
|
@ -57,23 +58,26 @@ public class Launch {
|
||||||
try (final GraphReader reader = new BinaryGraphReader(new DataInputStream(
|
try (final GraphReader reader = new BinaryGraphReader(new DataInputStream(
|
||||||
new BufferedInputStream(new FileInputStream(mapName))))) {
|
new BufferedInputStream(new FileInputStream(mapName))))) {
|
||||||
|
|
||||||
// TODO: read the graph
|
// DONE: read the graph
|
||||||
graph = null;
|
graph = reader.read();
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the drawing
|
// create the drawing
|
||||||
final Drawing drawing = createDrawing();
|
final Drawing drawing = createDrawing();
|
||||||
|
|
||||||
// TODO: draw the graph on the drawing
|
// DONE: draw the graph on the drawing
|
||||||
|
drawing.drawGraph(graph);
|
||||||
|
|
||||||
// TODO: create a path reader
|
// DONE: create a path reader
|
||||||
try (final PathReader pathReader = null) {
|
try (final PathReader pathReader = new BinaryPathReader(new DataInputStream(
|
||||||
|
new BufferedInputStream(new FileInputStream(pathName))))) {
|
||||||
|
|
||||||
// TODO: read the path
|
// DONE: read the path
|
||||||
path = null;
|
path = pathReader.readPath(graph);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: draw the path on the drawing
|
// DONE: draw the path on the drawing
|
||||||
|
drawing.drawPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@ package org.insa.graphs.model;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
|
|
@ -25,12 +27,32 @@ public class Path {
|
||||||
* @return A path that goes through the given list of nodes.
|
* @return A path that goes through the given list of nodes.
|
||||||
* @throws IllegalArgumentException If the list of nodes is not valid, i.e. two
|
* @throws IllegalArgumentException If the list of nodes is not valid, i.e. two
|
||||||
* consecutive nodes in the list are not connected in the graph.
|
* consecutive nodes in the list are not connected in the graph.
|
||||||
* @deprecated Need to be implemented.
|
|
||||||
*/
|
*/
|
||||||
public static Path createFastestPathFromNodes(Graph graph, List<Node> nodes)
|
public static Path createFastestPathFromNodes(Graph graph, List<Node> nodes)
|
||||||
throws IllegalArgumentException {
|
throws IllegalArgumentException {
|
||||||
List<Arc> arcs = new ArrayList<Arc>();
|
List<Arc> arcs = new ArrayList<Arc>();
|
||||||
// TODO:
|
|
||||||
|
if (nodes.size() == 1) { return new Path(graph, nodes.get(0)); }
|
||||||
|
|
||||||
|
for (int i = 0; i < nodes.size() - 1; i++) {
|
||||||
|
Arc bestArc = null;
|
||||||
|
double bestSpeed = Double.MAX_VALUE;
|
||||||
|
for (Arc arcsucc : nodes.get(i).getSuccessors()) {
|
||||||
|
if (arcsucc.getDestination().equals(nodes.get(i+1))) {
|
||||||
|
int succspeed = arcsucc.getRoadInformation().getMaximumSpeed();
|
||||||
|
if (arcsucc.getTravelTime(succspeed) < bestSpeed) {
|
||||||
|
bestArc = arcsucc;
|
||||||
|
bestSpeed = arcsucc.getTravelTime(succspeed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bestArc == null) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
} else {
|
||||||
|
arcs.add(bestArc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return new Path(graph, arcs);
|
return new Path(graph, arcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,12 +65,20 @@ public class Path {
|
||||||
* @return A path that goes through the given list of nodes.
|
* @return A path that goes through the given list of nodes.
|
||||||
* @throws IllegalArgumentException If the list of nodes is not valid, i.e. two
|
* @throws IllegalArgumentException If the list of nodes is not valid, i.e. two
|
||||||
* consecutive nodes in the list are not connected in the graph.
|
* consecutive nodes in the list are not connected in the graph.
|
||||||
* @deprecated Need to be implemented.
|
|
||||||
*/
|
*/
|
||||||
public static Path createShortestPathFromNodes(Graph graph, List<Node> nodes)
|
public static Path createShortestPathFromNodes(Graph graph, List<Node> nodes)
|
||||||
throws IllegalArgumentException {
|
throws IllegalArgumentException {
|
||||||
|
if (nodes.size() == 0) {
|
||||||
|
return new Path(graph);
|
||||||
|
}
|
||||||
|
if (nodes.size() == 1) {
|
||||||
|
return new Path(graph, nodes.getFirst());
|
||||||
|
}
|
||||||
List<Arc> arcs = new ArrayList<Arc>();
|
List<Arc> arcs = new ArrayList<Arc>();
|
||||||
// TODO:
|
for (int i=0; i<nodes.size()-1; i++) {
|
||||||
|
int j = i;
|
||||||
|
arcs.add(nodes.get(i).getSuccessors().stream().filter(a -> a.getDestination().equals(nodes.get(j+1))).min(Comparator.comparing(Arc::getLength)).orElseThrow(() -> new IllegalArgumentException("Invalid list of nodes")));
|
||||||
|
}
|
||||||
return new Path(graph, arcs);
|
return new Path(graph, arcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,22 +214,34 @@ public class Path {
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @return true if the path is valid, false otherwise.
|
* @return true if the path is valid, false otherwise.
|
||||||
* @deprecated Need to be implemented.
|
|
||||||
*/
|
*/
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
// TODO:
|
|
||||||
return false;
|
if (this.isEmpty()) { return true; }
|
||||||
|
if (this.size() == 1 && this.arcs.isEmpty()) { return true; }
|
||||||
|
if (!this.arcs.get(0).getOrigin().equals(this.origin)) { return false; }
|
||||||
|
|
||||||
|
Boolean good = true;
|
||||||
|
for (int i = 0; i < this.arcs.size() - 1; i++) {
|
||||||
|
if (!this.arcs.get(i).getDestination().equals(this.arcs.get(i+1).getOrigin())) {
|
||||||
|
good = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return good;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the length of this path (in meters).
|
* Compute the length of this path (in meters).
|
||||||
*
|
*
|
||||||
* @return Total length of the path (in meters).
|
* @return Total length of the path (in meters).
|
||||||
* @deprecated Need to be implemented.
|
|
||||||
*/
|
*/
|
||||||
public float getLength() {
|
public float getLength() {
|
||||||
// TODO:
|
float result = 0f;
|
||||||
return 0;
|
for (Arc arc : arcs) {
|
||||||
|
result += arc.getLength();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -208,11 +250,13 @@ public class Path {
|
||||||
* @param speed Speed to compute the travel time.
|
* @param speed Speed to compute the travel time.
|
||||||
* @return Time (in seconds) required to travel this path at the given speed (in
|
* @return Time (in seconds) required to travel this path at the given speed (in
|
||||||
* kilometers-per-hour).
|
* kilometers-per-hour).
|
||||||
* @deprecated Need to be implemented.
|
|
||||||
*/
|
*/
|
||||||
public double getTravelTime(double speed) {
|
public double getTravelTime(double speed) {
|
||||||
// TODO:
|
double ttime = 0;
|
||||||
return 0;
|
for (Arc thisArc : arcs) {
|
||||||
|
ttime += thisArc.getTravelTime(speed);
|
||||||
|
}
|
||||||
|
return ttime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -220,11 +264,15 @@ public class Path {
|
||||||
* every arc.
|
* every arc.
|
||||||
*
|
*
|
||||||
* @return Minimum travel time to travel this path (in seconds).
|
* @return Minimum travel time to travel this path (in seconds).
|
||||||
* @deprecated Need to be implemented.
|
|
||||||
*/
|
*/
|
||||||
public double getMinimumTravelTime() {
|
public double getMinimumTravelTime() {
|
||||||
// TODO:
|
double ttime = 0;
|
||||||
return 0;
|
int maxSpeed;
|
||||||
|
for (Arc thisArc : arcs) {
|
||||||
|
maxSpeed = thisArc.getRoadInformation().getMaximumSpeed();
|
||||||
|
ttime += thisArc.getTravelTime(maxSpeed);
|
||||||
|
}
|
||||||
|
return ttime;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue