Je mets en application DFS sur un graphique pondéré réalisé de la manière suivante:revisitant nœuds pendant DFS et le contrôle des cycles infinis
public class DFSonWeightedDirectedGraph {
private static final String START = "A";
private static final String END = "C";
private int pathLength = 0;
private int stops = 0;
public static void main(String[] args) {
//this is a directed weighted graph
WeightedDirectedGraph graph = new WeightedDirectedGraph();
graph.addEdge("A", "B", 5);
graph.addEdge("A", "D", 5);
graph.addEdge("A", "E", 7);
graph.addEdge("B", "C", 4);
graph.addEdge("C", "D", 8);
graph.addEdge("C", "E", 2);
graph.addEdge("D", "C", 8);
graph.addEdge("D", "E", 6);
graph.addEdge("E", "B", 3);
LinkedList<String> visited = new LinkedList<String>();
visited.add(START);
new DFSonWeightedDirectedGraph().depthFirst(graph, visited);
}
private void depthFirst(WeightedDirectedGraph graph, LinkedList<String> visited) {
Collection<Map.Entry<String, Integer>> nodes = graph.adjacentNodes(visited.getLast());
// examine adjacent nodes
for (Map.Entry<String, Integer> node : nodes) {
if (visited.contains(node.getKey())) {
continue;
}
if (node.getKey().equals(END)) {
visited.addLast(node.getKey());
pathLength += node.getValue();
stops += 1;
printPath(visited);
visited.removeLast();
pathLength -= node.getValue();
stops -= 1;
break;
}
}
// recursion
for (Map.Entry<String, Integer> node : nodes) {
if (visited.contains(node.getKey()) || node.getKey().equals(END)) {
continue;
}
visited.addLast(node.getKey());
pathLength += node.getValue();
stops += 1;
depthFirst(graph, visited);
visited.removeLast();
pathLength -= node.getValue();
stops -= 1;
}
}
private void printPath(LinkedList<String> visited) {
for (String node : visited) {
System.out.print(node);
System.out.print(" ");
}
System.out.println("[path length: "+pathLength +
" stops made: "+ stops+"]");
}
}
Je dois modifier ce qui précède pour permettre des cycles au cours de la recherche de tous les chemins entre une source nœud et un nœud de destination. Pour éviter les cycles infinis, les conditions peuvent être définies pour terminer la recherche en fonction du nombre de "arrêts" effectués, ou d'une distance maximale autorisée à partir de la source.
De cette façon, je peux trouver, par exemple, le nombre de voyages commençant à A et se terminant à D avec exactement 5 arrêts: Une solution peut être ABCDCD. Ou, je peux trouver, disons, le nombre de routes différentes de D à D avec une distance inférieure à 40: quelques solutions seraient DECD, DEBCD, DCDCD. Mon problème est que je ne suis pas sûr de savoir comment créer la logique de garder l'algorithme principal de recherche, tout en échappant à un cycle de recherche infinie qui est garanti pour ne pas atteindre le nœud de destination. Disons que je veux voyager de A à D. Un cycle sans issue possible peut être ABCEBCEBCEB .... (à l'infini). Mes conditions basées sur le nombre d'arrêts, ou la distance totale parcourue, peuvent terminer cette boucle, mais mettront également fin à toute la recherche, qui pourrait autrement trouver le bon chemin de dire ABCDCDCDCD, qui se terminera correctement lorsque l'une ou l'autre des conditions prédéfinies est remplie.
Merci pour vos idées.
Merci pour la réponse. Je me demandais, disons qu'il y a un chemin de A à D, de sorte que M (a, d) = 1, où M est la matrice d'accessibilité, comment peut-on atteindre D à partir de A sans sombrer dans un cycle infini quelque part entre ? (c'est-à-dire ABCEBCEBCEB ... à inf - où ABCDCDCD est un résultat valide) Si je termine en fonction des arrêts ou de la distance, je perds toute la recherche à droite? – denchr
Si M (A, D) = M (B, D) = M (C, D) = M (E, D) = 1, alors vous ne pouvez pas arrêter le cycle infini en utilisant cette méthode (et il ne serait pas avoir raison, car ABCEBCD est une solution valable). Dans ce cas, vous ne pouvez arrêter le cycle qu'en utilisant une coupure pour les arrêts. Par exemple, si vous avez besoin de trouver tous les chemins avec <= 8 arrêts, alors vous élagueriez ABCEBCEB (car il a atteint 8 arrêts, mais n'a pas atteint la cible), mais vous ne perdriez pas le reste de la recherche. Essentiellement vous implémentez une recherche de profondeur limitée: http://en.wikipedia.org/wiki/Depth-limited_search – 3lectrologos
Merci. Fondamentalement, j'expérimentais pour voir s'il y avait un moyen plus simple. Sur la base de mon code ci-dessus, si je supprime les instructions if qui vérifient les nœuds de réexamen - ou commente simplement les mots-clés "continue", alors j'ai une boucle infinie, qui imprime à la console quelque chose comme: ADEBC (...) DEBCDC [longueur du trajet: 4444 arrêts effectués: 846]. Mais j'ai encore du mal à comprendre la mécanique. – denchr