IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Plus court chemin Dijkstra STL


Sujet :

C++

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 301
    Par défaut Plus court chemin Dijkstra STL
    Bonjour à tous

    J'ai un problème sur l'agorithme de dijkstra, voici le code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
     
    struct C_Graph
    {
       vector<int>                   dist;
       vector<unsigned int>       pred;
       vector<vector<C_Arc*>> m_matOut; //les successeurs de chaque sommets (ptr d'arcs)
       void dijkstra (unsigned int start);
    };
     
    struct compare
    {
       bool operator() (const pair<int, unsigned int>& p1, const pair<int, unsigned int>& p2) const
       {
          if (p1.first == p2.first)
             return p1.second < p2.second;
          return (p1.first > p2.first) ;
       }
    };
     
    void C_Graph::dijkstra (unsigned int start)
    {
       size_t i,j;
       double alt;
     
       pair<int, unsigned int> p;
       set<pair<int, unsigned int>, compare> l_set;  //longueur, sommet
       set<pair<int, unsigned int>, compare>::iterator it_p;
       vector<C_Arc*>::iterator it_pArc;
     
       dist[start] = 0;
       dist.assign(m_nbNoeuds, (std::numeric_limits<int>::max)());
     
       pred.resize(m_nbNoeuds);
       for (i=0; i<m_nbNoeuds; ++i)
       {
          l_set.insert(make_pair(dist[i], i));
          pred[i] = i;
       }
     
       for (i=0; i<s_vctNoeuds.size(); ++i)
       {
             it_p = l_set.end();
             --it_p;
             p = *(it_p);
             l_set.erase(it_p);
             for (it_pArc=m_matOut[p.second].begin(); it_pArc != m_matOut[p.second].end(); ++it_pArc)
             {
                j = (*it_pArc)->second;
                alt = double(dist[p.second] +(*it_pArc)->m_iDistance);
                if (alt < double(dist[j]))
                {
                      l_set.erase(l_set.find(make_pair(dist[j], j)));
                      l_set.insert(make_pair(alt, j));
                      dist[j] = alt;
                      pred[j] = (*it_pArc)->m_uiId;
                }
             }
       }
       l_set.clear();
    }
    Ce code fonctionne bien, mais j'ai des problèmes de performances, j'appelle cette fonction un grand nombre de fois, mon nombre de noeuds étant constant entre deux appels, j'ai resizé les vecteurs dist et pred (il n'y a donc pas de réallocation entre deux appels). Je pense que ce qui me fait le plus perdre de temps c'est la partie en lien avec le set (utilisé pour la version améliorée du dijkstra). Voilà, si quelqu'un a déjà essayé de programmer cet algo à l'aide de la STL, je suis prenneur de tout exemple et conseils pour l'améliorer

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    58
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 58
    Par défaut
    Est-ce que les coûts des arcs changent entre chaque appels? Parce que si ils sont relativement constants et que ton nombre de noeud est assez faible, tu peux précalculer les chemins de chaque neoud vers tous les autres (algo de Floyd-Warshall). Ca permet ensuite de trouver le plus chemin sans aucun calcul.

  3. #3
    Membre éclairé Avatar de befalimpertinent
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    561
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Avril 2007
    Messages : 561
    Par défaut
    Encore plus rapide que Dijkstra ou que Floyd-Warshall : l'algorithme A star

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    58
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 58
    Par défaut
    ces 3 algos ne font pas la même chose donc ne sont pas comparable au niveau vitesse:
    - A* : donne un plus court chemin entre deux noeud
    - Dijskstra : tous les plus courts chemins vers ou depuis un noeud
    - Floyd-Warshall : tous les plus courts chemins entre tous les noeuds du graphe

    leur utilisation dépend du problème à traiter. si tu peux précalculer tous les chemins parce que le graphe est statique, utiliser Floyd-Warshall sera plus performant que d'appeler A* à chaque fois que tu cherches un chemin.

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 301
    Par défaut
    En fait mon graphe correspond à un graphe routier et je recherche les plus court chemins en temps. L'algorithme A* ne me semble donc pas convenir (il est basé sur une heuristique de distance euclidienne, ce qui ne marche pas avec l'aspect temporel: on va plus vite sur autoroute). Pour ce qui est de précalculer les chemins, je ne peux pas les précalculer (environ 12000 noeuds soit une matrice 12000*12000) (mon graphe est de plus orienté, je ne peux donc pas stocker la matrice triangulaire)

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    58
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 58
    Par défaut
    A mon avis, A* peut marcher dans ton cas si ton heuristique renvoie la distance entre les noeuds divisée par une vitesse maximale.

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 301
    Par défaut
    Le problème c'est qu'ensuite, j'utilise le code "basique" du dijkstra pour le faire en temporisé. Les valuations des arcs dépendent du moment où on arrive sur l'arc. J'utilise en plus une version inversée du dijkstra temporisé: on connait l'heure d'arrivée au noeud et il faut trouver le plus court chemin temporisé (cela nous donne les heures de passage par chaque arc et l'heure de départ du noeud de départ). Je ne connais pas très bien l'algorithme de A* et je pense qu'il vaudrait mieux que j'améliore la version basique du dijkstra (pour en faire bénéficier mes autre versions).

Discussions similaires

  1. Dijkstra K plus court chemin algorithme en Java - Tutorial
    Par geforce dans le forum Algorithmes et structures de données
    Réponses: 8
    Dernier message: 21/08/2014, 18h43
  2. [PHP 5.0] [Algorithme] Dijkstra : plus court chemin
    Par Opheodrys dans le forum Langage
    Réponses: 8
    Dernier message: 05/11/2012, 11h45
  3. Plus court-chemin selon DIJKSTRA
    Par jophar dans le forum Mathématiques
    Réponses: 1
    Dernier message: 11/10/2011, 16h32
  4. Algoritme Dijkstra pour le calcul du plus court chemin
    Par choko83 dans le forum Langage
    Réponses: 2
    Dernier message: 10/06/2010, 14h10
  5. Réponses: 2
    Dernier message: 21/03/2004, 18h57

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo