boost :: copy_graph的vertex_copy如何工作?

时间:2016-11-05 20:10:39

标签: c++ boost boost-graph

我正在使用boost::copy_graphadjacency_list复制到具有不同adjacency_list模板的其他VertexProperties。为此,我尝试使用vertex_copy参数(doc here)。我遇到了一个编译器错误,告诉我第二个(待复制)图的顶点属性有一个错误的类型。

最小示例

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

typedef boost::adjacency_list<boost::vecS,
                              boost::vecS,
                              boost::undirectedS,
                              uint32_t,
                              float> AdjacencyList;

typedef AdjacencyList::vertex_descriptor VertexID;

struct custom_property
{
    uint32_t label;
    float f;
};

typedef boost::adjacency_list<boost::vecS,
                              boost::vecS,
                              boost::undirectedS,
                              custom_property,
                              float> AdjacencyListCustom;

struct vertex_copier
{
    void operator() (uint32_t &input, custom_property &output)
    {
        output.label = input;
        output.f = 0.;
    }
};


int main(int argc, char** argv)
{
    AdjacencyList adj;
    VertexID id_0 = boost::add_vertex(0, adj);
    VertexID id_1 = boost::add_vertex(1, adj);
    VertexID id_2 = boost::add_vertex(2, adj);
    VertexID id_3 = boost::add_vertex(4, adj);
    boost::add_edge(id_0, id_1, 1.0f, adj);
    boost::add_edge(id_2, id_3, 2.0f, adj);

    AdjacencyListCustom adj_custom;
    boost::copy_graph(adj, adj_custom,  boost::vertex_copy(vertex_copier()));

}

g ++编译错误

...
/usr/include/boost/graph/copy.hpp:164:22: error: no match for call to '(vertex_copier) (boost::iterators::detail::iterator_facade_base<boost::range_detail::integer_iterator<long unsigned int>, long unsigned int, boost::iterators::random_access_traversal_tag, long unsigned int, long int, false, false>::reference, boost::graph_traits<boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, custom_property, float> >::vertex_descriptor&)'
           copy_vertex(*vi, new_v);
           ~~~~~~~~~~~^~~~~~~~~~~~
/path/to/file.cpp: note: candidate: void vertex_copier::operator()(uint32_t&, custom_property&)
     void operator() (uint32_t &input, custom_property &output)
          ^~~~~~~~
/path/to/file.cpp: note:   no known conversion for argument 2 from 'boost::graph_traits<boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, custom_property, float> >::vertex_descriptor {aka long unsigned int}' to 'custom_property&'

这告诉我vertex_copy实际上是在尝试复制vertex_descriptorlong unsigned int,而不是custom_property。这似乎违背了文档中所述的内容:

这是一个二进制函数,它将原始图形中顶点的属性复制到副本中的相应顶点。

vertex_copy如何运作?它可以用于在复制的图形中设置/定义不在原始图像中的顶点属性吗?如果没有,通过迭代图表,是否必须在复制后设置这些属性?我可以应用映射 en masse 还是必须访问和更新每个顶点?

修改 如果我在未指定copy_graph的情况下尝试使用vertex_copy,则会出现错误,因为=custom_property之间不存在uint32_t运算符。

1 个答案:

答案 0 :(得分:3)

将问题放在一边,实现目标的最简单方法是将适当的转换构造函数添加到自定义属性中:

struct custom_property {
    custom_property(uint32_t label = 0, float f = 0) : label(label), f(f) {}
    uint32_t label;
    float f;
};

在这种情况下,简单的副本将起作用:

boost::copy_graph(adj, adj_custom);

查看 Live On Coliru

关于顶点复制器,它接收顶点描述符。要访问顶点属性,您需要具有图形引用:

struct vertex_copier {
    AdjacencyList& from;
    AdjacencyListCustom& to;

    void operator()(AdjacencyList::vertex_descriptor input, AdjacencyListCustom::vertex_descriptor output) const {
        to[output] = { from[input], 0.f };
    }
};

在这种情况下,您可以调用内容:

boost::copy_graph(adj, adj_custom, boost::vertex_copy(vertex_copier{adj, adj_custom}));

再次, Live On Coliru

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

typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, uint32_t, float> AdjacencyList;

typedef AdjacencyList::vertex_descriptor VertexID;

    struct custom_property {
        //custom_property(uint32_t label = 0, float f = 0) : label(label), f(f) {}
        uint32_t label;
        float f;
    };

typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, custom_property, float> AdjacencyListCustom;

struct vertex_copier {
    AdjacencyList& from;
    AdjacencyListCustom& to;

    void operator()(AdjacencyList::vertex_descriptor input, AdjacencyListCustom::vertex_descriptor output) const {
        to[output] = { from[input], 0.f };
    }
};

int main(int argc, char **argv) {
    AdjacencyList adj;
    VertexID id_0 = boost::add_vertex(0, adj);
    VertexID id_1 = boost::add_vertex(1, adj);
    VertexID id_2 = boost::add_vertex(2, adj);
    VertexID id_3 = boost::add_vertex(4, adj);
    boost::add_edge(id_0, id_1, 1.0f, adj);
    boost::add_edge(id_2, id_3, 2.0f, adj);

    AdjacencyListCustom adj_custom;
    boost::copy_graph(adj, adj_custom, boost::vertex_copy(vertex_copier{adj, adj_custom}));
}