web-dev-qa-db-ja.com

C ++ Boostのグラフライブラリの使用

Boostライブラリを使用して実際にGraphを作成する方法について混乱しています。サンプルコードを調べましたが、その機能を説明するコメントはありません。

グラフを作成し、頂点とエッジを追加する方法は?

50
Jim

隣接リストを使用してトポロジーソートを実行する簡単な例を次に示します。

#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;
}

Boost :: graphのドキュメントは恐ろしいかもしれませんが、 look にする価値はあります。

印刷された本の内容が同じかどうかは思い出せませんが、目には少し楽だと思います。私は実際に本からboost:graphを使用することを学びました。しかし、学習曲線はかなり急に感じることがあります。私が参照している本とレビューは こちら にあります。

36
Liam M

これは、boost :: graph Webサイトでの例に基づいており、コメントが追加されています。

#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のadjacency_listは良い方法です。この例では、有向グラフを作成し、AT&TのGraphVizを使用してグラフの画像を出力します。

#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;
}

出力はDOTファイルであり、GraphVizに付属のdotユーティリティにすばやく入力できます。

14
tlehman

次のリソースが非常に役立つと思います。

グラフ理論入門

グラフ理論に慣れていない場合、または復習が必要な場合は、ブーストのElementary Graph Theoryのレビューをご覧ください: http://www.boost.org/ doc/libs/1_58_0/libs/graph/doc/graph_theory_review.html

この入門書は、用語、データ構造がグラフ(隣接行列、隣接リストなど)を表す方法、およびアルゴリズム(幅優先検索、深さ優先検索、最短パスなど)を理解するのに役立ちます。

詳細に説明されているサンプルコード

詳細に説明されているグラフを作成するためのサンプルコードについては、BorisSchälingのオンラインブックの次のセクションをご覧ください-The Boost C++ Librarieshttp:/ /theboostcpplibraries.com/boost.graph-vertices-and-edges

Borisは、隣接する隣接リストを使用して頂点とエッジを操作する方法を説明しています。コードは徹底的に説明されているため、各例を理解できます。

Adjacency_listテンプレートパラメータについて

Adjacency_listのテンプレートパラメータを理解することが重要です。たとえば、有向グラフまたは無向グラフが必要ですか?グラフに同じ終了ノードを持つ複数のエッジ(つまり、マルチグラフ)を含めますか?パフォーマンスも重要です。ボリスの本はこれらのいくつかを説明していますが、隣接するy_listの使用に関する追加情報はここにあります: http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/using_adjacency_list.html

頂点、エッジ、またはグラフにカスタムオブジェクトを使用する

頂点、エッジ、またはグラフ自体にカスタムオブジェクトを使用する場合は、バンドルプロパティを使用します。バンドルされたプロパティを使用するには、次のリンクが役立ちます。 http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/bundles.html

そして、おそらくこれも例です: ブーストグラフへのカスタム頂点の追加

循環依存関係(サイクル)の検出

以下を含む循環依存関係を検出する方法は複数あります。

深さ優先検索:1つの簡単な方法は、深さ優先検索を実行し、現在の検索ツリーですでに発見されている頂点に検索が実行されるかどうかを検出することです。以下は、ブーストの深さ優先検索を使用して循環依存関係を検出する例です。 http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/file_dependency_example.html#sec:cycles =

トポロジカルソートトポロジカルソート を使用してサイクルを検出することもできます。 boostはtopological_sortアルゴリズムを提供します: http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/topological_sort.html

トポロジカルソートは、有向非巡回グラフ(DAG)で機能します。循環グラフが渡されると、例外がスローされ、グラフに循環依存関係があることが示されます。 topological_sortには深さ優先検索が含まれますが、頂点の線形順序付けも提供されます。以下に例を示します。 http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/file_dependency_example.html#sec:cycles

強く接続されたコンポーネント:さらに、強く接続されたコンポーネントを見つけると、グラフにサイクルがあるかどうかを示すことができます: http://www.personal。 kent.edu/~rmuhamma/Algorithms/MyAlgorithms/GraphAlgor/strongComponent.htm

boostのstrong_components関数は、タージャンのアルゴリズムを使用して、有向グラフの強く接続されたコンポーネントを計算します。 http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/strong_components.html

ファイル依存関係の例

別の役立つリンクはすでに提供されています-ブーストのFile Dependency Exampleはソースコードファイルのグラフをセットアップし、コンパイル順(トポロジカルソート)に基づいて順序付けする方法を示します、同時にコンパイルできるファイルを決定し、循環依存関係を決定します。 http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/file_dependency_example.html

12
jrupe

Boost C++ライブラリの使用を開始する際のいくつかの簡潔で要点のあるレシピは、ここにあります。

ブーストグラフライブラリの使用

ここにリストされているこれらのコードサンプルは、合理的に最新であり、コンパイルして正常に動作しているように見えます。 Boost Graph Libraryの使用に関するオンラインドキュメントの一部が古くなっているか、コンパイルエラーが発生していることがわかりました。

ここには、有向グラフと無向グラフの作成、エッジの重みの印刷、クラスカルのアルゴリズムを使用した最小スパニングツリーの検索、最大フローの問題など、多数の実例があります。

3
AndyUK