[BGL] Extending own Graph type to work with BGL

Hi guys and girls, I've got an existing Graph structure, consisting of node and edge classes. The graph structure itself is implicit in the sense that every node contains a list of out edges, and edges know where they start from and go to. I'm using Qt's container classes for simplicity mostly, eg. a node has a QList of successors (QList<Edge*>), and all the nodes and edges get stored in a Network class using QHash<Node*> etc... I've been trying to extend this to work with the BGL, following the LEDA and SGB examples. As far as I know I can simply use the BGL functions on an instance of my own Network, ie. no need to recreate the graph. Is this correct? It would save a lot of cpu time since the network contains several thousand nodes and can be very dense. Thus I haven't implemented any add_node or add_edge functions, because I really only want to analyse the graph and not change anything. Some details of what I've got sofar: -vertex and edge descriptors are simply pointers corresponding to my own classes -vertex and edge iterators are simply typedefs of qhash::const_iterator or qlist::const_iterator -some source code at the bottom. So far so good. Though I've been stuck for 2 days trying to figure out how to get property maps to play nicely with my classes. I thought I'd be able to apply the bundle concept from the adjacency list to my own graph, but I'm not sure what exactly needs to be implemented to work. The idea is to create property maps directly from the members of my classes. Is this possible? What would I need to implement for something like weight_map(get(&Node::cost, Network)) to work? *** How about for member functions? ie. If cost were a function instead of a variable? *** I couldn't really figure out how the bundles are actually accessed. Though simply copying the get and put functions from the adjacency list class seems not to work... I think the crux of the matter really lies in figuring out how to access the pointers corresponding to nodes or edges with this T Bundle::* p that gets passed in. And what do I need to do when creating an exterior property map for storing temp data, for instance the distance map used by dijkstra? This is actually where compilation fails at the moment. Some source: //Getters and putters for bundles template <typename T, typename Bundle> inline typename property_map< Network, T Bundle::*>::type get(T Bundle::* p, Network& g) { typedef typename property_map< Network, T Bundle::*>::type result_type; return result_type(&g, p); } template <typename T, typename Bundle, typename Key> inline T get(T Bundle::* p, Network const & g, const Key& key) { return get(get(p, g), key); } template <typename T, typename Bundle, typename Key> inline void put(T Bundle::* p, Network& g, const Key& key, const T& value) { put(get(p, g), key, value); } The basic source, target etc. implementations: inline graph_traits< Network >::vertex_descriptor source(graph_traits< Network >::edge_descriptor e, const Network& g) { return e->getStart(); } inline graph_traits< Network >::vertex_descriptor target(graph_traits< Network >::edge_descriptor e, const Network& g) { return e->getEnd(); } inline std::pair<graph_traits< Network >::out_edge_iterator, graph_traits< Network >::out_edge_iterator> out_edges(graph_traits< Network >::vertex_descriptor u, const Network& g) { typedef graph_traits< Network >::out_edge_iterator Iter; return std::make_pair( u->getSucc().constBegin() , u->getSucc().constEnd() ); } inline std::pair<graph_traits< Network >::vertex_iterator, graph_traits< Network >::vertex_iterator> vertices(const Network& g) { typedef graph_traits< Network >::vertex_iterator Iter; return std::make_pair( g.getNodes().constBegin(), g.getNodes().constEnd() ); } // property map stuff template <> struct property_map<Network, vertex_index_t> { typedef identity_property_map type; typedef type const_type; }; inline identity_property_map get(vertex_index_t, const Network& g) { return identity_property_map(); } inline identity_property_map get(edge_index_t, const Network& g) { return identity_property_map(); } I really think everything else is working though I just can't get these silly property maps to play nicely. If someone could point me in the right direction it would be swell. I think once I get everything to work it would make a great example too. Though personally I thought something like this would be quite standard, though I couldn't find anything in the mailing list archives. Thanks for reading! And have a great day, Christian

on Wed Jul 09 2008, "Christiaan Putter" <ceputter-AT-googlemail.com> wrote:
Hi guys and girls,
I've got an existing Graph structure, consisting of node and edge classes. The graph structure itself is implicit in the sense that every node contains a list of out edges, and edges know where they start from and go to.
I'm using Qt's container classes for simplicity mostly, eg. a node has a QList of successors (QList<Edge*>), and all the nodes and edges get stored in a Network class using QHash<Node*> etc...
I've been trying to extend this to work with the BGL, following the LEDA and SGB examples.
As far as I know I can simply use the BGL functions on an instance of my own Network, ie. no need to recreate the graph. Is this correct?
Yes, that's what makes BGL a generic library :-) -- Dave Abrahams BoostPro Computing http://www.boostpro.com

Hi guys, Thanks for the clarification Dave, after struggling for for 2 days I wasn't so sure any more. Still not getting it right though. It seems the basic structure of the BGL interface works on my graph. I can run a bfs with "visitor(default_bfs_visitor())" , and it searches through the graph quite well. However when adding my own visitor... Taken from the bfs visitor example: class bfs_name_printer : public default_bfs_visitor { public: bfs_name_printer() { }; template <typename Vertex, typename Graph> void discover_vertex(Vertex u, const Graph &) const { std::cout << u << ' '; } }; Node* s = _network.getNodes().value(20); bfs_name_printer vis(); breadth_first_search(_network, s, visitor(vis)); Passing my own visitor causes the whole thing not to compile, with the error message: *********************************** *********************************** N:/_tools/boost_1_35_0/boost/graph/named_function_params.hpp: In instantiation of `boost::bgl_named_params<bfs_name_printer ()(), boost::graph_visitor_t, boost::no_property>': N:\_devel\_workspace\GWISeo\src\core\solution.cpp:186: instantiated from here N:/_tools/boost_1_35_0/boost/graph/named_function_params.hpp:58: error: field `boost::bgl_named_params<bfs_name_printer ()(), boost::graph_visitor_t, boost::no_property>::m_value' invalidly declared function type N:/_tools/boost_1_35_0/boost/graph/breadth_first_search.hpp: In static member function `static void boost::detail::bfs_dispatch<boost::detail::error_property_not_found>::apply(Vert exListGraph&, typename boost::graph_traits<G>::vertex_descriptor, const boost::bgl_named_params<P, T, R>&, boost::detail::error_property_not_found) [with VertexListGraph = Network, P = bfs_name_printer ()(), T = boost::graph_visitor_t, R = boost::no_property]': N:/_tools/boost_1_35_0/boost/graph/breadth_first_search.hpp:255: instantiated from `void boost::breadth_first_search(const VertexListGraph&, typename boost::graph_traits<G>::vert ex_descriptor, const boost::bgl_named_params<P, T, R>&) [with VertexListGraph = Network, P = bfs_name_printer ()(), T = boost::graph_visitor_t, R = boost::no_property]' N:\_devel\_workspace\GWISeo\src\core\solution.cpp:186: instantiated from here N:/_tools/boost_1_35_0/boost/graph/breadth_first_search.hpp:226: error: function return type cannot be function N:/_tools/boost_1_35_0/boost/graph/named_function_params.hpp:656: error: function return type cannot be function N:/_tools/boost_1_35_0/boost/graph/breadth_first_search.hpp:226: error: function return type cannot be function N:/_tools/boost_1_35_0/boost/graph/named_function_params.hpp: In function `typename boost::property_value<boost::bgl_named_params<T1, Tag1, Base>, Tag2>::type boost::get_param(cons t boost::bgl_named_params<T1, Tag1, Base>&, Tag2) [with Tag1 = boost::graph_visitor_t, Tag2 = boost::graph_visitor_t, T1 = bfs_name_printer ()(), Base = boost::no_property]': N:/_tools/boost_1_35_0/boost/graph/breadth_first_search.hpp:226: instantiated from `static void boost::detail::bfs_dispatch<boost::detail::error_property_not_found>::apply(Vertex ListGraph&, typename boost::graph_traits<G>::vertex_descriptor, const boost::bgl_named_params<P, T, R>&, boost::detail::error_property_not_found) [with VertexListGraph = Network, P = bfs_name_printer ()(), T = boost::graph_visitor_t, R = boost::no_property]' N:/_tools/boost_1_35_0/boost/graph/breadth_first_search.hpp:255: instantiated from `void boost::breadth_first_search(const VertexListGraph&, typename boost::graph_traits<G>::vert ex_descriptor, const boost::bgl_named_params<P, T, R>&) [with VertexListGraph = Network, P = bfs_name_printer ()(), T = boost::graph_visitor_t, R = boost::no_property]' N:\_devel\_workspace\GWISeo\src\core\solution.cpp:186: instantiated from here N:/_tools/boost_1_35_0/boost/graph/named_function_params.hpp:656: error: function return type cannot be function N:/_tools/boost_1_35_0/boost/graph/breadth_first_search.hpp:226: instantiated from `static void boost::detail::bfs_dispatch<boost::detail::error_property_not_found>::apply(Vertex ListGraph&, typename boost::graph_traits<G>::vertex_descriptor, const boost::bgl_named_params<P, T, R>&, boost::detail::error_property_not_found) [with VertexListGraph = Network, P = bfs_name_printer ()(), T = boost::graph_visitor_t, R = boost::no_property]' N:/_tools/boost_1_35_0/boost/graph/breadth_first_search.hpp:255: instantiated from `void boost::breadth_first_search(const VertexListGraph&, typename boost::graph_traits<G>::vert ex_descriptor, const boost::bgl_named_params<P, T, R>&) [with VertexListGraph = Network, P = bfs_name_printer ()(), T = boost::graph_visitor_t, R = boost::no_property]' N:\_devel\_workspace\GWISeo\src\core\solution.cpp:186: instantiated from here N:/_tools/boost_1_35_0/boost/graph/named_function_params.hpp:662: error: invalid conversion from `bfs_name_printer (*)()' to `int' etc. etc. *********************************** *********************************** I'm quite sure their must be something I've left out or done wrong when writing the BGL interface for my graph. If anybody can point me in the right direction I'd be very grateful. And advice on how to implement the bundle concept in my own graph would be great too. Have a nice day, Christiaan 2008/7/9 David Abrahams <dave@boostpro.com>:
on Wed Jul 09 2008, "Christiaan Putter" <ceputter-AT-googlemail.com> wrote:
Hi guys and girls,
I've got an existing Graph structure, consisting of node and edge classes. The graph structure itself is implicit in the sense that every node contains a list of out edges, and edges know where they start from and go to.
I'm using Qt's container classes for simplicity mostly, eg. a node has a QList of successors (QList<Edge*>), and all the nodes and edges get stored in a Network class using QHash<Node*> etc...
I've been trying to extend this to work with the BGL, following the LEDA and SGB examples.
As far as I know I can simply use the BGL functions on an instance of my own Network, ie. no need to recreate the graph. Is this correct?
Yes, that's what makes BGL a generic library :-)
-- Dave Abrahams BoostPro Computing http://www.boostpro.com _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Hi, Christian, Seems the error message you have does not indicate to your specialized functions. It is more likely of incorrect BFS call. Does the call of boost::get(vertex_index, g) returns a vertex_index property map? The bundled property maps can be understood from its implementaion, I think. Just take a look: http://svn.boost.org/svn/boost/trunk/boost/graph/properties.hpp #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES template<typename Graph, typename Descriptor, typename Bundle, typename T> struct bundle_property_map : put_get_helper<T&, bundle_property_map<Graph, Descriptor, Bundle, T> > { typedef Descriptor key_type; typedef T value_type; typedef T& reference; typedef lvalue_property_map_tag category; bundle_property_map() { } bundle_property_map(Graph* g_, T Bundle::* pm_) : g(g_), pm(pm_) {} reference operator[](key_type k) const { return (*g)[k].*pm; } private: Graph* g; T Bundle::* pm; }; //The gr So, 1. bundled_property_map is a propery_map 2. In order to use it like it is your graph class need operator[](Vertex) and operator[](Edge) functions be defined. Assume that each vertex of you graph has associated properties struct edgeinfo_t { //A lot of properties}; then the return type of operator[](Edge) is edgeinfo_t& 3 (just in case). T Bundle::* pm; Is a pointer member to the edge or vertex properties. Variable of this type is not a real pointer. Its value isa shift from the beginning of the structure till the given structure member. It can take values like 0,4, 10 etc. It can be used like this: struct EP { int m; } int EP::* pm = &EP::m; //Set to 0 EP s; std::cout << s.*pm << std::endl; 4. If your graph is not a class at all you can: a) Modify the line : reference operator[](key_type k) const { return (*g)[k].*pm; } as you need. b) Write a simple subscript adapter: struct subscriptAdaptor { typedef nodeinfo_t vertex_bundled; typedef edgeinfo_t edge_bundled; subscriptAdaptor(Graph const &g) : m_g(g) {} edgeinfo_t& operator[](Edge &e) { edgeinfo_t& r = *(edgeinfo_t*)get_data(e); return r; } nodeinfo_t& operator[](Vertex &n) { nodeinfo_t& r = *(nodeinfo_t*)get_data(n); return r; } private: Graph const &m_g; }; and then use it: typedef boost::bundle_property_map<Graph, Edge, edgeinfo_t, int> em_t; or equivalently typedef boost::property_map<Graph, int edgeinfo_t::*>::type em_t; Graph g; subscriptAdaptor sa(g); em_t em(sa, &edgeinfo_t::id); //em is an edge property_map 5. If you edgeinfo_t structure has some functions you can slightly modify the standard bundle_property_map and make it to use pointer to member function instead of pointer to member. (Untested) That is all, in brief. Hope this will help. Dmitry Christiaan Putter wrote:
Hi guys,
Thanks for the clarification Dave, after struggling for for 2 days I wasn't so sure any more. Still not getting it right though.
It seems the basic structure of the BGL interface works on my graph. I can run a bfs with "visitor(default_bfs_visitor())" , and it [snip]
Node* s = _network.getNodes().value(20);
bfs_name_printer vis(); breadth_first_search(_network, s, visitor(vis));
Passing my own visitor causes the whole thing not to compile, with the error message:
*********************************** ***********************************
[a lot of g++ compilation errors]
N:\_devel\_workspace\GWISeo\src\core\solution.cpp:186: instantiated from here N:/_tools/boost_1_35_0/boost/graph/named_function_params.hpp:662: error: invalid conversion from `bfs_name_printer (*)()' to `int'
etc. etc.
*********************************** ***********************************
I'm quite sure their must be something I've left out or done wrong when writing the BGL interface for my graph. If anybody can point me in the right direction I'd be very grateful.
And advice on how to implement the bundle concept in my own graph would be great too.
Have a nice day, Christiaan
2008/7/9 David Abrahams <dave@boostpro.com>:

Hi all I would like to know where I can get some information about how to use the relaxed heaps in Boost? I would also like to know which file/files it is located in? Are there any bugs on relaxed heaps that has been fixed since 1.33.1 ? Thanks alot for your help. Line

Hi Line, afaik there is no real documentation for the relaxed heap. It resides in boost/pending/relaxed_heap.hpp. There's also a binary heap in mutable_queue.hpp. Find below some basic code on how to initialize the heaps typedef graph_traits<graph_t>::vertex_descriptor vertex_t; typedef property_map<graph_t, vertex_index_t>::const_type vertex_index_map_t; // set up distance map typedef iterator_property_map<std::vector<cost_t>::iterator, vertex_index_map_t> distance_map_t; std::vector<cost_t> distance_vector(num_vertices(graph),std::numeric_limits<cost_t>::max()); distance_map_t distances(distance_vector.begin(), vertex_indices); typedef indirect_cmp<distance_map_t, compare_t> indirect_cmp_t; indirect_cmp_t icmp(distances, compare_t()); #ifdef MUTABLE typedef mutable_queue<vertex_t, std::vector<vertex_t>, indirect_cmp_t, vertex_index_map_t> Queue; #endif #ifdef RELAXED typedef relaxed_heap<vertex_t, indirect_cmp_t, vertex_index_map_t> Queue; #endif Queue Q(num_vertices(g), icmp, vertex_indices); afterwards you can insert elements into the heap via Q.push( ... ), get a reference to the first element via Q.top(), remove the first with Q.pop(), update an element's position with Q.update( ... ), ask if Q.empty() etc. Regards, Moritz On Fri, Jul 11, 2008 at 1:55 AM, Line Blander Reinhardt <lbr@imm.dtu.dk> wrote:
Hi all I would like to know where I can get some information about how to use the relaxed heaps in Boost? I would also like to know which file/files it is located in? Are there any bugs on relaxed heaps that has been fixed since 1.33.1 ?
Thanks alot for your help. Line
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Thanks Moritz for the information and the examples. It is expecially merging heaps I am interested in and it seems that relaxed_heap has a combine method to merge heaps. Thanks alot for the help. Line ________________________________ Fra: boost-users-bounces@lists.boost.org på vegne af moritz Hilger Sendt: fr 11-07-2008 09:55 Til: boost-users@lists.boost.org Emne: Re: [Boost-users] Relaxed heaps Hi Line, afaik there is no real documentation for the relaxed heap. It resides in boost/pending/relaxed_heap.hpp. There's also a binary heap in mutable_queue.hpp. Find below some basic code on how to initialize the heaps typedef graph_traits<graph_t>::vertex_descriptor vertex_t; typedef property_map<graph_t, vertex_index_t>::const_type vertex_index_map_t; // set up distance map typedef iterator_property_map<std::vector<cost_t>::iterator, vertex_index_map_t> distance_map_t; std::vector<cost_t> distance_vector(num_vertices(graph),std::numeric_limits<cost_t>::max()); distance_map_t distances(distance_vector.begin(), vertex_indices); typedef indirect_cmp<distance_map_t, compare_t> indirect_cmp_t; indirect_cmp_t icmp(distances, compare_t()); #ifdef MUTABLE typedef mutable_queue<vertex_t, std::vector<vertex_t>, indirect_cmp_t, vertex_index_map_t> Queue; #endif #ifdef RELAXED typedef relaxed_heap<vertex_t, indirect_cmp_t, vertex_index_map_t> Queue; #endif Queue Q(num_vertices(g), icmp, vertex_indices); afterwards you can insert elements into the heap via Q.push( ... ), get a reference to the first element via Q.top(), remove the first with Q.pop(), update an element's position with Q.update( ... ), ask if Q.empty() etc. Regards, Moritz On Fri, Jul 11, 2008 at 1:55 AM, Line Blander Reinhardt <lbr@imm.dtu.dk> wrote:
Hi all I would like to know where I can get some information about how to use the relaxed heaps in Boost? I would also like to know which file/files it is located in? Are there any bugs on relaxed heaps that has been fixed since 1.33.1 ?
Thanks alot for your help. Line
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (5)
-
Christiaan Putter
-
David Abrahams
-
Dmitry Bufistov
-
Line Blander Reinhardt
-
moritz Hilger