使用boost::copy_graph从网格图复制到邻接列表
Copying from grid_graph to adjacency_list with boost::copy_graph
我正在使用boost图库,并尝试初始化MutableGraph
以开始作为网格的生活。边缘会在以后的生活中添加和删除,所以我认为adjacency_list<vecS,listS,undirectedS>
是正确的选择。
我对BGL的了解表明,用这些边初始化它的明智方法是通过使用boost::copy_graph
从boost::grid_graph
复制,该CCD_5可以免费为我制作所有初始边。我认为这是有道理的——copy_graph
从VertexListGraph
的模型复制到MutableGraph
的模型,这正是我所拥有的。
我最初尝试使用copy_graph
的2参数版本,模糊地希望其余部分的默认值会发生一些合理的事情。事实并非如此,grid_graph
(由于我不太清楚的原因(似乎没有使用带边或顶点的PropertyMap
的功能,因此默认的CCD_ 12和CCD_。
由于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++中看不到的东西(。
问题:
- 这是将可变图初始化为常规网格的正确方法吗?我最初认为这比自己编写函数容易得多,但现在我不太确定了
- 为什么
orig_to_copy
和/或vertex_index
的默认值在这里不合适?我认为这两个是错误的原因。(如果有的话,是哪一个真正造成了问题?我无法解释当前错误的根本原因是什么( - 解决此问题的"正确"方法是什么
您正走在正确的轨道上,但代码中有两件事需要更改。第一个是有一种定义自定义顶点特性的特殊方法。第二个原因是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
定义了两个内部存储的属性:索引和自定义的"位置"。
关于第二项,使用命名参数的首选方式是"类似方法链接"的语法。例如,如果一个函数接受两个命名参数named_param1
和named_param2
,则在boost
命名空间中有两个函数分别命名为named_param1
和named_param2
。boost::named_param1
函数接受named_param1
参数的值,并返回具有named_param2
方法的对象(类似地,boost::named_param2
函数接受boost::grid_graph
0参数的值并返回具有named_param1
的方法的对象(。您调用该方法来设置该命名参数的值(这反过来又返回另一个具有其他支持的命名参数的方法的对象(。
为了传递命名参数named_param1
和named_param2
的值val1
和val2
,您可以使用:
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;
}
当我运行这个程序时,我收到了以下输出:
网格顶点=0,位置x=0,位置y=0网格顶点=1,位置x=1,位置y=0网格顶点=2,位置x=2,位置y=0网格顶点=3,位置x=0,位置y=1网格顶点=4,位置x=1,位置y=1网格顶点=5,位置x=2,位置y=1网格顶点=6,位置x=0,位置y=2网格顶点=7,位置x=1,位置y=2网格顶点=8,位置x=2,位置y=2网格顶点=9,位置x=0,位置y=3网格顶点=10,位置x=1,位置y=3网格顶点=11,位置x=2,位置y=3网格顶点=12,位置x=0,位置y=4网格顶点=13,位置x=1,位置y=4网格顶点=14,位置x=2,位置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-4;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;}
- 复制列表初始化的隐式转换的等级是多少
- 链表,将列表复制到另一个列表
- 我可以从列表中获取对象并复制它们,但如何删除我复制的对象?
- C++完全复制要字符串的字符列表,而不会忽略多个空格
- 如何将列表从一个类复制到另一个类
- 如何在向量列表初始化时避免对象复制以及如何延长临时的生存期
- 如何在不复制列表的情况下将列表传递给线程,同时销毁原始列表
- 复制列表并返回指向第二个列表的指针
- 直接列表初始化和复制列表初始化之间的差异
- 复制列表类的构造函数,而无需在实现中使用任何方法
- 不可复制类型的复制列表初始化
- 在带有转换运算符的初始值设定项的情况下,复制列表初始化的假定行为是什么
- 复制列表初始化和传统复制初始化之间的任何区别
- 为什么标准区分直接列表初始化和复制列表初始化?
- 使用随机指针C 复制列表
- 如何复制列表矢量
- 允许复制列表初始化和显式构造函数
- 复制列表初始化是否在概念上调用复制 ctor
- 复制列表时光荣崩溃
- 为什么我的复制列表初始化停止工作后,我添加继承