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

Boost C++ Discussion :

[Boost graph] Bellman ford Visitor .


Sujet :

Boost C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 68
    Par défaut [Boost graph] Bellman ford Visitor .
    Bonjour,
    je débute dans la librairie boost graph et j'ai besoin de maîtriser cette librairie pour un travail. J'ai déjà faits quelques codes pour utiliser les algorithmes de Dijkstra et de Belmman-Ford. Mais je vais avoir besoin d'utiliser les visitors et là je bloque.
    J'ai regarder les tutos que j'ai trouvé sur le net ainsi que la doc de boostgraph mais tout ça ne me permet pas de m'en sortir.
    Je vous appelle donc à l'aide!!

    Comme je le dis en titre, je veux utiliser les visitor de bellman ford. J'ai déjà un code qui effectue Bellman ford. Je pensais l'adapter mais je n'y arrive pas du tout. Je bloque sur les structures spécifiques à créer.
    Voici mon code de départ:
    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
    using namespace boost;
     
     
    struct EdgeProperties {
      int weight;
    };
     
    int main() {
     
      enum { A, B, C, D, E, F, G, H, I, J, N };
      char name[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' };
      typedef std::pair < int, int >Ed;
      const int n_edges = 11;
      Ed edge_array[] = { Ed(A,B), Ed(A,C), Ed(A,E), Ed(B,F),
          Ed(C,G), Ed(C,H), Ed(D,H), Ed(E,J), Ed(F,I), Ed(H,J), Ed(I,J) };
      int weight[n_edges] = { 85, 217, 173, 80,  186, 103, 183, 502, 250, 167, 84};
     
      typedef adjacency_list < vecS, vecS, directedS, no_property, EdgeProperties> Graph;
     
     
      Graph g(edge_array, edge_array + n_edges, N);
     
      graph_traits < Graph >::edge_iterator ei, ei_end
     
      property_map<Graph, int EdgeProperties::*>::type weight_pmap;
      weight_pmap = get(&EdgeProperties::weight, g);		
     
      int i = 0;
      for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei, ++i)	
        weight_pmap[*ei] = weight[i];
     
      std::vector<int> distance(N, (std::numeric_limits < short >::max)());
      std::vector<std::size_t> parent(N);
     
      for (i = 0; i < N; ++i)	
        parent[i] = i;
      distance[A] = 0;
     
      bool r = bellman_ford_shortest_paths
        (g, int (N), weight_map(weight_pmap).distance_map(&distance[0]).
         predecessor_map(&parent[0]));
     
      if (r)
        for (i = 0; i < N; ++i){
          std::cout << "distance(" << name[i] << ") = " << distance[i] << ", ";
          std::cout << "parent(" << name[i] << ") = " << name[parent[i]] << std::endl;
        }
     
     
     
      return EXIT_SUCCESS;
    }
    J'ai vu sur la doc de boost graph qu'il fallait utiliser les fonctions de BinaryFunction::combine, BinaryPredicate::compare, BellmanFordVisitor::v. Mais, je ne vois pas comment m'en sortir.
    N'hésitez pas à commenter tout ce que vous trouvez à redire, je suis là pour apprendre.
    Je vous remercie et je vous attends pour un échange constructif.

    J'ai remarqué un autre problème. Suivant dans quels sens j'enregistre mes arêtes et donc mes poids associés dans weight, le tour fournit comme résultat n'est plus le même. J'ai essayé avec l'algorithme de dijkstra fournit par boost graph et je n'ai eu aucun problème. Donc je reste assez perplexe... j'ai pensée à plusieurs choses mais rien de concret. J'aimerais aussi avoir un avis sur ce problème s'il vous plaît.
    Merci d'avance.

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 68
    Par défaut
    Bon, j'ai continuer mais toujours sans succés. Je veux pouvoir enregistrer le graphe générer par bellman ford mais je ne sais pas trop comment faire.
    J'ai créer cette structure:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    template <class NewGraph, class Tag>
     
    struct graph_copier : public boost::base_visitor<graph_copier<NewGraph, Tag> >{
      typedef Tag event_filter;
      graph_copier(NewGraph& graph) : new_g(graph) { }
      template <class Edge, class Graph>
      void operator()(Edge e, Graph& g) {
        add_edge(source(e, g), target(e, g), new_g);
      }
    private:
      NewGraph& new_g;
    };
    Mais, je n'arrive pas à la mettre comme il faut dans l'appelle à la fonction Bellman_Ford...J'ai voulu faire comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      bool r = bellman_ford_shortest_paths
        (g, int (N), weight_map(weight_pmap).distance_map(&distance[0]).
         predecessor_map(&parent[0]).
    	visitor(graph_copier<Graph,EdgeProperties>, on_examine_edge());
    Mais ça ne marche pas du tout.
    Je demande encore de l'aide pour m'éclaircir sur les points que je ne maîtrise pas.
    Merci.

  3. #3
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    Bonsoir,
    Citation Envoyé par hyuga33 Voir le message
    Bon, j'ai continuer mais toujours sans succés. Je veux pouvoir enregistrer le graphe générer par bellman ford mais je ne sais pas trop comment faire.
    Qu'est-ce que tu veux dire exactement par "enregistrer le graphe généré par bellman ford" ? Le code montré enregistre la plus courte distance entre tous les sommets et le sommet A dans la distance_map ainsi que l'arbre des prédécesseurs menant à A par le plus court chemin dans la predecessor_map. C'est ce que l'on attend d'un algo de plus court chemin, non ?

    Sinon pour l'utilisation du visiteur, je ne connaissais pas la méthode consistant à dériver de base_visitor et utiliser des tag comme event_filter, mais à première vu il me semble que la méthode "classique" (celle du tutorial) a l'air plus simple :

    On part d'un visiteur vide qui ne fait rien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    struct MyBellmanVisitor : public bellman_visitor<>
    {
    };
    Puis on ajoute des fonctions correspondants à un "event point" défini dans la doc. Par exemple avec le visiteur ci-dessous on peut ajouter son propre code (un peu comme une callback) à chaque fois qu'un edge est examiné et à chaque fois qu'un edge est relaché par l'algo.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    struct MyBellmanVisitor : public bellman_visitor<>
    {
       template <typename Edge, typename Graph>
      void  examine_edge(Edge e, Graph& g) const 
      {
         std::cout << "edge examinted " << source(e, g) << " " << target(e, g) << "\n";
      }
       template <typename Edge, typename Graph>
       void edge_relaxed(Edge e, Graph& g) const 	
       {
          std::cout << "edge relaxed " << source(e, g) << " " << target(e, g) << "\n";
        }
    };
    Utilisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
       bool r = bellman_ford_shortest_paths
       (g, int (N), weight_map(weight_pmap).distance_map(&distance[0]).
       predecessor_map(&parent[0]).visitor(MyBellmanVisitor()));
    Mais je n'ai quand même pas bien compris à quoi va te servir le visiteur au final

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 68
    Par défaut
    Merci beaucoup.
    En fait, je reprend un code sur lequel je dois travailler et finir mais qui utilise boost::graph donc je m'y suis mis(Je ne connaissais pas du tout il y a 10 jours). Sauf que dans l'exécution de bellman ford il y a des erreurs à cause de la façon de travailler sur le graphe d'origine. J'avais entendu parlé des visiteurs donc j'ai voulu m'y mettre car cela pourrait être intéressants. Je risque de m'en servir, soit pour enregistrer le tour optimal dans un vecteur spécial en même temps que l'exécution du programme (une fois que l'on est arriver au bout). Soit pour examiner seulement certains noeuds de mon graphe de départ qui est complet car j'ai besoin de résoudre un problème de plus court chemin sur un sous-graphe du graphe d'origine.
    Je voulais surtout comprendre la façon de structurer et d'utiliser les visitors. Tu m'a trés bien aidé pour ça, merci encore.

    Sinon, dans mon premier post je parlais d'un "truc" bizarre:
    J'ai remarqué un autre problème. Suivant dans quels sens j'enregistre mes arêtes et donc mes poids associés dans weight, le tour fournit comme résultat n'est plus le même. J'ai essayé avec l'algorithme de dijkstra fournit par boost graph et je n'ai eu aucun problème.
    Tu n'aurais pas une idée par hasard.
    Merci.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 68
    Par défaut suggestion
    Maintenant je voudrais pouvoir ne pas considérer un noeud de mon graphe lors de sa résolution.
    Je comptais faire:
    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
    struct EdgeProperties { 
      int weight;
    };
     
    enum { A, B, C, D, E, F, G, H, I, J, N };
    char name[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' };
     
    typedef adjacency_list < vecS, vecS, directedS, no_property, EdgeProperties> Graph;
     
     
    struct MyBellmanVisitor : public bellman_visitor<>
    {
       template <typename Edge, typename Graph>
      void  examine_edge(Edge e, Graph& g) const 
      {
         cout << "edge examinted " << source(e, g) << " " << target(e, g) << "\n";
     
         if (name[source(e,g)]=='H'){
     
         }
      }
    };
    et dans le if mettre une instruction qui dit d'ignorer le noeud H mais sans le supprimer du graphe.
    Est-ce possible?
    Si oui, comment?
    Je continue de chercher et si j'ai des idées je les mettrais.
    Merci.

    Voilà ou j'en suis:
    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
    struct EdgeProperties { 
      int weight;
    };
     
    typedef std::pair < int, int >Ed;
     
    enum { A, B, C, D, E, F, G, H, I, J, N };
    char name[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' };
     
    typedef adjacency_list < vecS, vecS, directedS, no_property, EdgeProperties> Graph;
     
    vector<Ed> stock;
     
    struct MyBellmanVisitor : public bellman_visitor<>
    {
       template <typename Edge, typename Graph>
      void  examine_edge(Edge e, Graph& g) const 
      {
         if (name[source(e,g)]=='H' || name[target(e,g)]=='H'){
          stock.push_back(Ed(source(e,g),target(e,g)));
          remove_edge(e,g);
         }
      }
    };
    Pour le moment je crée un vecteur de pair<int,int> pour stocker les arcs que je ne veux pas considérer. Je veux pouvoir les "réinsérer" dans mon graphe.
    Mais j'ai quelques questions:
    -remove-edge() supprime t'il définitivement mes arcs du graphe?
    -comment puis-je avoir accés aux éléments de mon vecteur? (je n'y arrive pas).

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 68
    Par défaut
    J'ai réussi à faire ce que je voulais.
    Je peux résoudre le problème de plus court chemin d'un graphe en excluant l'un de ces noeuds sans modifier le graphe en lui-même.
    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
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    #include <boost/config.hpp>
    #include <iostream>
    #include <boost/graph/adjacency_list.hpp>
    #include <boost/graph/edge_list.hpp>
    #include <boost/graph/bellman_ford_shortest_paths.hpp>
     
     
    using namespace::boost;
    using namespace::std;
     
    struct EdgeProperties { 
      int weight;
    };
     
    enum { A, B, C, D, E, F, G, H, I, J, N };
    char name[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' };
     
    typedef adjacency_list < vecS, vecS, directedS, no_property, EdgeProperties> Graph;
    vector <int> depart;
    vector <int> cible;
     
    struct MyBellmanVisitor : public bellman_visitor<>
    {
       template <typename Edge, typename Graph>
      void  examine_edge(Edge e, Graph& g) const 
      {
         if (name[source(e,g)]=='H' || name[target(e,g)]=='H'){
          depart.push_back(source(e,g));
          cible.push_back(target(e,g));
     
          remove_edge(e,g);
         }
      }
    };
     
    void bfv(Graph g,   property_map<Graph, int EdgeProperties::*>::type weight_pmap,vector<int> distance, vector<size_t> parent){
      cout<<"\n RESOLUTION DU PLUS COURT CHEMIN AVEC BELLMAN FORD VISITOR"<<endl;
      bool r = bellman_ford_shortest_paths
       (g, int (N), weight_map(weight_pmap).distance_map(&distance[0]).
       predecessor_map(&parent[0]).visitor(MyBellmanVisitor()));
      if (r){
        for (int i = 0; i < N; ++i){
          std::cout << "distance(" << name[i] << ") = " << distance[i] << ", ";
          std::cout << "parent(" << name[i] << ") = " << name[parent[i]] << std::endl;
        }
      }
    }
     
    void bf(Graph g,   property_map<Graph, int EdgeProperties::*>::type weight_pmap,vector<int> distance, vector<size_t> parent){
      cout<<"\n RESOLUTION DU PLUS COURT CHEMIN AVEC BELLMAN FORD CLASSIQUE"<<endl;
      bool r = bellman_ford_shortest_paths
        (g, int (N), weight_map(weight_pmap).distance_map(&distance[0]).
         predecessor_map(&parent[0]));
     
      if (r){
        for (int i = 0; i < N; ++i){
          std::cout << "distance(" << name[i] << ") = " << distance[i] << ", ";
          std::cout << "parent(" << name[i] << ") = " << name[parent[i]] << std::endl;
        }     
      }
    }
     
     
     
    int main() {
      typedef std::pair < int, int >Ed;
      const int n_edges = 11;
     
      Ed edge_array[] = { Ed(A,B), Ed(A,C), Ed(A,E), Ed(B,F),
          Ed(C,G), Ed(C,H), Ed(D,H), Ed(E,J), Ed(F,I), Ed(H,J), Ed(I,J) };
      int weight[n_edges] = { 85, 217, 173, 80,  186, 103, 183, 502, 250, 167, 84};
      Graph g(edge_array, edge_array + n_edges, N);  
     
      property_map<Graph, int EdgeProperties::*>::type weight_pmap;
      weight_pmap = get(&EdgeProperties::weight, g);
     
      std::vector<int> distance(N, (std::numeric_limits < short >::max)());
      std::vector<std::size_t> parent(N);
     
      int i = 0; 
      graph_traits < Graph >::edge_iterator ei, ei_end;
      for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei, ++i) {weight_pmap[*ei] = weight[i];}
     
      for (i = 0; i < N; ++i) {parent[i] = i;}
      distance[A] = 0;
     
      bfv(g,weight_pmap,distance,parent);
     
      bf(g,weight_pmap,distance,parent);
     
      return EXIT_SUCCESS;
    }
    Voila ce que j'ai fait.
    J'ai besoin de ça car je dois travailler sur un graphe dont les noeuds changent de propriétés au cour du temps. Donc je peux considérer mon graphe initial avec tous les noeuds et lors de la résolution à l'instant T, je choisis uniquement les noeuds qui ont un intêrets pour moi.

    N'hésitez pas à faire des comentaires sur mon code ou sur ma méthodologie.

    Merci pour votre aide.

Discussions similaires

  1. Boost.Graph : Comment utiliser tout ça?
    Par Xanto dans le forum Boost
    Réponses: 1
    Dernier message: 08/05/2009, 19h48
  2. Utilisation de Boost::Graph
    Par dj_benz dans le forum Boost
    Réponses: 6
    Dernier message: 01/10/2008, 09h56
  3. Bibli Boost Graph
    Par devroot dans le forum Boost
    Réponses: 5
    Dernier message: 10/09/2008, 12h38
  4. conctruction de la librairie boost graph
    Par jiim dans le forum Bibliothèques
    Réponses: 1
    Dernier message: 10/03/2005, 22h30

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