Boost logo

Boost Users :

Subject: Re: [Boost-users] [BGL] Having a cost function as weight map
From: Jeremiah Willcock (jewillco_at_[hidden])
Date: 2009-12-18 12:21:11


On Fri, 18 Dec 2009, Maxime van Noppen wrote:

> Hi,
>
> I can't find how to do this pretty basic thing : having a function
> instead of a field to compute the cost of edges for various path finding
> algorithms. I couldn't find the answer in the documentation and Google
> was of no help. Did I miss something obvious ?
>
> Example :
>
> -------------------
> #include <boost/graph/dijkstra_shortest_paths.hpp>
> #include <boost/graph/graph_traits.hpp>
> #include <boost/graph/adjacency_list.hpp>
>
> struct my_edge
> {
> double cost() const { return cost_ * 2; }
> double cost_;
> };
>
> struct my_node
> {
> };
>
> int main()
> {
> typedef boost::adjacency_list< boost::vecS, boost::vecS,
> boost::directedS, my_node, my_edge >
> graph_t;
> typedef boost::graph_traits<graph_t>::vertex_descriptor vertex_t;
>
> graph_t graph;
>
> vertex_t v /*= ... */;
>
> using boost::weight_map;
>
> // Works :
> boost::dijkstra_shortest_paths(graph, v,
> weight_map(boost::get(&my_edge::cost_, graph)));
>
> // Doesn't compile :
> //boost::dijkstra_shortest_paths(graph, v,
> // weight_map(boost::get(&my_edge::cost, graph)));
> }
> -------------------
>
>
> Thanks !

It looks like there is no property map that does what you want, although
there should be. Try something like this (not tested); it assumes that
your functors are lightweight to copy, have a const operator()(), and do
not have any internal state:

#include <boost/property_map/property_map.hpp>
#include <boost/utility.hpp>

template <typename Functor, typename Arg>
struct function_property_map {
   private:
   Functor f;

   public:
   explicit function_property_map(const Functor& f): f(f) {}

   friend value_type get(const function_property_map& pm, const Arg& x) {
     return pm.f(x);
   }
};

namespace boost {
   template <typename Functor, typename Arg>
   struct property_traits<function_property_map<Functor, Arg> > {
     typedef typename boost::result_of<Functor(Arg)>::type value_type;
     typedef value_type reference;
     typedef Arg key_type;
     typedef boost::readable_property_map_tag category;
   };
}

template <typename Arg, typename Functor>
function_property_map<Functor, Arg>
make_function_property_map(const Functor& f) {
   return function_property_map<Functor, Arg>(f);
}

The write a function object (get_weight, say) that takes an edge
descriptor and returns your weight, make sure it has a member typedef
called "result_type" that gives the result of operator()(), and use
"make_function_property_map<edge_descriptor>(get_weight)" as the property
map. Please tell me if there are any problems, as I have not tested this.

-- Jeremiah Willcock


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net