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.ArcInspectorFactory;
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.Graph;
import org.insa.graphs.model.Node;
@ -50,18 +51,18 @@ public abstract class ShortestPathAlgorithmTest {
public final Graph graph; // chemin du fichier mapgr
public final Node origin, destination;
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.origin = graph.get(originId);
this.destination = graph.get(destinationId);
this.isFeasible = isFeasible;
this.expectedStatus = expectedStatus;
this.arcInspector = arcInspector;
}
public TestScenario(Graph graph, int originId, int destinationId, boolean isFeasible) {
this(graph, originId, destinationId, isFeasible, new ArcInspectorFactory.NoFilterByLengthArcInspector()); // par défaut, aucune restriction sur les arcs
public TestScenario(Graph graph, int originId, int destinationId, Status expectedStatus) {
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<>();
// 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
objects.add(new TestScenario(insaGraph, 286, 823, true));
objects.add(new TestScenario(insaGraph, 286, 823, Status.OPTIMAL));
// 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
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
objects.add(new TestScenario(insaGraph, 297, 297, true));
objects.add(new TestScenario(insaGraph, 297, 297, Status.OPTIMAL));
// Exemple trajet très long
//objects.add(new TestScenario(franceGraph, 981717, 5539046, true));
//objects.add(new TestScenario(franceGraph, 981717, 5539046, Status.OPTIMAL));
return objects;
}
@ -123,19 +124,10 @@ public abstract class ShortestPathAlgorithmTest {
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
public void testCompareWithBellman() {
// 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
Assume.assumeFalse(scenario.origin.equals(scenario.destination));
@ -147,26 +139,17 @@ public abstract class ShortestPathAlgorithmTest {
final Path pathDijkstra = solutionDijkstra.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++) {
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);
}
assertEquals(coutBellman, coutDijkstra, 0.0);
}
@Test
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 ShortestPathSolution solution = this.runAlgo(algoData);
@ -185,38 +168,36 @@ public abstract class ShortestPathAlgorithmTest {
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
public void testConherence() {
Assume.assumeTrue(scenario.isFeasible);
final ShortestPathData algoData = new ShortestPathData(scenario.graph, scenario.origin, scenario.destination, scenario.arcInspector);
final ShortestPathSolution solution = this.runAlgo(algoData);
final Path dijkstraPath = solution.getPath();
final Path solutionPath = solution.getPath();
System.out.println("testCoherence()");
if (dijkstraPath.getArcs().size() > 0) {
System.out.println("OUI");
Random random = new Random();
for (int i=0; i<10; i++) {
final int k = random.nextInt(1, dijkstraPath.getArcs().size()-1);
final Node randomNode = dijkstraPath.getArcs().get(k).getOrigin();
final ShortestPathData algoDataSousChemin = new ShortestPathData(scenario.graph, scenario.origin, randomNode, scenario.arcInspector);
final ShortestPathSolution solutionSousChemin = this.runAlgo(algoDataSousChemin);
final Path dijkstraPathSousChemin = solutionSousChemin.getPath();
double coutDijkstraSousChemin = 0;
for (Arc arc : dijkstraPathSousChemin.getArcs()) coutDijkstraSousChemin += 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(scenario.expectedStatus, solution.getStatus());
if (solution.isFeasible()) {
final int solutionPathLength = solutionPath.getArcs().size();
for (int k = 1; k < (solutionPathLength/10); k++) {
// On calcule un sous chemin, partant du même origin, mais arrivant à un point intermédiaire de la solution globale
final Node middleNode = solutionPath.getArcs().get(k*5).getOrigin();
final ShortestPathData algoSousCheminData = new ShortestPathData(scenario.graph, scenario.origin, middleNode, scenario.arcInspector);
final ShortestPathSolution sousCheminSolution = this.runAlgo(algoSousCheminData);
assertTrue(sousCheminSolution.isFeasible());
final Path sousCheminPath = sousCheminSolution.getPath();
double sousCheminCost = 0.0;
System.out.println("SousCheminPathLength: " + sousCheminPath.getArcs().size());
for (final Arc arc : sousCheminPath.getArcs()) {
sousCheminCost += scenario.arcInspector.getCost(arc);
}
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);
}
}
}