繁体   English   中英

使用boost :: copy_graph从grid_graph复制到adjacency_list

[英]Copying from grid_graph to adjacency_list with boost::copy_graph

我使用升压图形库,并试图initalise一个MutableGraph重新开始生活作为一个网格。 边缘将在以后添加和删除,所以我认为adjacency_list<vecS,listS,undirectedS>是正确的选择。

我对BGL的阅读表明,用这些边缘初始化它的明智方法是利用boost::grid_graph通过使用boost::copy_graphboost::grid_graph复制,可以为我免费提供所有初始边缘。 我认为是有道理的- copy_graph从模型复制VertexListGraph的模型MutableGraph ,这正是我。

我最初尝试使用copy_graph的2参数版本,模糊地希望其余的默认值会发生一些明智的事情。 结果并非如此, grid_graph (由于我无法弄清楚的原因)似乎没有使用PropertyMap的边缘或顶点的设施,因此默认的vertex_copyedge_copy失败(使用编译器)错误)复制属性。

由于2参数版本显然不合适,我继续尝试实现自己的二元运算符来复制顶点和边。 即使使用“无操作”副本,这也不如我希望的那样好(即它不会编译)。

我已经汇总了一个说明问题的最小工作示例:

#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和/或vertex_index的默认值不合适? 我假设这两个是错误的原因。 (哪些,如果有的话实际上导致问题?我无法解读当前错误的根本原因)。
  3. 解决这个问题的“正确”方法是什么?

您走在正确的轨道上,但在您的代码中有两件事需要更改。 第一个是有一种定义自定义顶点属性的特殊方法。 第二个是BGL命名参数有不同的语法(更优选,也可能是唯一正确的)。

在第一项上,请参阅标题为“自定义顶点属性”的文档部分 本质上,为了定义自定义顶点属性,您需要首先定义“标记类型”(名称以_t结尾的struct ):

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定义了两个内部存储的属性:index和自定义“position”。

在第二项上,使用命名参数的首选方法是“类似方法链接”语法。 例如,如果函数接受两个命名参数named_param1named_param2 ,则boost命名空间中有两个函数,分别名为named_param1named_param2 boost::named_param1函数接受named_param1参数的值并返回具有named_param2 方法的对象(类似地, boost::named_param2函数接受named_param2参数的值并返回具有named_param1 方法的对象)。 您调用该方法来设置该命名参数的值(该参数又返回另一个具有其他受支持的命名参数的方法的对象)。

为了为命名参数named_param1named_param2传递值val1val2 ,您可以使用:

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM