简体   繁体   中英

Negative edge weight check in boost's dijkstra_shortest_paths

I am using the boost graph library to make a call to dijkstra_shortest_paths . However, I have something special setup in that the weight_map is actually a functor. Hence, everytime the boost library requires the weight of an edge, my functor is called, makes a complicated computation and delivers the result back to boost.

Unfortunately, in dijkstra_shortest_paths.hpp the struct dijkstra_bfs_visitor 's method examine_edge has a get call to the weightmap, only to check if the returned value is negative. I am fully aware that I cannot use Dijkstra's algorithm with negative values and I am certain that my functor only returns positive values. However, this check causes my functor to be called twice for each edge. As it performs a complicated computation I'd like to avoid performing it twice (the results don't change between calls.. each edge gets the same wait during a dijkstra_shortest_paths run).

So far, I am manually checking the edge passed to the functor and in case of the duplicate call I am returning the previous remembered result. This clearly is more of a workaround than a solution.

I tried to pass my own visitor that overwrites examine_edge , however, the original method defined by boost's dijkstra_bfs_visitor is still applied.

Does anyone know if there is a better way to handle this situation and somehow avoid the negate edge weight check?

You are right, even supplying you own visitor the test of negativity will be performed.

  void examine_edge(Edge e, Graph& g) {
    if (m_compare(get(m_weight, e), m_zero))
        boost::throw_exception(negative_edge());
    m_vis.examine_edge(e, g);
  } 

But anyway the weight_map is supposed to be called multiple time (see boost doc ):

 for each vertex v in Adj[u]
  if (w(u,v) + d[u] < d[v])
    d[v] := w(u,v) + d[u]

Just call djikstra with a precomputed weight map, every edge weight will have to be computed anyway.

I suggest you use lazy computation to ensure that each expensive computation is carried out at most once. The most straightforward way to implement this would be give your Edge class a getWeight() lazy getter, I'm not familiar with the library you're using so I'm not sure how you'd integrate that with the functor.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM