2

I have constructed a boost BGL graph:

using vertex_t = std::variant<node_t, specialNode_t>; // structs
using edge_t = std::variant<TerminalType>;            // enum

using Graph_t = boost::adjacency_list<
    boost::vecS,
    boost::vecS,
    boost::undirectedS,
    vertex_t,
    edge_t>;

Graph_t myGraph;

and I'm trying to find (collect) all vertices reachable from a certain starting point (vertex) sorted by their distance. That means I'd like to create a list of all vertices reachable from a certain starting vertex where "nearer" vertices are stored earlier in the list/vector. Therefore I (think I) need BFS.

Unfortunately I failed to find out how to do that without compile error:

boost::queue<vertex_t> Q;
boost::default_bfs_visitor vis; // Will do my collecting visitor later...

auto indexmap = boost::get(boost::vertex_index, myGraph);
auto colormap = boost::make_vector_property_map<boost::default_color_type>(indexmap);

boost::breadth_first_visit(myGraph, start, std::ref(Q), vis, colormap);

this leads to the following errors:

Error   C2039   'push': is not a member of 'std::reference_wrapper<boost::queue<ListSim::vertex_t,std::deque<_Tp,std::allocator<_Ty>>>>'
Error   C2039   'empty': is not a member of 'std::reference_wrapper<boost::queue<ListSim::vertex_t,std::deque<_Tp,std::allocator<_Ty>>>>'
Error   C2039   'top': is not a member of 'std::reference_wrapper<boost::queue<ListSim::vertex_t,std::deque<_Tp,std::allocator<_Ty>>>>'
Error   C2039   'pop': is not a member of 'std::reference_wrapper<boost::queue<ListSim::vertex_t,std::deque<_Tp,std::allocator<_Ty>>>>'
Error   C2039   'push': is not a member of 'std::reference_wrapper<boost::queue<ListSim::vertex_t,std::deque<_Tp,std::allocator<_Ty>>>>'

My questions:

  1. Can anyone shed some light on my mistake? Or maybe a pointer to an example?
  2. Is there possibly a better (in terms of efficiency) or different approach to reach that goal?

(I though about using "connected_components" first... but it uses DFS which cannot fulfill the distance/sorting criteria I have).

fhw72
  • 1,066
  • 1
  • 11
  • 19

1 Answers1

1

The docs say that the Buffer needs to be a queue of vertex_descriptors. You accidentally declared it to have vertex_t (the vertex property bundle) as the value type.

Fix it:

using vertex_descriptor = boost::graph_traits<Graph_t>::vertex_descriptor;

boost::queue<vertex_descriptor> Q;

And it compiles:

Live On Coliru

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/breadth_first_search.hpp>
#include <variant>

struct node_t {
};
struct specialNode_t {
};
enum class TerminalType {
};

using vertex_t = std::variant<node_t, specialNode_t>; // structs
using edge_t = std::variant<TerminalType>;            // enum

using Graph_t = boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, vertex_t, edge_t>;

int main() {
    Graph_t myGraph(5);
    boost::default_bfs_visitor vis; // Will do my collecting visitor later...

    auto indexmap = boost::get(boost::vertex_index, myGraph);
    auto colormap = boost::make_vector_property_map<boost::default_color_type>(indexmap);

    using vertex_descriptor = boost::graph_traits<Graph_t>::vertex_descriptor;

    boost::queue<vertex_descriptor> Q;
    boost::breadth_first_visit(myGraph, 0, Q, vis, colormap);
}
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Thanks. I also had to replace the std::ref(Q) with just Q... two mistakes in one line. OMG – fhw72 Dec 21 '18 at 11:42
  • That's nothing :) This is C++. And Boost – sehe Dec 21 '18 at 11:59
  • LOL. Just a last question: When using bundled vertices/edges all examples I've seen even single (lets say) uint32_t in a struct. Are there any restrictions why I cannot use the uint32_t directly? – fhw72 Dec 21 '18 at 20:43
  • No restrictions. Just good practice. Why make your code significantly less versatile and non-conventional? – sehe Dec 21 '18 at 21:09
  • I think `boost::queue` should come from the header file `boost/pending/queue.hpp`, which has been `include`d in [`breadth_first_search.hpp`](https://www.boost.org/doc/libs/1_81_0/boost/graph/breadth_first_search.hpp). Therefore, `#include ` here seems redundant and misleading. Moreover, `breadth_first_visit()` requires a `top` method of the buffer object, which is unfortunately absent in `std::queue`. Under the hood, `boost::queue` implements `top()` and `front()` exactly the same, but BGL's BFS algorithms choose to use `top()` instead of `front()`. – wu1meng2 Sep 02 '23 at 23:10
  • @wu1meng2 You're correct. Removed the misleading include – sehe Sep 02 '23 at 23:21