Compare commits

...

28 commits
main ... main

Author SHA1 Message Date
771dfb96b2 Dijkstra with Hashmap 2026-05-12 17:54:35 +02:00
Yanis Mahé
bf2c35eadd AStar done :) :hapy: 2026-05-12 17:02:21 +02:00
d203e56988 Update again LabelStar 2026-05-12 16:10:51 +02:00
dee66c6242 Update LabelStar 2026-05-12 15:59:25 +02:00
91e95f7260 LabelStar Started 2026-05-12 15:48:24 +02:00
Yanis Mahé
5de1caec47 Finished ShortestPathTest for Bellman and Dijkstra 2026-05-12 15:45:53 +02:00
3df94a9cec Update Dijkstra - verifiy if infeasible 2026-05-06 18:10:39 +02:00
Yanis Mahé
07029f751d Init ShortestPathTest, testInsaBikini et testCheminInexistant 2026-05-06 18:08:38 +02:00
23be38ee2b Update Dijkstra (all notify working) 2026-05-06 16:37:34 +02:00
e249625793 Dijkstra Updated (pour le côut et les limitations) 2026-05-06 16:20:23 +02:00
d53cc298d9 DONE Dijsktra 2026-04-20 06:50:49 +02:00
fa87e8d63b NOT FINISHED : Dijkstra 2026-04-20 06:39:27 +02:00
Yanis Mahé
f42e7edf5f NOT FINISHED : Dijkstra, changed Label 2026-04-16 10:44:48 +02:00
Yanis Mahé
52a8945a91 Added constructor for label and changed coutRealise to double 2026-04-16 09:47:29 +02:00
Yanis Mahé
f80f2a348c Added getCoutRealie for Label 2026-04-16 09:38:23 +02:00
Yanis Mahé
fcfa9e05eb Finishes label (?) 2026-04-16 09:36:24 +02:00
8726dded7e Start of Label 2026-04-16 09:33:04 +02:00
c3e188aab2 done remove() 2026-04-16 09:10:21 +02:00
Yanis Mahé
a9165c3bfc Merge branch 'main' of https://git.etud.insa-toulouse.fr/ymahe/BE-Graphes-MAHE-MOLL 2026-04-15 18:12:33 +02:00
Yanis Mahé
ae6bf5d339 Path.createShortestPathFromNodes 2026-04-15 18:08:25 +02:00
6f126202ca done Launch.java 2026-04-15 18:08:01 +02:00
684c8ea6ac made createFastestPathFromNodes() 2026-04-15 17:38:08 +02:00
6613be4663 update isValid() 2026-04-15 17:03:43 +02:00
b65f6c27ca made isValid() 2026-04-15 17:01:33 +02:00
Yanis Mahé
472b578692 Add /.metadata/ to.gitignore 2026-04-15 16:46:21 +02:00
Yanis Mahé
ac08a9ded0 path.getLength 2026-04-15 16:46:21 +02:00
941ff07d89 made getMinimumTravelTime() 2026-04-15 16:36:31 +02:00
2f523b12c3 made getTravelTime() 2026-04-15 16:33:02 +02:00
9 changed files with 397 additions and 26 deletions

1
.gitignore vendored
View file

@ -19,3 +19,4 @@ doc
*.mapgr
*.path
*.tgz
/.metadata/

View file

@ -1,9 +1,17 @@
package org.insa.graphs.algorithm.shortestpath;
import org.insa.graphs.model.Node;
public class AStarAlgorithm extends DijkstraAlgorithm {
public AStarAlgorithm(ShortestPathData data) {
super(data);
}
@Override
protected Label createLabel(Node node) {
return new LabelStar(node, getInputData().getDestination());
}
}

View file

@ -1,23 +1,95 @@
package org.insa.graphs.algorithm.shortestpath;
import java.util.ArrayList;
import java.util.HashMap;
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 DijkstraAlgorithm(ShortestPathData data) {
super(data);
}
protected Label createLabel(Node node) {
return new Label(node);
}
@Override
protected ShortestPathSolution doRun() {
// retrieve data from the input problem (getInputData() is inherited from the
// parent class ShortestPathAlgorithm)
final ShortestPathData data = getInputData();
Graph graph = data.getGraph();
// variable that will contain the solution of the shortest path problem
ShortestPathSolution solution = null;
// TODO: implement the Dijkstra algorithm
// Initialize hashmap of labels.
HashMap<Integer, Label> labelsMap = new HashMap<Integer, Label>();
// Set cost of origin to zero
Label concurentNodeLabel = createLabel(data.getOrigin());
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 (!labelsMap.containsKey(concurentNodeLabel.getSommetCourant().getId())) {
notifyNodeMarked(concurentNodeLabel.getSommetCourant());
labelsMap.put(concurentNodeLabel.getSommetCourant().getId(), concurentNodeLabel);
for (Arc arc : concurentNodeLabel.getSommetCourant().getSuccessors()) {
// Small test to check allowed roads...
if (!data.isAllowed(arc)) {
continue;
}
Label successorLabel = createLabel(arc.getDestination());
Double newCost = concurentNodeLabel.getCoutRealise() + data.getCost(arc);
successorLabel.setPere(arc);
successorLabel.setCoutRealise(newCost);
labelsHeap.insert(successorLabel);
notifyNodeReached(successorLabel.getSommetCourant());
}
if (labelsMap.containsKey(data.getDestination().getId())) {
found = true;
}
}
}
// Destination has no predecessor, the solution is infeasible...
if (concurentNodeLabel.getPere() == null) {
return new ShortestPathSolution(data, Status.INFEASIBLE);
}
Label destinationNodeLabel = labelsMap.get(data.getDestination().getId());
notifyDestinationReached(data.getDestination());
ArrayList<Arc> pathArcs = new ArrayList<Arc>();
concurentNodeLabel = destinationNodeLabel;
while(concurentNodeLabel.getPere() != null) {
pathArcs.add(0, concurentNodeLabel.getPere());
concurentNodeLabel = labelsMap.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
return solution;
}

View file

@ -0,0 +1,76 @@
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 double coutRealise;
private double coutEstime;
private Arc pere;
public Label(Node sommetCourant) {
this.sommetCourant = sommetCourant;
this.marque = false;
this.coutRealise = Double.POSITIVE_INFINITY;
this.coutEstime = 0;
}
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 double getCoutEstime() {
return coutEstime;
}
public void setCoutRealise(double nouveauCout) {
this.coutRealise = nouveauCout;
}
public void setCoutEstime(double nouveauCout) {
this.coutEstime = nouveauCout;
}
public double getCost() {
return coutRealise + coutEstime;
}
@Override
public int compareTo(Label o) {
if (this.getCost() == o.getCost()) {
return Double.compare(this.getCoutEstime(), o.getCoutEstime());
}
else {
return Double.compare(this.getCost(), o.getCost());
}
}
}

View file

@ -0,0 +1,13 @@
package org.insa.graphs.algorithm.shortestpath;
import org.insa.graphs.model.Node;
import org.insa.graphs.model.Point;
public class LabelStar extends Label {
public LabelStar(Node sommetCourant, Node sommetDestination) {
super(sommetCourant);
this.setCoutEstime(Point.distance(this.getSommetCourant().getPoint(), sommetDestination.getPoint()));
}
}

View file

@ -134,7 +134,13 @@ public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
@Override
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

View file

@ -0,0 +1,143 @@
package org.insa.graphs.algorithm.utils;
import static org.junit.Assert.*;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
import org.insa.graphs.algorithm.AbstractSolution.Status;
import org.insa.graphs.algorithm.ArcInspector;
import org.insa.graphs.algorithm.ArcInspectorFactory;
import org.insa.graphs.algorithm.shortestpath.BellmanFordAlgorithm;
import org.insa.graphs.algorithm.shortestpath.DijkstraAlgorithm;
import org.insa.graphs.algorithm.shortestpath.ShortestPathAlgorithm;
import org.insa.graphs.algorithm.shortestpath.ShortestPathData;
import org.insa.graphs.algorithm.shortestpath.ShortestPathSolution;
import org.insa.graphs.model.Graph;
import org.insa.graphs.model.Path;
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.PathReader;
import org.junit.BeforeClass;
import org.junit.Test;
public class ShortestPathTest {
final static String midiPyreneesFile = "/mnt/commetud/3emeAnneeMIC/Graphes-et-Algorithmes/Maps/midi-pyrenees.mapgr";
final static String hauteGaronneFile = "/mnt/commetud/3emeAnneeMIC/Graphes-et-Algorithmes/Maps/haute-garonne.mapgr";
final static String insaFile = "/mnt/commetud/3emeAnneeMIC/Graphes-et-Algorithmes/Maps/insa.mapgr";
final static String belgiqueFile = "/mnt/commetud/3emeAnneeMIC/Graphes-et-Algorithmes/Maps/belgium.mapgr";
final static String insaBikiniCanalPathFile = "/mnt/commetud/3emeAnneeMIC/Graphes-et-Algorithmes/Paths/path_fr31_insa_bikini_canal.path";
static Graph midiPyrenees;
static Graph hauteGaronne;
static Graph insa;
static Graph belgique;
static Path insaBikiniCanal;
static ArcInspector onlyPedestrianByTime;
static ArcInspector onlyCarsByLengthArcInspector;
static ArcInspector noFilterByLengthArcInspector;
@BeforeClass
public static void setUp() throws FileNotFoundException, IOException {
try (final GraphReader reader = new BinaryGraphReader(new DataInputStream(
new BufferedInputStream(new FileInputStream(midiPyreneesFile))))) {
midiPyrenees = reader.read();
}
try (final GraphReader reader = new BinaryGraphReader(new DataInputStream(
new BufferedInputStream(new FileInputStream(hauteGaronneFile))))) {
hauteGaronne = reader.read();
}
try (final GraphReader reader = new BinaryGraphReader(new DataInputStream(
new BufferedInputStream(new FileInputStream(insaFile))))) {
insa = reader.read();
}
try (final GraphReader reader = new BinaryGraphReader(new DataInputStream(
new BufferedInputStream(new FileInputStream(belgiqueFile))))) {
belgique = reader.read();
}
try (final PathReader pathReader = new BinaryPathReader(new DataInputStream(
new BufferedInputStream(new FileInputStream(insaBikiniCanalPathFile))))) {
insaBikiniCanal = pathReader.readPath(hauteGaronne);
}
List<ArcInspector> inspectors = ArcInspectorFactory.getAllFilters();
noFilterByLengthArcInspector = inspectors.get(0);
onlyCarsByLengthArcInspector = inspectors.get(1);
onlyPedestrianByTime = inspectors.get(3);
}
@Test
public void testCheminInsaBikiniCanal() { // En comparant avec un fichier path
ShortestPathData insaBikiniCanalPathData = new ShortestPathData(hauteGaronne, insaBikiniCanal.getOrigin(), insaBikiniCanal.getDestination(), noFilterByLengthArcInspector);
// System.out.println("" + insaBikiniCanal.getOrigin().getId() +" "+ insaBikiniCanal.getDestination().getId());
ShortestPathAlgorithm bellmanFord = new BellmanFordAlgorithm(insaBikiniCanalPathData);
ShortestPathAlgorithm dijkstra = new DijkstraAlgorithm(insaBikiniCanalPathData);
ShortestPathSolution solutionBellmanFord = bellmanFord.run();
ShortestPathSolution solutionDijkstra = dijkstra.run();
assertEquals(Status.OPTIMAL, solutionBellmanFord.getStatus());
assertEquals(Status.OPTIMAL, solutionDijkstra.getStatus());
assertEquals(insaBikiniCanal.getLength(), solutionBellmanFord.getPath().getLength(),1.0);
assertEquals(insaBikiniCanal.getLength(), solutionDijkstra.getPath().getLength(), 1.0);
assertEquals(insaBikiniCanal.getTravelTime(120), solutionBellmanFord.getPath().getTravelTime(120),1.0);
assertEquals(insaBikiniCanal.getTravelTime(120), solutionDijkstra.getPath().getTravelTime(120), 1.0);
}
@Test
public void testCheminInexistant() {
ShortestPathData cheminInexistant = new ShortestPathData(insa, insa.get(940), insa.get(702), onlyCarsByLengthArcInspector);
ShortestPathAlgorithm bellmanFord = new BellmanFordAlgorithm(cheminInexistant);
ShortestPathAlgorithm dijkstra = new DijkstraAlgorithm(cheminInexistant);
ShortestPathSolution solutionBellmanFord = bellmanFord.run();
ShortestPathSolution solutionDijkstra = dijkstra.run();
assertEquals(Status.INFEASIBLE, solutionBellmanFord.getStatus());
assertEquals(Status.INFEASIBLE, solutionDijkstra.getStatus());
}
@Test
public void testCheminLongueurNulle() {
ShortestPathData cheminInexistant = new ShortestPathData(insa, insa.get(940), insa.get(940), noFilterByLengthArcInspector);
ShortestPathAlgorithm bellmanFord = new BellmanFordAlgorithm(cheminInexistant);
ShortestPathAlgorithm dijkstra = new DijkstraAlgorithm(cheminInexistant);
ShortestPathSolution solutionBellmanFord = bellmanFord.run();
ShortestPathSolution solutionDijkstra = dijkstra.run();
assertEquals(Status.INFEASIBLE, solutionBellmanFord.getStatus());
assertEquals(Status.INFEASIBLE, solutionDijkstra.getStatus());
assertNull(solutionBellmanFord.getPath());
assertNull(solutionDijkstra.getPath());
}
@Test
public void testCheminLong() { // En comparant les deux algos
ShortestPathData cheminInexistant = new ShortestPathData(belgique, belgique.get(956754), belgique.get(842938), noFilterByLengthArcInspector);
ShortestPathAlgorithm bellmanFord = new BellmanFordAlgorithm(cheminInexistant);
ShortestPathAlgorithm dijkstra = new DijkstraAlgorithm(cheminInexistant);
ShortestPathSolution solutionBellmanFord = bellmanFord.run();
ShortestPathSolution solutionDijkstra = dijkstra.run();
assertEquals(solutionBellmanFord.getStatus(), solutionDijkstra.getStatus());
assertEquals(solutionBellmanFord.getPath().getLength(), solutionDijkstra.getPath().getLength(), 1.0);
assertEquals(solutionBellmanFord.getPath().getTravelTime(120), solutionDijkstra.getPath().getTravelTime(120), 1.0);
}
}

View file

@ -14,6 +14,7 @@ import org.insa.graphs.gui.drawing.components.BasicDrawing;
import org.insa.graphs.model.Graph;
import org.insa.graphs.model.Path;
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.PathReader;
@ -57,23 +58,26 @@ public class Launch {
try (final GraphReader reader = new BinaryGraphReader(new DataInputStream(
new BufferedInputStream(new FileInputStream(mapName))))) {
// TODO: read the graph
graph = null;
// DONE: read the graph
graph = reader.read();
}
// create the drawing
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
try (final PathReader pathReader = null) {
// DONE: create a path reader
try (final PathReader pathReader = new BinaryPathReader(new DataInputStream(
new BufferedInputStream(new FileInputStream(pathName))))) {
// TODO: read the path
path = null;
// DONE: read the path
path = pathReader.readPath(graph);
}
// TODO: draw the path on the drawing
// DONE: draw the path on the drawing
drawing.drawPath(path);
}
}

View file

@ -2,7 +2,9 @@ package org.insa.graphs.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Iterator;
/**
* <p>
@ -25,12 +27,32 @@ public class Path {
* @return A path that goes through the given list of nodes.
* @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.
*/
public static Path createFastestPathFromNodes(Graph graph, List<Node> nodes)
throws IllegalArgumentException {
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);
}
@ -43,12 +65,20 @@ public class Path {
* @return A path that goes through the given list of nodes.
* @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.
*/
public static Path createShortestPathFromNodes(Graph graph, List<Node> nodes)
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>();
// 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);
}
@ -184,22 +214,34 @@ public class Path {
* </ul>
*
* @return true if the path is valid, false otherwise.
* @deprecated Need to be implemented.
*/
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).
*
* @return Total length of the path (in meters).
* @deprecated Need to be implemented.
*/
public float getLength() {
// TODO:
return 0;
float result = 0f;
for (Arc arc : arcs) {
result += arc.getLength();
}
return result;
}
/**
@ -208,11 +250,13 @@ public class Path {
* @param speed Speed to compute the travel time.
* @return Time (in seconds) required to travel this path at the given speed (in
* kilometers-per-hour).
* @deprecated Need to be implemented.
*/
public double getTravelTime(double speed) {
// TODO:
return 0;
double ttime = 0;
for (Arc thisArc : arcs) {
ttime += thisArc.getTravelTime(speed);
}
return ttime;
}
/**
@ -220,11 +264,15 @@ public class Path {
* every arc.
*
* @return Minimum travel time to travel this path (in seconds).
* @deprecated Need to be implemented.
*/
public double getMinimumTravelTime() {
// TODO:
return 0;
double ttime = 0;
int maxSpeed;
for (Arc thisArc : arcs) {
maxSpeed = thisArc.getRoadInformation().getMaximumSpeed();
ttime += thisArc.getTravelTime(maxSpeed);
}
return ttime;
}
}