webentwicklung-frage-antwort-db.com.de

Verwenden der C ++ Boost-Grafikbibliothek

Ich bin verwirrt darüber, wie man ein Diagramm mithilfe der Boost-Bibliothek erstellt. Ich habe mir den Beispielcode angesehen und es gibt keine Kommentare, in denen die Funktionsweise erläutert wird.

Wie erstellen Sie ein Diagramm und fügen dabei Scheitelpunkte und Kanten hinzu?

50
Jim

Hier ist ein einfaches Beispiel, bei dem eine Adjazenzliste verwendet und eine topologische Sortierung ausgeführt wird:

#include <iostream>
#include <deque>
#include <iterator>

#include "boost/graph/adjacency_list.hpp"
#include "boost/graph/topological_sort.hpp"

int main()
{
    // Create a n adjacency list, add some vertices.
    boost::adjacency_list<> g(num tasks);
    boost::add_vertex(0, g);
    boost::add_vertex(1, g);
    boost::add_vertex(2, g);
    boost::add_vertex(3, g);
    boost::add_vertex(4, g);
    boost::add_vertex(5, g);
    boost::add_vertex(6, g);

    // Add edges between vertices.
    boost::add_Edge(0, 3, g);
    boost::add_Edge(1, 3, g);
    boost::add_Edge(1, 4, g);
    boost::add_Edge(2, 1, g);
    boost::add_Edge(3, 5, g);
    boost::add_Edge(4, 6, g);
    boost::add_Edge(5, 6, g);

    // Perform a topological sort.
    std::deque<int> topo_order;
    boost::topological_sort(g, std::front_inserter(topo_order));

    // Print the results.
    for(std::deque<int>::const_iterator i = topo_order.begin();
        i != topo_order.end();
        ++i)
    {
        cout << tasks[v] << endl;
    }

    return 0;
}

Ich stimme zu, dass die Dokumentation zu boost :: graph einschüchternd sein kann, aber es lohnt sich, ein siehe .

Ich kann mich nicht erinnern, ob der Inhalt des gedruckten Buches der gleiche ist. Ich vermute, es ist ein bisschen augenschonender. Ich habe tatsächlich gelernt, Boost: Graph aus dem Buch zu verwenden. Die Lernkurve kann sich allerdings ziemlich steil anfühlen. Das Buch, auf das ich mich beziehe und Rezensionen finden Sie hier .

36
Liam M

Dies basiert auf dem Beispiel auf der boost :: graph-Website, wobei Kommentare hinzugefügt wurden:

#include <iostream>
#include <utility>
#include <algorithm>
#include <vector>

#include "boost/graph/graph_traits.hpp"
#include "boost/graph/adjacency_list.hpp"

using namespace boost;

int main(int argc, char *argv[])
{
    //create an -undirected- graph type, using vectors as the underlying containers
    //and an adjacency_list as the basic representation
    typedef adjacency_list<vecS, vecS, undirectedS> UndirectedGraph;

    //Our set of edges, which basically are just converted into ints (0-4)
    enum {A, B, C, D, E, N};
    const char *name = "ABCDE";

    //An Edge is just a connection between two vertitices. Our verticies above
    //are an enum, and are just used as integers, so our edges just become
    //a std::pair<int, int>
    typedef std::pair<int, int> Edge;

    //Example uses an array, but we can easily use another container type
    //to hold our edges. 
    std::vector<Edge> edgeVec;
    edgeVec.Push_back(Edge(A,B));
    edgeVec.Push_back(Edge(A,D));
    edgeVec.Push_back(Edge(C,A));
    edgeVec.Push_back(Edge(D,C));
    edgeVec.Push_back(Edge(C,E));
    edgeVec.Push_back(Edge(B,D));
    edgeVec.Push_back(Edge(D,E));

    //Now we can initialize our graph using iterators from our above vector
    UndirectedGraph g(edgeVec.begin(), edgeVec.end(), N);

    std::cout << num_edges(g) << "\n";

    //Ok, we want to see that all our edges are now contained in the graph
    typedef graph_traits<UndirectedGraph>::Edge_iterator Edge_iterator;

    //Tried to make this section more clear, instead of using tie, keeping all
    //the original types so it's more clear what is going on
    std::pair<Edge_iterator, Edge_iterator> ei = edges(g);
    for(Edge_iterator Edge_iter = ei.first; Edge_iter != ei.second; ++Edge_iter) {
        std::cout << "(" << source(*Edge_iter, g) << ", " << target(*Edge_iter, g) << ")\n";
    }

    std::cout << "\n";
    //Want to add another Edge between (A,E)?
    add_Edge(A, E, g);

    //Print out the Edge list again to see that it has been added
    for(Edge_iterator Edge_iter = ei.first; Edge_iter != ei.second; ++Edge_iter) {
        std::cout << "(" << source(*Edge_iter, g) << ", " << target(*Edge_iter, g) << ")\n";
    }

    //Finally lets add a new vertex - remember the verticies are just of type int
    int F = add_vertex(g);
    std::cout << F << "\n";

    //Connect our new vertex with an Edge to A...
    add_Edge(A, F, g);

    //...and print out our Edge set once more to see that it was added
    for(Edge_iterator Edge_iter = ei.first; Edge_iter != ei.second; ++Edge_iter) {
        std::cout << "(" << source(*Edge_iter, g) << ", " << target(*Edge_iter, g) << ")\n";
    }
    return 0;
}
24
Yuushi

Boost's adjacency_list ist ein guter Weg, dieses Beispiel erstellt einen gerichteten Graphen und gibt ein Bild des Graphen mit GraphViz von AT & T aus:

#include <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>

int main()
{
    using namespace std;
    using namespace boost;

    /* define the graph type
          listS: selects the STL list container to store 
                 the OutEdge list
          vecS: selects the STL vector container to store 
                the vertices
          directedS: selects directed edges
    */
   typedef adjacency_list< listS, vecS, directedS > digraph;

   // instantiate a digraph object with 8 vertices
   digraph g(8);

   // add some edges
   add_Edge(0, 1, g);
   add_Edge(1, 5, g);
   add_Edge(5, 6, g);
   add_Edge(2, 3, g);
   add_Edge(2, 4, g);
   add_Edge(3, 5, g);
   add_Edge(4, 5, g);
   add_Edge(5, 7, g);

   // represent graph in DOT format and send to cout
   write_graphviz(cout, g);

   return 0;
}

Die Ausgabe ist eine DOT-Datei, die Sie schnell in das in GraphViz enthaltene Dienstprogramm dot einfügen können.

14
tlehman

Ich denke, Sie werden die folgenden Ressourcen sehr hilfreich finden.

Graph Theory Primer

Wenn Sie mit der Graphentheorie nicht vertraut sind oder eine Auffrischung benötigen, werfen Sie einen Blick auf Boosts Review of Elementary Graph Theory : http://www.boost.org/ doc/libs/1_58_0/libs/graph/doc/graph_theory_review.html

Dieser Primer ist hilfreich, um die Terminologie zu verstehen, wie Datenstrukturen Graphen (Adjazenzmatrix, Adjazenzliste usw.) und Algorithmen (Breitensuche, Tiefensuche, kürzester Pfad usw.) darstellen.

Im Detail beschriebener Beispielcode

Im folgenden Abschnitt des Online-Buches von Boris Schäling finden Sie einen Beispielcode für die Erstellung detailliert beschriebener Diagramme - Die Boost C++ - Bibliotheken : http://theboostcpplibraries.com/boost.graph-vertices-and-edges

Boris erklärt anhand der adjacenty_list, wie man mit Eckpunkten und Kanten arbeitet. Der Code wird ausführlich erklärt, damit Sie jedes Beispiel verstehen können.

Grundlegendes zu adjacency_list-Vorlagenparametern

Es ist wichtig, die Vorlagenparameter für die adjacency_list zu verstehen. Möchten Sie beispielsweise ein gerichtetes oder ungerichtetes Diagramm? Soll Ihr Diagramm mehrere Kanten mit denselben Endknoten (d. H. Mehrfachgrafiken) enthalten? Leistung kommt auch ins Spiel. Boris 'Buch erklärt einige davon, aber Sie finden hier zusätzliche Informationen zur Verwendung der adjacenty_list: http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/using_adjacency_list.html

Verwenden benutzerdefinierter Objekte für Scheitelpunkte, Kanten oder Diagramme

Wenn Sie benutzerdefinierte Objekte für die Eckpunkte, Kanten oder sogar das Diagramm selbst verwenden möchten, sollten Sie gebündelte Eigenschaften verwenden . Die folgenden Links sind hilfreich für die Verwendung gebündelter Eigenschaften: http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/bundles.html

Und vielleicht auch dies als Beispiel: Hinzufügen benutzerdefinierter Scheitelpunkte zu einem Boost-Diagramm

Kreisförmige Abhängigkeiten erkennen (Zyklen)

Es gibt mehrere Möglichkeiten, um zirkuläre Abhängigkeiten zu erkennen:

Tiefensuche : Eine einfache Möglichkeit besteht darin, eine Tiefensuche durchzuführen und festzustellen, ob die Suche auf einen bereits erkannten Scheitelpunkt im aktuellen Suchbaum stößt . Hier ist ein Beispiel für das Erkennen von zyklischen Abhängigkeiten mithilfe der Tiefensuche von Boost: http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/file_dependency_example.html#sec:cycles =

Topologische Sortierung : Man kann Zyklen auch mit einem topologische Sortierung erkennen. boost stellt einen topologischen Sortieralgorithmus bereit: http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/topological_sort.html

Eine topologische Sortierung arbeitet mit einem gerichteten azyklischen Graphen (DAG). Wenn ein zyklischer Graph übergeben wird, wird eine Ausnahme ausgelöst, die angibt, dass der Graph eine zirkuläre Abhängigkeit hat. topological_sort enthält eine Tiefensuche, bietet aber auch eine lineare Anordnung der Scheitelpunkte. Hier ist ein Beispiel: http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/file_dependency_example.html#sec:cycles

Stark verbundene Komponenten : Wenn Sie außerdem stark verbundene Komponenten suchen, können Sie feststellen, ob ein Diagramm Zyklen aufweist oder nicht: http: //www.personal. kent.edu/~rmuhamma/Algorithms/MyAlgorithms/GraphAlgor/strongComponent.htm

die strong_components-Funktion von boost berechnet die stark verbundenen Komponenten eines gerichteten Graphen unter Verwendung des Tarjan-Algorithmus. http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/strong_components.html

Beispiel für die Dateiabhängigkeit

Ein weiterer hilfreicher Link wurde bereits bereitgestellt - Boost's File Dependency Example , das zeigt, wie man ein Diagramm von Quellcode-Dateien erstellt und diese anhand ihrer Kompilierungsreihenfolge sortiert (topologische Sortierung). Bestimmen Sie, welche Dateien gleichzeitig kompiliert werden können, und bestimmen Sie zyklische Abhängigkeiten: http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/file_dependency_example.html

12
jrupe

Einige kurze und aktuelle Rezepte für den Einstieg in die Boost C++ - Bibliotheken finden Sie hier:

Verwenden der Boost Graph Library

Diese hier aufgelisteten Codebeispiele sind einigermaßen aktuell und scheinen ordnungsgemäß zu kompilieren und zu funktionieren. Ich stelle fest, dass einige der Online-Dokumentationen zur Verwendung der Boost Graph Library veraltet zu sein scheinen oder zu Kompilierungsfehlern führen.

Hier finden Sie eine Reihe von Arbeitsbeispielen, darunter das Erstellen gerichteter und ungerichteter Diagramme, das Drucken der Kantengewichte, das Auffinden minimaler Spannbäume mithilfe des Kruskal-Algorithmus und Probleme mit maximalem Durchfluss.

3
AndyUK