简体   繁体   English

BGL - 如何在捆绑属性图中使用 BFS 记录距离?

[英]BGL - How to record distances with BFS in bundled properties graph?

I'm trying to do something as simple as getting the distances from one node to all the others, but I'm not getting it right about how to use the breadth_first_search with my graph... I'm getting a lot of compilation errors and I don't undestand why.我正在尝试做一些简单的事情,比如获取一个节点到所有其他节点的距离,但我没有正确了解如何将breadth_first_search与我的图表一起使用......我遇到了很多编译错误我不明白为什么。

I even tried the solutions proposed in other questions, but they didn't work for me我什至尝试了其他问题中提出的解决方案,但它们对我不起作用

Can some one help me?有人能帮我吗?

Definitions:释义:

class Position {
   public:
    Position() : x(0), y(0) {}
    Position(int a, int b) : x(a), y(b) {}

    // operator overrides
    
    int x, y;
};

struct Group {
    Group(Position pos, short c, short s) : position(pos), color(c), size(s) {}
    Group() {}
    Position position;
    short color;
    short size;
};

inline bool operator==(const Group& g1, const Group& g2) {
    return g1.position == g2.position;
};
inline bool operator!=(const Group& g1, const Group& g2) {
    return g1.position != g2.position;
};

typedef boost::adjacency_list<boost::setS, boost::listS, boost::undirectedS, Group, boost::no_property> Graph;

typedef boost::graph_traits<Graph>::vertex_descriptor VertexDescriptor;

Minimal example:最小的例子:

int main() {
    Graph graph;

    // build graph

    VertexDescriptor v = *boost::vertices(graph).first;
    std::vector<int> distances(boost::num_vertices(graph));

    boost::breadth_first_search(graph, v, boost::visitor( boost::make_bfs_visitor( boost::record_distances(distances.begin(), boost::on_tree_edge{}))));

    return 0;
}

Compilation error:编译错误:

In file included from /usr/include/boost/graph/adjacency_list.hpp:223,
                 from src/../include/graph.hpp:4,
                 from src/main.cpp:3:
/usr/include/boost/graph/detail/adjacency_list.hpp: In instantiation of ‘struct boost::adj_list_any_vertex_pa::bind_<boost::vertex_index_t, boost::adjacency_list<boost::setS, boost::listS, boost::undirectedS, Group, boost::no_property>, Group>’:
/usr/include/boost/graph/detail/adjacency_list.hpp:2617:12:   required from ‘struct boost::detail::adj_list_choose_vertex_pa<boost::vertex_index_t, boost::adjacency_list<boost::setS, boost::listS, boost::undirectedS, Group, boost::no_property>, Group>’
/usr/include/boost/graph/detail/adjacency_list.hpp:2754:12:   required from ‘struct boost::adj_list_vertex_property_selector::bind_<boost::adjacency_list<boost::setS, boost::listS, boost::undirectedS, Group, boost::no_property>, Group, boost::vertex_index_t>’
/usr/include/boost/graph/properties.hpp:201:12:   required from ‘struct boost::detail::vertex_property_map<boost::adjacency_list<boost::setS, boost::listS, boost::undirectedS, Group, boost::no_property>, boost::vertex_index_t>’
/usr/include/boost/graph/properties.hpp:212:10:   required from ‘struct boost::property_map<boost::adjacency_list<boost::setS, boost::listS, boost::undirectedS, Group, boost::no_property>, boost::vertex_index_t, void>’
/usr/include/boost/mpl/eval_if.hpp:38:31:   recursively required from ‘struct boost::mpl::eval_if<mpl_::bool_<true>, boost::detail::const_type_as_type<boost::property_map<boost::adjacency_list<boost::setS, boost::listS, boost::undirectedS, Group, boost::no_property>, boost::vertex_index_t, void> >, boost::property_map<boost::adjacency_list<boost::setS, boost::listS, boost::undirectedS, Group, boost::no_property>, boost::vertex_index_t, void> >’
/usr/include/boost/mpl/eval_if.hpp:38:31:   required from ‘struct boost::mpl::eval_if<boost::is_same<boost::param_not_found, boost::param_not_found>, boost::mpl::eval_if<mpl_::bool_<true>, boost::detail::const_type_as_type<boost::property_map<boost::adjacency_list<boost::setS, boost::listS, boost::undirectedS, Group, boost::no_property>, boost::vertex_index_t, void> >, boost::property_map<boost::adjacency_list<boost::setS, boost::listS, boost::undirectedS, Group, boost::no_property>, boost::vertex_index_t, void> >, boost::mpl::identity<boost::param_not_found> >’
/usr/include/boost/graph/named_function_params.hpp:273:12:   required from ‘struct boost::detail::choose_impl_result<mpl_::bool_<true>, boost::adjacency_list<boost::setS, boost::listS, boost::undirectedS, Group, boost::no_property>, boost::param_not_found, boost::vertex_index_t>’
/usr/include/boost/graph/named_function_params.hpp:309:3:   required by substitution of ‘template<class Param, class Graph, class PropertyTag> typename boost::detail::choose_impl_result<mpl_::bool_<true>, Graph, Param, PropertyTag>::type boost::choose_const_pmap(const Param&, const Graph&, PropertyTag) [with Param = boost::param_not_found; Graph = boost::adjacency_list<boost::setS, boost::listS, boost::undirectedS, Group, boost::no_property>; PropertyTag = boost::vertex_index_t]’
/usr/include/boost/graph/breadth_first_search.hpp:315:30:   required from ‘static void boost::detail::bfs_dispatch<boost::param_not_found>::apply(VertexListGraph&, typename boost::graph_traits<Graph>::vertex_descriptor, const boost::bgl_named_params<T, Tag, Base>&, boost::param_not_found) [with VertexListGraph = boost::adjacency_list<boost::setS, boost::listS, boost::undirectedS, Group, boost::no_property>; P = boost::bfs_visitor<boost::distance_recorder<__gnu_cxx::__normal_iterator<int*, std::vector<int> >, boost::on_tree_edge> >; T = boost::graph_visitor_t; R = boost::no_property; typename boost::graph_traits<Graph>::vertex_descriptor = void*]’
/usr/include/boost/graph/breadth_first_search.hpp:343:35:   required from ‘void boost::breadth_first_search(const VertexListGraph&, typename boost::graph_traits<Graph>::vertex_descriptor, const boost::bgl_named_params<T, Tag, Base>&) [with VertexListGraph = boost::adjacency_list<boost::setS, boost::listS, boost::undirectedS, Group, boost::no_property>; P = boost::bfs_visitor<boost::distance_recorder<__gnu_cxx::__normal_iterator<int*, std::vector<int> >, boost::on_tree_edge> >; T = boost::graph_visitor_t; R = boost::no_property; typename boost::graph_traits<Graph>::vertex_descriptor = void*]’
src/main.cpp:41:151:   required from here
/usr/include/boost/graph/detail/adjacency_list.hpp:2547:29: error: forming reference to void
 2547 |         typedef value_type& reference;
      |                             ^~~~~~~~~
/usr/include/boost/graph/detail/adjacency_list.hpp:2548:35: error: forming reference to void
 2548 |         typedef const value_type& const_reference;
      |                                   ^~~~~~~~~~~~~~~
/usr/include/boost/graph/detail/adjacency_list.hpp:2551:47: error: forming reference to void
 2551 |           <Graph, value_type, reference, Tag> type;
      |                                               ^~~~
/usr/include/boost/graph/detail/adjacency_list.hpp:2553:53: error: forming reference to void
 2553 |           <Graph, value_type, const_reference, Tag> const_type;
      |                                                     ^~~~~~~~~~
In file included from src/main.cpp:7:
/usr/include/boost/graph/breadth_first_search.hpp: In instantiation of ‘static void boost::detail::bfs_dispatch<boost::param_not_found>::apply(VertexListGraph&, typename boost::graph_traits<Graph>::vertex_descriptor, const boost::bgl_named_params<T, Tag, Base>&, boost::param_not_found) [with VertexListGraph = boost::adjacency_list<boost::setS, boost::listS, boost::undirectedS, Group, boost::no_property>; P = boost::bfs_visitor<boost::distance_recorder<__gnu_cxx::__normal_iterator<int*, std::vector<int> >, boost::on_tree_edge> >; T = boost::graph_visitor_t; R = boost::no_property; typename boost::graph_traits<Graph>::vertex_descriptor = void*]’:
/usr/include/boost/graph/breadth_first_search.hpp:343:35:   required from ‘void boost::breadth_first_search(const VertexListGraph&, typename boost::graph_traits<Graph>::vertex_descriptor, const boost::bgl_named_params<T, Tag, Base>&) [with VertexListGraph = boost::adjacency_list<boost::setS, boost::listS, boost::undirectedS, Group, boost::no_property>; P = boost::bfs_visitor<boost::distance_recorder<__gnu_cxx::__normal_iterator<int*, std::vector<int> >, boost::on_tree_edge> >; T = boost::graph_visitor_t; R = boost::no_property; typename boost::graph_traits<Graph>::vertex_descriptor = void*]’
src/main.cpp:41:151:   required from here
/usr/include/boost/graph/breadth_first_search.hpp:315:30: error: no matching function for call to ‘choose_const_pmap(const type&, boost::adjacency_list<boost::setS, boost::listS, boost::undirectedS, Group, boost::no_property>&, boost::vertex_index_t)’
  315 |             choose_const_pmap(get_param(params, vertex_index),
      |             ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  316 |                               g, vertex_index)),
      |                               ~~~~~~~~~~~~~~~~
In file included from /usr/include/boost/graph/breadth_first_search.hpp:23,
                 from src/main.cpp:7:
/usr/include/boost/graph/named_function_params.hpp:309:3: note: candidate: ‘template<class Param, class Graph, class PropertyTag> typename boost::detail::choose_impl_result<mpl_::bool_<true>, Graph, Param, PropertyTag>::type boost::choose_const_pmap(const Param&, const Graph&, PropertyTag)’
  309 |   choose_const_pmap(const Param& p, const Graph& g, PropertyTag tag)
      |   ^~~~~~~~~~~~~~~~~
/usr/include/boost/graph/named_function_params.hpp:309:3: note:   substitution of deduced template arguments resulted in errors seen above

Two problems两个问题

Problem 1: Vertex Index问题一:顶点索引

The documented requirements for breadth_first_search include a vertex index. breadth_first_search 的记录要求包括顶点索引。 Since you use a node-based container selector ( listS ) there is no implicit index, so you should provide one :由于您使用基于节点的容器选择器 ( listS ),因此没有隐式索引,因此您应该提供一个

Note: if you use this default, make sure your graph has an internal vertex_index property.注意:如果您使用此默认值,请确保您的图形具有内部 vertex_index 属性。 For example, adjacency_list with VertexList=listS does not have an internal vertex_index property例如,带有 VertexList=listS 的 adjacency_list 没有内部 vertex_index 属性

Here's a simplified example showing that vecS works:这是一个显示vecS有效的简化示例:

Live On Compiler Explorer在编译器资源管理器上运行

using Graph =
    boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, Group>;
using V = Graph::vertex_descriptor;

int main() {
    Graph graph(10);

    V v = vertex(0, graph);

    auto vis = boost::default_bfs_visitor{};

    breadth_first_search(graph, v, visitor(vis));
}

Now changing vecS to listS :现在将vecS更改为listS

using Graph =
    boost::adjacency_list<boost::vecS, boost::listS, boost::undirectedS, Group>;

doesn't compile ( Live ), as expected.没有按预期编译 ( Live )。 So we could supply an external, temporary index: Live所以我们可以提供一个外部的临时索引: Live

std::map<V, int> tmp_index;
for (auto v : boost::make_iterator_range(vertices(graph)))
    tmp_index[v] = tmp_index.size();

auto index_map = boost::make_assoc_property_map(tmp_index);
breadth_first_search(graph, v, visitor(vis).vertex_index_map(index_map));

It still compiles even with unique edges ( setS , Live ).即使有独特的优势( setSLive ),它仍然可以编译。

Now, let's record distances.现在,让我们记录距离。

Problem 2: Distance Map Keys问题2:距离Map键

The keys of the distance map are required to be the vertex descriptor距离 map 的键必须是顶点描述符。¹

You can tell because the compilation error indicates that the distance_recorder tries to call:你可以看出是因为编译错误表明 distance_recorder 试图调用:

put(m_distance, v, get(m_distance, u) + 1);

where v and u are vertex descriptors (and m_distance is the distance propertymap you supplied).其中vu是顶点描述符( m_distance是您提供的距离属性图)。

Two solutions两种解决方案

  • You can use an associative map again: Live您可以再次使用关联 map: Live

     std::map<V, int> distances; auto vis = make_bfs_visitor(record_distances( boost::make_assoc_property_map(distances), boost::on_tree_edge{}));
  • You can fix the propertymap by projecting the key through the temporary vertex index: Live您可以通过临时顶点索引投影键来修复属性映射: Live

     auto index_map = boost::make_assoc_property_map(tmp_index); auto dist_map = make_safe_iterator_property_map(dist.begin(), dist.size(), index_map); auto vis = make_bfs_visitor(record_distances(dist_map, boost::on_tree_edge{}));

¹ Actually it looks like there was a copy paste error because that page incorrectly claims the value type needs to be the vertex-descriptor as well. ¹ 实际上它看起来像有一个复制粘贴错误,因为该页面错误地声称值类型也需要是顶点描述符。 That is (obviously?) copy-pasted from the docs for predecessor_recorder ...那是(显然?)从文档中为predecessor_recorder复制粘贴...

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

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