amélioration: Le testCoherence n'a plus d'aléatoire, le testCompareWithBellman compare désormais les coûts et non les chemins arc par arc.

This commit is contained in:
Brendan Saint Germes 2026-05-28 17:55:46 +02:00
parent b81286e6ba
commit a6892ff0ca

View file

@ -20,6 +20,7 @@ import java.util.stream.Collectors;
import org.insa.graphs.algorithm.ArcInspector; import org.insa.graphs.algorithm.ArcInspector;
import org.insa.graphs.algorithm.ArcInspectorFactory; import org.insa.graphs.algorithm.ArcInspectorFactory;
import org.insa.graphs.algorithm.AbstractInputData.Mode; import org.insa.graphs.algorithm.AbstractInputData.Mode;
import org.insa.graphs.algorithm.AbstractSolution.Status;
import org.insa.graphs.model.Arc; import org.insa.graphs.model.Arc;
import org.insa.graphs.model.Graph; import org.insa.graphs.model.Graph;
import org.insa.graphs.model.Node; import org.insa.graphs.model.Node;
@ -50,18 +51,18 @@ public abstract class ShortestPathAlgorithmTest {
public final Graph graph; // chemin du fichier mapgr public final Graph graph; // chemin du fichier mapgr
public final Node origin, destination; public final Node origin, destination;
public final ArcInspector arcInspector; public final ArcInspector arcInspector;
public final boolean isFeasible; public final Status expectedStatus;
public TestScenario(Graph graph, int originId, int destinationId, boolean isFeasible, ArcInspector arcInspector) { public TestScenario(Graph graph, int originId, int destinationId, Status expectedStatus, ArcInspector arcInspector) {
this.graph = graph; this.graph = graph;
this.origin = graph.get(originId); this.origin = graph.get(originId);
this.destination = graph.get(destinationId); this.destination = graph.get(destinationId);
this.isFeasible = isFeasible; this.expectedStatus = expectedStatus;
this.arcInspector = arcInspector; this.arcInspector = arcInspector;
} }
public TestScenario(Graph graph, int originId, int destinationId, boolean isFeasible) { public TestScenario(Graph graph, int originId, int destinationId, Status expectedStatus) {
this(graph, originId, destinationId, isFeasible, new ArcInspectorFactory.NoFilterByLengthArcInspector()); // par défaut, aucune restriction sur les arcs this(graph, originId, destinationId, expectedStatus, new ArcInspectorFactory.NoFilterByLengthArcInspector()); // par défaut, aucune restriction sur les arcs
} }
}; };
@ -97,17 +98,17 @@ public abstract class ShortestPathAlgorithmTest {
Collection<Object> objects = new ArrayList<>(); Collection<Object> objects = new ArrayList<>();
// Exemple trajet court, toutes routes // Exemple trajet court, toutes routes
objects.add(new TestScenario(carreGraph, 9, 11, true)); objects.add(new TestScenario(carreGraph, 9, 11, Status.OPTIMAL));
// Exemple trajet moyen, toutes routes // Exemple trajet moyen, toutes routes
objects.add(new TestScenario(insaGraph, 286, 823, true)); objects.add(new TestScenario(insaGraph, 286, 823, Status.OPTIMAL));
// Exemple trajet infaisable (composantes non connexes) // Exemple trajet infaisable (composantes non connexes)
objects.add(new TestScenario(haitiGraph, 265362, 92314, false)); objects.add(new TestScenario(haitiGraph, 265362, 92314, Status.INFEASIBLE));
// Exemple trajet moyen, à pieds // Exemple trajet moyen, à pieds
objects.add(new TestScenario(toulouseGraph, 16824, 4028, true, new ArcInspectorFactory.OnlyPedestrianByTime())); objects.add(new TestScenario(toulouseGraph, 16824, 4028, Status.OPTIMAL, new ArcInspectorFactory.OnlyPedestrianByTime()));
// Exemple trajet de longueur nulle // Exemple trajet de longueur nulle
objects.add(new TestScenario(insaGraph, 297, 297, true)); objects.add(new TestScenario(insaGraph, 297, 297, Status.OPTIMAL));
// Exemple trajet très long // Exemple trajet très long
//objects.add(new TestScenario(franceGraph, 981717, 5539046, true)); //objects.add(new TestScenario(franceGraph, 981717, 5539046, Status.OPTIMAL));
return objects; return objects;
} }
@ -123,19 +124,10 @@ public abstract class ShortestPathAlgorithmTest {
assertNotNull(scenario.arcInspector); assertNotNull(scenario.arcInspector);
} }
@Test
public void testFeasability() {
final ShortestPathData algoData = new ShortestPathData(scenario.graph, scenario.origin, scenario.destination, scenario.arcInspector);
final ShortestPathSolution solution = this.runAlgo(algoData);
assertEquals(solution.isFeasible(), scenario.isFeasible);
if (solution.isFeasible()) assertTrue(solution.getPath().isValid());
}
@Test @Test
public void testCompareWithBellman() { public void testCompareWithBellman() {
// On ne compare avec Bellman qui si le scenario est faisable // On ne compare avec Bellman qui si le scenario est faisable
Assume.assumeTrue(scenario.isFeasible); Assume.assumeTrue(scenario.expectedStatus == Status.FEASIBLE || scenario.expectedStatus == Status.OPTIMAL);
// Si un chemin de longueur nulle (origin==destination) on ne compare pas avec Bellman, qui ne respecte pas les mêmes conventions que notre Dijkstra // Si un chemin de longueur nulle (origin==destination) on ne compare pas avec Bellman, qui ne respecte pas les mêmes conventions que notre Dijkstra
Assume.assumeFalse(scenario.origin.equals(scenario.destination)); Assume.assumeFalse(scenario.origin.equals(scenario.destination));
@ -147,26 +139,17 @@ public abstract class ShortestPathAlgorithmTest {
final Path pathDijkstra = solutionDijkstra.getPath(); final Path pathDijkstra = solutionDijkstra.getPath();
final Path pathBellman = solutionBellman.getPath(); final Path pathBellman = solutionBellman.getPath();
assertEquals(pathDijkstra.getArcs().size(), pathBellman.getArcs().size()); double coutDijkstra = 0.0;
for (final Arc arc : pathDijkstra.getArcs()) coutDijkstra += scenario.arcInspector.getCost(arc);
double coutBellman = 0.0;
for (final Arc arc : pathBellman.getArcs()) coutBellman += scenario.arcInspector.getCost(arc);
for (int i=0; i<pathDijkstra.getArcs().size(); i++) { assertEquals(coutBellman, coutDijkstra, 0.0);
final Arc arcDijkstra = pathDijkstra.getArcs().get(i);
final Node from1 = arcDijkstra.getOrigin();
final Node to1 = arcDijkstra.getDestination();
final Arc arcBellman = pathBellman.getArcs().get(i);
final Node from2 = arcBellman.getOrigin();
final Node to2 = arcBellman.getDestination();
assertEquals(arcDijkstra.getLength(), arcBellman.getLength(), 0.0);
assertEquals(from1, from2);
assertEquals(to1, to2);
}
} }
@Test @Test
public void testCompareCost() { public void testCompareCost() {
Assume.assumeTrue(scenario.isFeasible); Assume.assumeTrue(scenario.expectedStatus == Status.FEASIBLE || scenario.expectedStatus == Status.OPTIMAL);
final ShortestPathData algoData = new ShortestPathData(scenario.graph, scenario.origin, scenario.destination, scenario.arcInspector); final ShortestPathData algoData = new ShortestPathData(scenario.graph, scenario.origin, scenario.destination, scenario.arcInspector);
final ShortestPathSolution solution = this.runAlgo(algoData); final ShortestPathSolution solution = this.runAlgo(algoData);
@ -185,38 +168,36 @@ public abstract class ShortestPathAlgorithmTest {
assertEquals(coutDijkstra, coutComputed, 0.0); assertEquals(coutDijkstra, coutComputed, 0.0);
} }
// Tout sous chemin d'un PCC est un PCC // Tout sous chemin d'un PCC est un PCC, on vérifie aussi si le status est cohérent avec les attentes
@Test @Test
public void testConherence() { public void testConherence() {
Assume.assumeTrue(scenario.isFeasible);
final ShortestPathData algoData = new ShortestPathData(scenario.graph, scenario.origin, scenario.destination, scenario.arcInspector); final ShortestPathData algoData = new ShortestPathData(scenario.graph, scenario.origin, scenario.destination, scenario.arcInspector);
final ShortestPathSolution solution = this.runAlgo(algoData); final ShortestPathSolution solution = this.runAlgo(algoData);
final Path dijkstraPath = solution.getPath(); final Path solutionPath = solution.getPath();
System.out.println("testCoherence()"); assertEquals(scenario.expectedStatus, solution.getStatus());
if (dijkstraPath.getArcs().size() > 0) { if (solution.isFeasible()) {
System.out.println("OUI"); final int solutionPathLength = solutionPath.getArcs().size();
Random random = new Random(); for (int k = 1; k < (solutionPathLength/10); k++) {
for (int i=0; i<10; i++) { // On calcule un sous chemin, partant du même origin, mais arrivant à un point intermédiaire de la solution globale
final int k = random.nextInt(1, dijkstraPath.getArcs().size()-1); final Node middleNode = solutionPath.getArcs().get(k*5).getOrigin();
final Node randomNode = dijkstraPath.getArcs().get(k).getOrigin(); final ShortestPathData algoSousCheminData = new ShortestPathData(scenario.graph, scenario.origin, middleNode, scenario.arcInspector);
final ShortestPathSolution sousCheminSolution = this.runAlgo(algoSousCheminData);
final ShortestPathData algoDataSousChemin = new ShortestPathData(scenario.graph, scenario.origin, randomNode, scenario.arcInspector); assertTrue(sousCheminSolution.isFeasible());
final ShortestPathSolution solutionSousChemin = this.runAlgo(algoDataSousChemin); final Path sousCheminPath = sousCheminSolution.getPath();
final Path dijkstraPathSousChemin = solutionSousChemin.getPath(); double sousCheminCost = 0.0;
System.out.println("SousCheminPathLength: " + sousCheminPath.getArcs().size());
double coutDijkstraSousChemin = 0; for (final Arc arc : sousCheminPath.getArcs()) {
for (Arc arc : dijkstraPathSousChemin.getArcs()) coutDijkstraSousChemin += scenario.arcInspector.getCost(arc); sousCheminCost += scenario.arcInspector.getCost(arc);
double coutDijkstraPortion = 0;
for (Arc arc : dijkstraPath.getArcs()) {
coutDijkstraPortion += scenario.arcInspector.getCost(arc);
// Si on arrive au noeud random sur le dijkstra de référence, on s'arrête pour comparer les couts du sous chemin
if (arc.getDestination().equals(randomNode)) break;
} }
assertEquals(coutDijkstraSousChemin, coutDijkstraPortion, 0.0); double solutionCost = 0.0;
for (final Arc arc : solutionPath.getArcs()) {
solutionCost += scenario.arcInspector.getCost(arc);
if (arc.getDestination().equals(middleNode)) break; // Si on est arrivé au noeud intermédiaire, on arrête
}
assertEquals(solutionCost, sousCheminCost, 0.0);
} }
} }
} }