在BGL的上下文中,我需要迭代in_edges
和out_edges
,但我想排除那些属于反向边缘的那些,即排除那些属于反向边缘的那些property_map
1}}。下面的代码显示了我想要做的事情,但当然property_map
没有find
和end
方法。
更新:
一种可能的解决方案是在构建图形时保持一个单独的结构,如包含反向边的地图。如果我控制了图形构建,这将起作用,但我没有,因为我使用函数read_dimacs_max_flow
来读取DIMACS格式的图形文件。所以我只能依靠BGL的可访问性方法来弄清楚它是什么。
图表定义:
typedef adjacency_list_traits<vecS, vecS, bidirectionalS> ttraits;
typedef adjacency_list<vecS, vecS, bidirectionalS,
// vertex properties
property<vertex_index_t, int,
property<vertex_color_t, default_color_type> >,
// edge properties
property<edge_capacity_t, int,
property<edge_residual_capacity_t, int,
property<edge_reverse_t, ttraits::edge_descriptor> > >, no_property, vecS> tbgl_adjlist_bidir;
typedef graph_traits<tbgl_adjlist_bidir>::vertex_descriptor tvertex;
typedef graph_traits<tbgl_adjlist_bidir>::edge_descriptor tedge;
typedef property_map<tbgl_adjlist_bidir, edge_capacity_t>::type tedge_capacity_map;
typedef property_map<tbgl_adjlist_bidir, edge_reverse_t>::type treverse_edge_map;
typedef property_map<tbgl_adjlist_bidir, vertex_color_t>::type tvertex_color_map;
typedef property_map<tbgl_adjlist_bidir, vertex_index_t>::type tvertex_index_map;
typedef graph_traits<tbgl_adjlist_bidir>::vertex_iterator tvertex_iterator;
typedef graph_traits<tbgl_adjlist_bidir>::edge_iterator tedge_iterator;
typedef graph_traits<tbgl_adjlist_bidir>::out_edge_iterator tout_edge_iterator;
typedef graph_traits<tbgl_adjlist_bidir>::in_edge_iterator tin_edge_iterator;
以及我想要做的示例片段(但不会使用下面的错误进行编译):
tvertex_index_map indices = get(vertex_index, bgl_adjlist_bidir);
tedge_capacity_map capacities = get(edge_capacity, bgl_adjlist_bidir);
treverse_edge_map rev_edges = get(edge_reverse, bgl_adjlist_bidir);
// iterate all vertices in the right order
for (int current = 0; current < m_num_vertices; ++current) {
printf("processing vertex=%d\n", current);
tin_edge_iterator ei1, ei1_end;
for (tie(ei1, ei1_end) = in_edges(tvertex(current), bgl_adjlist_bidir); ei1 != ei1_end; ++ei1) {
// exclude reverse edges <<<<<<<======= HOW DO I DO THIS??
if (rev_edges.find(*ei1) != rev_edges.end()) {
continue;
}
int in = indices[boost::source(*ei1, bgl_adjlist_bidir)];
printf("in edge: %d <- %d \n", current, in);
}
}
和编译器错误:
/Users/bravegag/code/fastcode_project/build_debug$ make 2> out ; grep -i "error" ./out
[ 2%] Building CXX object CMakeFiles/submodularity.dir/src/graph/hp_adjlist_bidir.cc.o
/Users/bravegag/code/fastcode_project/code/src/api/hp_adjlist_bidir.h:146:18: error: 'treverse_edge_map' has no member named 'find'
/Users/bravegag/code/fastcode_project/code/src/api/hp_adjlist_bidir.h:146:42: error: 'treverse_edge_map' has no member named 'end'
make[2]: *** [CMakeFiles/submodularity.dir/src/graph/hp_adjlist_bidir.cc.o] Error 1
make[1]: *** [CMakeFiles/submodularity.dir/all] Error 2
make: *** [all] Error 2
答案 0 :(得分:2)
您的edge_reverse
属性映射会将边缘描述符与图形的每个边缘相关联。因此,“查找”函数没有任何意义,因为所有边将在该属性映射中具有相应的条目(请记住,此类属性映射不一定实现为std::map
对象,事实上,它们不属于内部属性。)
您可以而且应该做的一件事是为每个边设置反向边属性的值,使其成为反向边的边描述符或无效的边描述符(对于非反向边) 。然后,检查(而不是“查找”)只是检查反向边缘属性是否是有效边缘描述符。
不幸的是,BGL不提供null_edge()
静态函数(就像null_vertex()
一样)。这可能是开发人员的遗漏(我开发了一些自己的图形结构,并且我包含了null_edge()
函数,但没有包含在Boost中)。这意味着很难想出一个好的,可移植的“空边”描述符值来使用。一种选择是使用特定的位模式,如下所示:
ttraits::edge_descriptor my_null_edge;
memset((char*)&my_null_edge, 0xFF, sizeof(ttraits::edge_descriptor));
然后,确保非反向边的所有反向边属性都设置为my_null_edge
,然后通过此比较实现循环:
for (tie(ei1, ei1_end) = in_edges(tvertex(current), bgl_adjlist_bidir); ei1 != ei1_end; ++ei1) {
// exclude reverse edges
if (rev_edges[*ei1] != my_null_edge) {
continue;
}
int in = indices[boost::source(*ei1, bgl_adjlist_bidir)];
printf("in edge: %d <- %d \n", current, in);
}
如果您的反向边缘属性非常稀疏,您可能希望使用类似std::map
(或std::unordered_map
)的地图类来创建外部属性地图。在adjacency-list类模板中指定为EdgeProperty或VertexProperty的内容按值(kind-of)存储,用于图的每个顶点或边。如果你想要std::map
行为(只存储具有指定属性的子集),那么你可以在外部对邻接列表图执行此操作,属性映射的好处是它们不必对应内部属性,这也是有用的。所以,你可以这样做:
typedef std::map< tedge, tedge > treverse_edge_map;
treverse_edge_map rev_edges;
如果您需要使用rev_edges
作为BGL属性映射,那么您可以使用:
typedef boost::associative_property_map< treverse_edge_map > tbgl_reverse_edge_map;
tbgl_reverse_edge_map bgl_rev_edges = boost::make_assoc_property_map(rev_edges);
但是,当然,一旦它是BGL样式的属性映射,您就不能再使用“查找”机制来确定是否为给定边缘设置了属性。