0

I have a question on using arrays in the bundled properties in the boost graph library. The below I tried and ended up in comilation error.

Below is my graph declaration.

struct PT_EdgeProperties{
    PT_EdgeId edge_id;
    double weights[10];
};
typedef boost::property<boost::vertex_name_t, std::string> PT_VertexProperties;
typedef boost::adjacency_list<boost::vecS,
                              boost::vecS,
                              boost::directedS,

                              PT_VertexProperties,
                              PT_EdgeProperties> PublicTransitGraph;
vector<sim_mob::StreetDirectory::PT_EdgeId>    

Below is the code I use to find the shortest path using astar_search boost algorithm.

sim_mob::A_StarPublicTransitShortestPathImpl::searchShortestPath(StreetDirectory::PT_VertexId fromNode,StreetDirectory::PT_VertexId toNode,int cost)
{
    vector<StreetDirectory::PT_EdgeId> res;
    StreetDirectory::PT_Vertex from=vertexMap.find(fromNode)->second;;
    StreetDirectory::PT_Vertex to=vertexMap.find(toNode)->second;;      
    StreetDirectory::PublicTransitGraph& graph = publictransitMap_;
    list<StreetDirectory::PT_Vertex> partialRes;
    vector<StreetDirectory::PT_Vertex> p(boost::num_vertices(graph));  //Output variable
    vector<double> d(boost::num_vertices(graph));  //Output variable
    try {
        boost::astar_search(
            graph,
            from,
            distance_heuristic_graph_PT(&graph, to),
            boost::weight_map(get(&StreetDirectory::PT_EdgeProperties::weights[cost],graph)).predecessor_map(&p[0]).distance_map(&d[0])
            .visitor(astar_pt_goal_visitor(to)));

    }
    catch (pt_found_goal& goal) {
        for (StreetDirectory::PT_Vertex v=to;;v=p[v]) {
            partialRes.push_front(v);
            if(p[v] == v) {
                break;
            }
        }
        std::list<StreetDirectory::PT_Vertex>::const_iterator prev = partialRes.end();
        for (std::list<StreetDirectory::PT_Vertex>::const_iterator it=partialRes.begin(); it!=partialRes.end(); it++) {

            if (prev!=partialRes.end()) {
                std::pair<StreetDirectory::PT_Edge, bool> edge = boost::edge(*prev, *it, graph);
                if (!edge.second) {
                    Warn() <<"ERROR: Boost can't find an edge that it should know about." <<std::endl;
                    return vector<StreetDirectory::PT_EdgeId>();
                }

                StreetDirectory::PT_EdgeId edge_id = get(&StreetDirectory::PT_EdgeProperties::edge_id, graph,edge.first);
                res.push_back(edge_id);
            }
            prev = it;
        }
    }
    return res;
 }

Compilation error :

In file included from /home/smart-nus/code/simmobility/dev/Basic/shared/geospatial/streetdir/A_StarPublicTransitShortestPathImpl.hpp:22:0,
             from /home/smart-nus/code/simmobility/dev/Basic/shared/geospatial/streetdir/A_StarPublicTransitShortestPathImpl.cpp:5:
/home/smart-nus/code/simmobility/dev/Basic/shared/geospatial/streetdir/StreetDirectory.hpp: In member function ‘virtual std::vector<int> sim_mob::A_StarPublicTransitShortestPathImpl::searchShortestPath(sim_mob::StreetDirectory::PT_VertexId, sim_mob::StreetDirectory::PT_VertexId, int)’:
/home/smart-nus/code/simmobility/dev/Basic/shared/geospatial/streetdir/StreetDirectory.hpp:208:20: error: invalid use of non-static data member ‘sim_mob::StreetDirectory::PT_EdgeProperties::weights’
   double weights[10];
                ^
/home/smart-nus/code/simmobility/dev/Basic/shared/geospatial/streetdir/A_StarPublicTransitShortestPathImpl.cpp:223:64: error: from this location
 boost::weight_map(get(&StreetDirectory::PT_EdgeProperties::weights[cost],graph)).predecessor_map(&p[0]).distance_map(&d[0])
                                                            ^
make[2]: *** [CMakeFiles/SimMob_Shared.dir/shared/geospatial/streetdir/A_StarPublicTransitShortestPathImpl.cpp.o] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [CMakeFiles/SimMob_Shared.dir/all] Error 2
make: *** [all] Error 2

Questions: Could you please help me to find the way to use arrays in the bundled properties of the BGL. And how to specify to boost algorithms in weight_map boost named params to use particular index of the array as cost function ?

Thanks in advance .

Cheers, Prabhu

1 Answers1

1

The compilation error means the following: you try to tell compiler to use the edge property weight[cost] as weight map. The integer "cost" here is not known at compile time, it comes as function parameter.

It is somewhat non-standard but doable. You should define your own property map

#include <boost/graph/properties.hpp>
#include <boost/graph/properties.hpp>
#include <boost/property_map/property_map.hpp>

struct variable_weight_map //maps "PublicTransit" edge to its weight
{
    typedef boost::readable_property_map_tag category;
    typedef double  value_type;
    typedef const value_type & reference;
    typedef PublicTransitGraph::edge_descriptor key_type;

    variable_weight_map(const PublicTransitGraph* graph, size_t cost_idx_)
       : cost_idx(cost_idx_), g(graph)
    {
    }

    size_t cost_idx;
    const PublicTransitGraph* g;
};


//ReadablePropertyMapConcept
variable_weight_map::value_type
    get( variable_weight_map pmap,
            variable_weight_map::key_type edge)
{
    //access edge_property, then extract specific element of the array
    return (*pmap.g)[edge].weights[pmap.cost_idx];
}

Now, when you need to pass such property map, you call its constructor where you specify the cost index:

boost::astar_search(
            graph,
            from,
            distance_heuristic_graph_PT(&graph, to),
            boost::weight_map( variable_weight_map(&graph, cost) )
            ...

By the way, I would also recommend to replace C-array in edge properties with Boost array: boost::array weights; Unlike C-array, Boost.Array has correct copy semantics.

Michael Simbirsky
  • 3,045
  • 1
  • 12
  • 24