12
votes

Floyd-Warshall avec des cycles négatifs. Comment trouver tous les chemins non définis?

J'ai mis en œuvre l'algorithme Floyd Warshall et cela fonctionne, mais le problème est que je ne sais pas comment je peux trouver tous les chemins qui ne sont pas définis. J'ai cherché sur le Web mais je ne peux trouver que des réponses sur la manière de détecter si un graphique a des cycles négatifs ou non.

  | 0     1     2     3     4
--|----------------------------
0 | 0    -INF   -INF    -INF  INF
1 | INF  -INF   -INF    -INF  INF
2 | INF  -INF   -INF    -INF  INF
3 | INF   INF    INF     0    INF
4 | 1    -INF   -INF    -INF  0 


0 commentaires

3 Réponses :


10
votes

Eh bien, j'ai trouvé une solution à mon propre problème.

for(int i = 0; i < n; i++)
    for(int j = 0; j < n; j++)    // Go through all possible sources and targets

        for(int k = 0; d[i][j] != -INF && k < n; k++)
            if( d[i][k] != INF && // Is there any path from i to k?
                d[k][j] != INF && // Is there any path from k to j?
                d[k][k] < 0)      // Is k part of a negative loop?

                d[i][j] = -INF;   // If all the above are true
                                  // then the path from i to k is undefined


0 commentaires

0
votes

L'algorithme Floyd-Warshall affiche le résultat correct tant qu'aucun négatif Les cycles existent dans le graphique d'entrée. En cas d'existence d'un cycle négatif, calculer un chemin le plus court (simple) est un problème durs NP et le L'algorithme Floyd-Warshall n'étisera pas le résultat correct.

Mais il est possible de détecter la présence d'un cycle négatif en vérifiant qu'il existe une entrée négative dans la diagonale de la matrice. Ceci est fait dans la ligne 8 et la ligne 9 de cet algorithme: xxx

source


2 commentaires

Devons-nous réellement attendre jusqu'à la fin de la boucle Triple "pour" pour vérifier la diagonale? Nous pourrions sortir dès que nous avons découvert que l'élément diagonal est devenu négatif après une certaine kième itération. C'est aussi ce qui est indiqué dans Wiki: "devrait vérifier les nombres négatifs sur la diagonale de la matrice de chemin dans l'intérieur de la boucle de l'algorithme"


C'est vraiment mauvais, si le graphique contient un cycle négatif, les distances pourraient déborder. Cette condition doit être testée dans la boucle interne de l'algorithme. recherchegate.net/publication/.../a>



2
votes

J'ai un vidéo qui explique exactement comment l'algorithme Floyd-Warshall fonctionne. Essentiellement, l'algorithme Floyd-Warshall est utilisé pour trouver les chemins les plus courts entre toutes les paires de nœuds dans un graphique pondéré avec des poids de bord positif ou négatif.

L'algorithme suivant accepte une matrice d'adjacence, où la double.Positive est utilisée pour indiquer que deux nœuds ne se connectent pas. Pour chaque nœud, vous voudrez également initialiser un poids de 0 à lui-même. P>

Cette méthode met à jour la matrice initiale pour indiquer la distance minimale entre toutes les paires de nœuds. Si le chemin le plus court est arbitrairement petit, la réponse est stockée en tant que double.Negative_infinity. Si deux nœuds ne peuvent pas se rejoindre, il est encore double. Positive_infinity. Cette mise en œuvre fonctionne deux fois et si la longueur du chemin est plus petite que celle-ci, nous sommes dans un cycle négatif. P>

static void floydWarshall(double[][] dist) {

  int n = dist.length;

  // Compute shortest paths
  for (int k = 0; k < n; k++)
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++)
        if (dist[i][k] + dist[k][j] < dist[i][j])
          dist[i][j] = dist[i][k] + dist[k][j];

  // Identify negative cycles
  for (int k = 0; k < n; k++)
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++)
        if (dist[i][k] + dist[k][j] < dist[i][j])
          dist[i][j] = Double.NEGATIVE_INFINITY;

}


2 commentaires

Consultez mon commentaire sur la réponse ci-dessus, cela pourrait également se déborder.


Juste pour noter, le code ci-dessus ne fonctionne pas si un nœud a un bord avec un poids négatif à lui-même parce que (dans certains cas), il ne propagerait pas correctement la valeur Négative Infinity. Voir mon problème ici: Github.com/williamfiset/algorithms/issues/260