7

MutableGraphブースト グラフ ライブラリを使用して、グリッドとしての生活を開始するために a を初期化しようとしています。エッジは後で追加および削除されるためadjacency_list<vecS,listS,undirectedS>、正しい選択だと思います。

BGL について読んだところ、これらのエッジで BGL を初期化する賢明な方法は、すべての初期エッジを無料で作成できるa からコピーすることboost::grid_graphを利用 することであることがわかりました。のモデルから のモデルへのコピーは、まさに私が持っているものです。boost::copy_graphboost::grid_graphcopy_graphVertexListGraphMutableGraph

私は最初、 の 2 引数バージョンを使用してみcopy_graphましたが、残りのデフォルトで何か賢明なことが起こるという漠然とした希望を持っていました。そうではないことが判明しましたgrid_graph(理由がよくわかりませんでした) には、エッジまたは頂点のいずれかで s を使用する機能がないようPropertyMapです。プロパティ。vertex_copyedge_copy

引数が 2 つのバージョンは明らかに適切ではないように思われたので、次に進み、頂点とエッジをコピーするための独自の 2 項演算子を実装しようとしました。'no-op' コピーを使用しても、期待どおりに動作しません (つまり、コンパイルされません)。

問題を説明する最小限の実例をまとめました。

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/grid_graph.hpp>
#include <boost/graph/copy.hpp>

struct Position {
  int x, y;
};

struct VertexProperties {
  Position pos;
};

typedef boost::adjacency_list<boost::vecS, boost::listS, boost::undirectedS, 
                      VertexProperties> Graph;

struct MyCopy {
  template <typename S, typename D>
  void operator()(const S& /*src*/, D& /*dest*/) {
    // Nothing for now, deduced types to try and just make it compile
    // TODO: set values for pos to reflect position on grid.
  }
};

int main() {
    boost::array<std::size_t, 2> lengths = { { 3, 3 } };
    boost::grid_graph<2> grid(lengths);

    Graph graph;
    MyCopy copier;
    // Using 3-Arg version of copy_graph so we can specify a custom way of copying to create the properties
    boost::copy_graph(grid,graph,boost::bgl_named_params<MyCopy,boost::vertex_copy_t,
                                 boost::bgl_named_params<MyCopy,boost::edge_copy_t> >(copier));
}

この例はコンパイルされません:

g++ -Wextra -Wall -O2 -g -o copytest.o -c copytest.cc
In file included from /usr/include/boost/graph/grid_graph.hpp:24:0,
                 from copytest.cc:2:
/usr/include/boost/iterator/transform_iterator.hpp: In constructor ‘boost::transform_iterator<UnaryFunction, Iterator, Reference, Value>::transform_iterator() [with UnaryFunc = boost::detail::grid_graph_vertex_at<boost::grid_graph<2u> >, Iterator = boost::counting_iterator<unsigned int, boost::use_default, boost::use_default>, Reference = boost::use_default, Value = boost::use_default]’:
/usr/include/boost/graph/copy.hpp:115:55:   instantiated from ‘static void boost::detail::copy_graph_impl<0>::apply(const Graph&, MutableGraph&, CopyVertex, CopyEdge, Orig2CopyVertexIndexMap, IndexMap) [with Graph = boost::grid_graph<2u>, MutableGraph = boost::adjacency_list<boost::vecS, boost::listS, boost::undirectedS, VertexProperties>, CopyVertex = MyCopy, CopyEdge = MyCopy, IndexMap = boost::grid_graph_index_map<boost::grid_graph<2u>, boost::array<unsigned int, 2u>, unsigned int>, Orig2CopyVertexIndexMap = boost::iterator_property_map<__gnu_cxx::__normal_iterator<void**, std::vector<void*, std::allocator<void*> > >, boost::grid_graph_index_map<boost::grid_graph<2u>, boost::array<unsigned int, 2u>, unsigned int>, void*, void*&>]’
/usr/include/boost/graph/copy.hpp:327:5:   instantiated from ‘void boost::copy_graph(const VertexListGraph&, MutableGraph&, const boost::bgl_named_params<P, T, R>&) [with VertexListGraph = boost::grid_graph<2u>, MutableGraph = boost::adjacency_list<boost::vecS, boost::listS, boost::undirectedS, VertexProperties>, P = MyCopy, T = boost::vertex_copy_t, R = boost::bgl_named_params<MyCopy, boost::edge_copy_t>]’
/mnt/home/ajw/code/hpcwales/copytest.cc:31:66:   instantiated from here
/usr/include/boost/iterator/transform_iterator.hpp:100:26: error: no matching function for call to ‘boost::detail::grid_graph_vertex_at<boost::grid_graph<2u> >::grid_graph_vertex_at()’
/usr/include/boost/graph/grid_graph.hpp:104:7: note: candidates are: boost::detail::grid_graph_vertex_at<Graph>::grid_graph_vertex_at(const Graph*) [with Graph = boost::grid_graph<2u>]
/usr/include/boost/graph/grid_graph.hpp:100:33: note:                 boost::detail::grid_graph_vertex_at<boost::grid_graph<2u> >::grid_graph_vertex_at(const boost::detail::grid_graph_vertex_at<boost::grid_graph<2u> >&)

grid_graphそのエラーの私の分析は、私にはひどく明確ではない何らかの理由で、デフォルトで構築できないの内部の一部をデフォルトで構築しようとしているように見えるということです。(clang は、ここで g++ から見えないことは何も教えてくれません)。

質問:

  1. これは、可変グラフを初期化して通常のグリッドとして開始する正しい方法ですか? 私は当初、自分で関数を書くよりもはるかに簡単だと思っていましたが、今ではよくわかりません!
  2. orig_to_copyここでand/orのデフォルト値がvertex_index適切でないのはなぜですか? この2つがエラーの原因だと思います。(もしあれば、実際に問題を引き起こしているのはどれですか?現在のエラーの根本的な原因が何であるかを解読することはできません)。
  3. これを修正する「正しい」方法は何ですか?
4

1 に答える 1

12

あなたは正しい道を進んでいますが、コードで変更する必要があることが 2 つあります。1 つ目は、カスタム頂点プロパティを定義する特別な方法があることです。2 つ目は、BGL の名前付きパラメーターには別の構文 (より好ましく、おそらく唯一正しい構文) があることです。

最初の項目については、ドキュメントの Custom Vertex Properties というタイトルのセクションを参照してください。基本的に、カスタム頂点プロパティを定義するには、最初に「タグ タイプ」( でstruct終わる名前の_t)を定義する必要があります。

struct vertex_position_t {
    typedef boost::vertex_property_tag kind;
};

boost::property次に、内部に保存された頂点プロパティを定義するテンプレートのどこかにタグ タイプを含めます。

typedef boost::property<boost::vertex_index_t, std::size_t,
        boost::property<vertex_position_t, Position> > VertexProperties;

上記typedefは、内部に保存された 2 つのプロパティを定義しています: インデックスとカスタムの「位置」です。

2 番目の項目では、名前付きパラメーターを使用するための推奨される方法は、「メソッド チェーンのような」構文です。たとえば、関数が 2 つの名前付きパラメーターと を受け入れる場合named_param1、敬意を表して名前空間named_param2に 2 つの関数と があります。関数はパラメーターの値を受け取り、メソッドを持つオブジェクトを返します(同様に、関数はパラメーターの値を受け取り、メソッドを持つオブジェクトを返します)。メソッドを呼び出して、その名前付きパラメーターの値を設定します (これにより、サポートされている他の名前付きパラメーターのメソッドを持つ別のオブジェクトが返されます)。boostnamed_param1named_param2boost::named_param1named_param1named_param2 boost::named_param2named_param2named_param1

val1値を渡すためにval2、名前付きパラメーターnamed_param1およびnamed_param2に対して、次のいずれかを使用できます。

boost::named_parameter1(val1).named_param2(val2)

また:

boost::named_parameter2(val2).named_param1(val1)

 

Graph参考までに、グリッドを次のタイプのオブジェクトにコピーする完全なプログラムを次に示します。

#include <cassert>
#include <cstddef>
#include <cstdlib>
#include <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/copy.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/grid_graph.hpp>
#include <boost/property_map/property_map.hpp>

struct vertex_position_t {
    typedef boost::vertex_property_tag kind;
};

struct Position {
    std::size_t x, y;

    Position()
        : x(0), y(0)
    {
    }
};

typedef boost::property<boost::vertex_index_t, std::size_t, boost::property<vertex_position_t, Position> > VertexProperties;
typedef boost::adjacency_list<boost::vecS, boost::listS, boost::undirectedS, VertexProperties> Graph;
typedef boost::graph_traits<Graph> GraphTraits;

namespace detail {
typedef boost::grid_graph<2> Grid;
typedef boost::graph_traits<Grid> GridTraits;

struct grid_to_graph_vertex_copier {
    typedef boost::property_map< Grid, boost::vertex_index_t>::type grid_vertex_index_map;
    typedef boost::property_map< ::Graph, boost::vertex_index_t>::type graph_vertex_index_map;
    typedef boost::property_map< ::Graph, ::vertex_position_t>::type graph_vertex_position_map;

    const Grid& grid;
    grid_vertex_index_map grid_vertex_index;
    graph_vertex_index_map graph_vertex_index;
    graph_vertex_position_map graph_vertex_position;

    grid_to_graph_vertex_copier(const Grid& grid_, Graph& graph)
        : grid(grid_), grid_vertex_index(get(boost::vertex_index_t(), grid_)),
        graph_vertex_index(get(boost::vertex_index_t(), graph)),
        graph_vertex_position(get(::vertex_position_t(), graph))
    {
    }

private:
    Position grid_vertex_index_to_position(std::size_t idx) const {
        unsigned num_dims = grid.dimensions();
        assert(grid.dimensions() == 2);

        idx %= grid.length(0) * grid.length(1);

        Position ret;
        ret.x = idx % grid.length(0);
        ret.y = idx / grid.length(0);

        return ret;
    }

public:
    void operator()(GridTraits::vertex_descriptor grid_vertex, ::GraphTraits::vertex_descriptor graph_vertex) const {
        std::size_t idx = get(grid_vertex_index, grid_vertex);
        put(graph_vertex_index, graph_vertex, idx);
        Position pos = grid_vertex_index_to_position(idx);
        std::cout << "grid_vertex = " << idx << ", pos.x = " << pos.x << ", pos.y = " << pos.y << std::endl;
        put(graph_vertex_position, graph_vertex, pos);
    }
};

struct grid_to_graph_edge_copier {
    void operator()(GridTraits::edge_descriptor grid_edge, ::GraphTraits::edge_descriptor graph_edge) const {
    }
};
}

int main()
{
    boost::array<std::size_t, 2> lengths = { { 3, 5 } };
    detail::Grid grid(lengths);

    Graph graph;

    boost::copy_graph(grid, graph, boost::vertex_copy(detail::grid_to_graph_vertex_copier(grid, graph))
            .edge_copy(detail::grid_to_graph_edge_copier()));

    std::cout << std::endl;
    boost::write_graphviz(std::cout, graph);

    return EXIT_SUCCESS;
}

これを実行すると、次の出力を受け取りました。

grid_vertex = 0、pos.x = 0、pos.y = 0
grid_vertex = 1、pos.x = 1、pos.y = 0
grid_vertex = 2、pos.x = 2、pos.y = 0
grid_vertex = 3、pos.x = 0、pos.y = 1
grid_vertex = 4、pos.x = 1、pos.y = 1
grid_vertex = 5、pos.x = 2、pos.y = 1
grid_vertex = 6、pos.x = 0、pos.y = 2
grid_vertex = 7、pos.x = 1、pos.y = 2
grid_vertex = 8、pos.x = 2、pos.y = 2
grid_vertex = 9、pos.x = 0、pos.y = 3
grid_vertex = 10、pos.x = 1、pos.y = 3
grid_vertex = 11、pos.x = 2、pos.y = 3
grid_vertex = 12、pos.x = 0、pos.y = 4
grid_vertex = 13、pos.x = 1、pos.y = 4
grid_vertex = 14、pos.x = 2、pos.y = 4

グラフ G {
0;
1;
2;
3;
4;
5;
6;
7;
8;
9;
10;
11;
12;
13;
14;
0--1;
1--2;
3--4;
4--5;
6--7;
7--8;
9--10;
10--11;
12--13;
13--14;
1--0;
2--1;
4--3;
5--4;
7--6;
8--7;
10--9 ;
11--10;
13--12;
14--13;
0--3;
1--4;
2--5;
3--6;
4--7;
5--8;
6--9;
7--10;
8--11;
9--12;
10--13;
11--14;
3--0;
4--1;
5--2 ;
6--3;
7--4;
8--5;
9--6;
10--7 ;
11--8;
12--9 ;
13--10;
14--11;
}
于 2011-09-24T10:51:06.843 に答える