0

I'm trying to create a graph where lanes represent vertices and edges connections between. The idea is to later on use a_star algorithm to traverse the graph and find the best route.

My question is how can I get vertex (descriptor?) by using just (town_id, road_id, lane_id)? I tryied battling with the examples that are shipped with boost and basically lost. In them they always traverse thru all the vertices and then get the vertex_descriptor, but I want to do that in constant time. What is need is something like boost::get_vertex(std::tuple(1, 2, 3), graph).

My situation is marked as PROBLEM bellow in the code. The code bellow compiles because there is 12 that I guess corresponds to the index in boost::vecS, but I want to use a tuple (or something else that can hold the triplet) that could get me the vertex descriptor as my starting location.

using TRL = std::tuple<int, int, int>;

struct TRL_VProp {

    /// For some reason this object has to be default constructable
    /// use invalid data to flag it as invalid
    TRL_VProp()
        : trl(-1, -1, 0) {}

    TRL_VProp(TRL trl)
        : trl(trl) {}

    TRL_VProp(int town_id, int road_id, int lane_id)
        : trl(town_id, road_id, lane_id) {}

    TRL trl;
};

using DirectedGraph = boost::adjacency_list<boost::listS,
                                            boost::vecS,
                                            boost::directedS,
                                            RSL_VProp>;

using Vertex = boost::graph_traits<DirectedGraph>::vertex_descriptor;
using VertexI = boost::graph_traits<DirectedGraph>::vertex_iterator;

using EdgeI = boost::graph_traits<DirectedGraph>::edge_iterator;
using Edge = boost::graph_traits<DirectedGraph>::edge_descriptor;

using AdjI = boost::graph_traits<DirectedGraph>::adjacency_iterator;

using Route = std:vector<TRL>;
Route BuildRoute(Map & map) {
    Route result;
    DirectedGraph graph;

    const boost::property_map<DirectedGraph, RSL RSL_VProp:: *>::type trl =
            boost::get(&TRL_VProp::rsl, graph);

    bool is_inserted;
    Edge e_desc;

    for (auto & town: map.GetTowns()) {
        for (auto & road: town.GetRoads()) {
            for (auto & lane: road.GetLanes()) {

                auto vtx_1 = boost::add_vertex(
                    RSL_VProp(town.GetId(), road.GetId(), lane.GetId()),
                    graph);

                const auto next_lanes = map.GetNextLanes(town.GetId(), road.GetId(), lane.GetId());

                for(const auto & next_lane : next_lanes) {
                     auto vtx_2 = boost::add_vertex(
                        TRL_VProp(lane.GetTown().GetId(), lane.GetRoad().GetId(), lane.GetId()),
                        graph);

                     std::tie(e_desc, is_inserted) = boost::add_edge(vtx_1, vtx_2, graph);
                     assert(is_inserted);
                }
            }
        }
    }

    // debug part
    TRL temp_trl;
    std::pair<AdjI, AdjI> adj_i = boost::adjacent_vertices(12, graph);  // <--- PROBLEM
    for( auto i = adj_i.first; i != adj_i.second; i++) {
        temp_trl = trl[*i];  // trl prop map
        std:: cout << "\Town id: " << std::get<0>(temp_trl)
                   << "\nRoad id: " << std::get<1>(temp_trl)
                   << "\nLane id: " << std::get<2>(temp_trl);
         result.push_back(
             std::make_tuple(
                std::get<0>(temp_trl), 
                std::get<1>(temp_trl),
                std::get<2>(temp_trl)));
    }
    return result;
}

For completeness, I don't plan to change data inside the property or the graph itself. Once thing is created it will probably stay that way. Maybe lateron I'll probably have to add the weight or whatever is necessary to get the traversing algorithm to work. Edit: I forgot to mention that there is a bug in the code because I'm adding vertices before checking was vertex with identical (town, road, lane) already been created. I wonder is there a builtin boost::graph way to not insert duplicated so I won't have to use a std::unordered_map or something.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Daniel
  • 980
  • 9
  • 20
  • 1
    Why would you expect to be able to traverse a graph and find an arbitrary node in *constant time*? Think about it; if your "searched for node" is the root node, finding it will obviously be faster than finding any other node. You just cannot find *any* node in constant time. You have to traverse the graph and the time *will* vary depending on how many nodes you need to search. – Jesper Juhl Nov 18 '19 at 19:12
  • So basically what I should do is create manually a `unordered_map, graph_traits::vertex_descriptor>` and get vertex descriptors from there? But all this still sounds crazy to me. So if someone wants to find shortest distance between two vertices `(v1, v2)` he would have to traverse all the vertices to find the ones he is looking for and then pass them to the algorithm? – Daniel Nov 18 '19 at 22:17

0 Answers0