C++ 使用boost::copy_graph从网格_图复制到邻接_列表

C++ 使用boost::copy_graph从网格_图复制到邻接_列表,c++,boost,boost-graph,C++,Boost,Boost Graph,我正在使用boost graph库,并尝试初始化一个MutableGraph,以网格的形式开始生活。 边缘会在以后的生活中添加和删除,所以我认为邻接列表是正确的选择 我对BGL的阅读表明,使用这些边初始化BGL的明智方法是利用boost::grid\u graph boost::copy_graph从一个boost::grid_graph复制,它可以为我免费创建所有初始边。 我认为这是有意义的-copy\u graph将VertexListGraph的模型复制到MutableGraph的模型,这

我正在使用boost graph库,并尝试初始化一个
MutableGraph
,以网格的形式开始生活。 边缘会在以后的生活中添加和删除,所以我认为
邻接列表
是正确的选择

我对BGL的阅读表明,使用这些边初始化BGL的明智方法是利用
boost::grid\u graph
boost::copy_graph
从一个
boost::grid_graph
复制,它可以为我免费创建所有初始边。 我认为这是有意义的-
copy\u graph
VertexListGraph
的模型复制到
MutableGraph
的模型,这正是我所拥有的

我最初尝试使用双参数版本的
copy\u graph
,模糊地希望在剩下的默认值中会发生一些合理的事情。事实并非如此,
grid\u graph
(出于我无法完全理解的原因)似乎没有一个工具可以使用带有边或顶点的
PropertyMap
s,因此默认的
vertex\u copy
edge\u 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));
}
#包括
#包括
#包括
结构位置{
int x,y;
};
结构顶点属性{
位置pos;
};
typedef boost::邻接列表图;
结构霉菌病{
模板
void运算符()(常数S&/*src*/,D&/*dest*/){
//现在没什么,只是让它编译
//TODO:设置pos值以反映网格上的位置。
}
};
int main(){
数组长度={3,3};
boost::grid\u图形网格(长度);
图形;
霉菌复制机;
//使用3-Arg版本的copy_graph,以便我们可以指定自定义的复制方式来创建属性
boost::copy_graph(网格、图形、boost::bgl_named_params(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> >&)
g++-Wextra-Wall-O2-g-o copytest.o-c copytest.cc
在/usr/include/boost/graph/grid_-graph.hpp:24:0中包含的文件中,
从copytest.cc:2:
/usr/include/boost/iterator/transform\u iterator.hpp:在构造函数'boost::transform\u iterator::transform\u iterator()[带UnaryFunc=boost::detail::grid\u graph\u vertex\u at,iterator=boost::counting\u iterator,Reference=boost::use\u default,Value=boost::use\u default]:
/usr/include/boost/graph/copy.hpp:115:55:从“静态void boost::detail::copy\u graph\u impl::apply”实例化(const-graph&、MutableGraph&、CopyVertex、CopyEdge、Orig2CopyVertexIndexMap、IndexMap)[with Graph=boost::grid\u Graph,MutableGraph=boost::adjacence\u list,CopyVertex=MyCopy,CopyEdge=MyCopy,IndexMap=boost::grid\u Graph\u index\u map,Orig2CopyVertexIndexMap=boost::迭代器属性\u map]'
/usr/include/boost/graph/copy.hpp:327:5:从“void boost::copy_graph(const VertexListGraph&,MutableGraph&,const boost::bgl_named_params&”)实例化[带VertexListGraph=boost::grid_graph,MutableGraph=boost::adjacency_list,P=MyCopy,T=boost::vertext_copy_,R=boost::bgl_named___params]”
/mnt/home/ajw/code/hpcwales/copytest.cc:31:66:从此处实例化
/usr/include/boost/iterator/transform\u iterator.hpp:100:26:错误:调用“boost::detail::grid\u graph\u vertex\u at::grid\u graph\u vertex\u at()”时没有匹配的函数
/usr/include/boost/graph/grid\u-graph.hpp:104:7:注:候选项为:boost::detail::grid\u-graph\u-vertex\u-at::grid\u-graph\u-vertex\u-at(const-graph*)[带graph=boost::grid\u-graph]
/usr/include/boost/graph/grid\u graph.hpp:100:33:注:boost::detail::grid\u graph\u vertex\u at::grid\u graph\u vertex\u at(const boost::detail::grid\u graph\u vertex\u at&)
我对该错误的分析是,它似乎试图默认构造
网格图
内部的一部分,但由于某些我并不十分清楚的原因,它不能默认构造。 (叮当声并没有告诉我任何我在这里看不到的东西)

问题:

  • 这是将可变图初始化为常规网格的正确方法吗?我最初认为这样做比自己编写函数容易得多,但现在我不太确定
  • 为什么
    orig\u to\u copy
    和/或
    vertex\u index
    的默认值在这里不合适?我假设这两个是错误的原因。(如果有的话,哪一个是真正导致问题的原因?我无法解释当前错误的根本原因是什么)
  • 解决这个问题的“正确”方法是什么

  • 您的思路是正确的,但代码中有两件事情需要更改。第一件是有一种特殊的方法来定义自定义顶点属性。第二件是BGL命名参数有一种不同的语法(更可取,而且可能是唯一正确的语法)

    关于第一项,请参阅。基本上,为了定义自定义顶点属性,您需要首先定义一个“标记类型”(一个名称以
    \u t
    结尾的
    结构):

    然后将标记类型包含在定义内部存储的顶点属性的
    boost::property
    模板中的某个位置:

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

    以下是一个完整的程序,用于将网格复制到
    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;
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    结构顶点位置{
    typedef boost::vertex_属性_标记种类;
    };
    结构位置{
    标准:尺寸x,y;
    职位(
    :x(0),y(0)
    {
    }
    };
    typedef boost::属性VertexProperties;
    类型
    
    boost::named_parameter1(val1).named_param2(val2)
    
    boost::named_parameter2(val2).named_param1(val1)
    
    #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 ; }