40 template <
class Graph,
41 class StartPredecessorMap,
42 class StartDistanceMap,
class StartDistanceLookaheadMap,
43 class GoalSuccessorMap,
44 class GoalDistanceMap,
class GoalDistanceLookaheadMap,
46 class VertexIndexMap,
class EdgeIndexMap,
47 typename CompareFunction,
typename CombineFunction,
48 typename CostInf,
typename CostZero,
49 class IncBiVisitor,
class IncBiBalancer>
54 typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
55 typedef typename boost::graph_traits<Graph>::vertex_iterator VertexIter;
56 typedef typename boost::graph_traits<Graph>::edge_descriptor Edge;
57 typedef typename boost::graph_traits<Graph>::out_edge_iterator OutEdgeIter;
58 typedef typename boost::graph_traits<Graph>::in_edge_iterator InEdgeIter;
59 typedef typename boost::property_traits<WeightMap>::value_type weight_type;
63 weight_type path_length;
64 weight_type start_dist;
65 weight_type goal_dist;
67 path_length(weight_type()), start_dist(weight_type()), goal_dist(weight_type())
70 conn_key(weight_type path_length, weight_type start_dist, weight_type goal_dist):
71 path_length(path_length), start_dist(start_dist), goal_dist(goal_dist)
74 bool operator<(
const conn_key & rhs)
const
76 return path_length < rhs.path_length;
78 bool operator>(
const conn_key & rhs)
const
80 return path_length > rhs.path_length;
82 bool operator<=(
const conn_key & rhs)
const
84 return path_length <= rhs.path_length;
91 StartPredecessorMap start_predecessor;
92 StartDistanceMap start_distance;
93 StartDistanceLookaheadMap start_distance_lookahead;
94 GoalSuccessorMap goal_successor;
95 GoalDistanceMap goal_distance;
96 GoalDistanceLookaheadMap goal_distance_lookahead;
98 VertexIndexMap vertex_index_map;
99 EdgeIndexMap edge_index_map;
100 CompareFunction compare;
101 CombineFunction combine;
104 weight_type goal_margin;
106 IncBiBalancer balancer;
119 Vertex v_start, Vertex v_goal,
120 StartPredecessorMap start_predecessor,
121 StartDistanceMap start_distance, StartDistanceLookaheadMap start_distance_lookahead,
122 GoalSuccessorMap goal_successor,
123 GoalDistanceMap goal_distance, GoalDistanceLookaheadMap goal_distance_lookahead,
125 VertexIndexMap vertex_index_map,
126 EdgeIndexMap edge_index_map,
127 CompareFunction compare, CombineFunction combine,
128 CostInf inf, CostZero zero,
129 weight_type goal_margin,
131 IncBiBalancer balancer):
132 g(g), v_start(v_start), v_goal(v_goal),
133 start_predecessor(start_predecessor),
134 start_distance(start_distance),
135 start_distance_lookahead(start_distance_lookahead),
136 goal_successor(goal_successor),
137 goal_distance(goal_distance),
138 goal_distance_lookahead(goal_distance_lookahead),
140 vertex_index_map(vertex_index_map),
141 edge_index_map(edge_index_map),
142 compare(compare), combine(combine),
143 inf(inf), zero(zero),
144 goal_margin(goal_margin),
145 vis(vis), balancer(balancer)
152 VertexIter vi, vi_end;
153 for (boost::tie(vi,vi_end)=vertices(g); vi!=vi_end; ++vi)
155 put(start_distance_lookahead, *vi, inf);
156 put(start_distance, *vi, inf);
157 put(goal_distance_lookahead, *vi, inf);
158 put(goal_distance, *vi, inf);
160 put(start_distance_lookahead, v_start, zero);
161 put(goal_distance_lookahead, v_goal, zero);
163 start_queue.insert(
get(vertex_index_map,v_start), zero);
164 vis.start_queue_insert(v_start);
166 goal_queue.insert(
get(vertex_index_map,v_goal), zero);
167 vis.goal_queue_insert(v_goal);
171 inline weight_type start_calculate_key(Vertex u)
173 return std::min(
get(start_distance,u),
get(start_distance_lookahead,u));
176 inline weight_type goal_calculate_key(Vertex u)
178 return std::min(
get(goal_distance,u),
get(goal_distance_lookahead,u));
183 void update_edge(Edge e)
186 size_t eidx =
get(edge_index_map, e);
187 weight_type elen =
get(weight, e);
188 Vertex va = source(e,g);
189 Vertex vb = target(e,g);
191 bool is_valid =
false;
194 if (elen == inf)
break;
195 if (start_queue.contains(
get(vertex_index_map,va)))
break;
196 if (goal_queue.contains(
get(vertex_index_map,vb)))
break;
197 if (
get(start_distance,va) == inf)
break;
198 if (
get(goal_distance,vb) == inf)
break;
205 if (conn_queue.contains(eidx))
207 conn_queue.remove(eidx);
208 vis.conn_queue_remove(e);
214 weight_type pathlen = combine(combine(
get(start_distance,va), elen),
get(goal_distance,vb));
215 conn_key new_key(pathlen,
get(start_distance,va),
get(goal_distance,vb));
216 if (conn_queue.contains(eidx))
218 conn_queue.update(eidx, new_key);
219 vis.conn_queue_update(e);
223 conn_queue.insert(eidx, new_key);
224 vis.conn_queue_insert(e);
235 inline bool start_update_predecessor(Vertex u, Vertex v,
double uv_weight)
242 Vertex v_pred =
get(start_predecessor, v);
243 weight_type v_look_old =
get(start_distance_lookahead, v);
244 weight_type v_look_u = combine(
get(start_distance,u), uv_weight);
249 if (v_look_u == v_look_old)
253 else if (v_look_u < v_look_old)
255 put(start_distance_lookahead, v, v_look_u);
261 weight_type v_look_best = inf;
263 InEdgeIter ei, ei_end;
264 for (boost::tie(ei,ei_end)=in_edges(v,g); ei!=ei_end; ei++)
266 weight_type v_look_uu = combine(
get(start_distance,source(*ei,g)),
get(weight,*ei));
267 if (v_look_uu < v_look_best)
269 v_look_best = v_look_uu;
270 v_pred_best = source(*ei,g);
273 if (v_look_best != inf)
274 put(start_predecessor, v, v_pred_best);
275 if (v_look_best == v_look_old)
281 put(start_distance_lookahead, v, v_look_best);
288 if (v_look_u < v_look_old)
290 put(start_predecessor, v, u);
291 put(start_distance_lookahead, v, v_look_u);
304 inline void start_update_vertex(Vertex u)
306 weight_type u_dist =
get(start_distance,u);
307 bool is_consistent = (u_dist ==
get(start_distance_lookahead,u));
308 size_t u_idx =
get(vertex_index_map,u);
311 if (start_queue.contains(u_idx))
313 start_queue.remove(u_idx);
314 vis.start_queue_remove(u);
318 OutEdgeIter ei, ei_end;
319 for (boost::tie(ei,ei_end)=out_edges(u,g); ei!=ei_end; ei++)
321 Vertex v = target(*ei,g);
322 size_t v_idx =
get(vertex_index_map, v);
324 weight_type v_goaldist =
get(goal_distance,v);
325 if (!goal_queue.contains(v_idx) && v_goaldist != inf &&
get(weight,*ei) != inf)
327 conn_key new_key(combine(combine(u_dist,
get(weight,*ei)), v_goaldist),
329 conn_queue.insert(
get(edge_index_map,*ei), new_key);
330 vis.conn_queue_insert(*ei);
338 if (start_queue.contains(u_idx))
340 start_queue.update(u_idx, start_calculate_key(u));
341 vis.start_queue_update(u);
345 start_queue.insert(u_idx, start_calculate_key(u));
346 vis.start_queue_insert(u);
348 OutEdgeIter ei, ei_end;
349 for (boost::tie(ei,ei_end)=out_edges(u,g); ei!=ei_end; ei++)
351 size_t edge_index =
get(edge_index_map,*ei);
352 if (conn_queue.contains(edge_index))
354 conn_queue.remove(edge_index);
355 vis.conn_queue_remove(*ei);
368 inline bool goal_update_successor(Vertex u, Vertex v,
double uv_weight)
375 Vertex u_succ =
get(goal_successor, u);
376 weight_type u_look_old =
get(goal_distance_lookahead, u);
377 weight_type u_look_v = combine(uv_weight,
get(goal_distance,v));
382 if (u_look_v == u_look_old)
386 else if (u_look_v < u_look_old)
388 put(goal_distance_lookahead, u, u_look_v);
394 weight_type u_look_best = inf;
396 OutEdgeIter ei, ei_end;
397 for (boost::tie(ei,ei_end)=out_edges(u,g); ei!=ei_end; ei++)
399 weight_type u_look_vv = combine(
get(weight,*ei),
get(goal_distance,target(*ei,g)));
400 if (u_look_vv < u_look_best)
402 u_look_best = u_look_vv;
403 u_succ_best = target(*ei,g);
406 if (u_look_best != inf)
407 put(goal_successor, u, u_succ_best);
408 if (u_look_best == u_look_old)
414 put(goal_distance_lookahead, u, u_look_best);
421 if (u_look_v < u_look_old)
423 put(goal_successor, u, v);
424 put(goal_distance_lookahead, u, u_look_v);
437 inline void goal_update_vertex(Vertex v)
439 weight_type v_dist =
get(goal_distance,v);
440 bool is_consistent = (v_dist ==
get(goal_distance_lookahead,v));
441 size_t v_idx =
get(vertex_index_map,v);
444 if (goal_queue.contains(v_idx))
446 goal_queue.remove(v_idx);
447 vis.goal_queue_remove(v);
451 InEdgeIter ei, ei_end;
452 for (boost::tie(ei,ei_end)=in_edges(v,g); ei!=ei_end; ei++)
454 Vertex u = source(*ei,g);
455 size_t u_idx =
get(vertex_index_map, u);
457 weight_type u_startdist =
get(start_distance,u);
458 if (!start_queue.contains(u_idx) && u_startdist != inf &&
get(weight,*ei) != inf)
460 conn_key new_key(combine(combine(u_startdist,
get(weight,*ei)), v_dist),
461 u_startdist, v_dist);
462 conn_queue.insert(
get(edge_index_map,*ei), new_key);
463 vis.conn_queue_insert(*ei);
471 if (goal_queue.contains(v_idx))
473 goal_queue.update(v_idx, goal_calculate_key(v));
474 vis.goal_queue_update(v);
478 goal_queue.insert(v_idx, goal_calculate_key(v));
479 vis.goal_queue_insert(v);
481 InEdgeIter ei, ei_end;
482 for (boost::tie(ei,ei_end)=in_edges(v,g); ei!=ei_end; ei++)
484 size_t edge_index =
get(edge_index_map,*ei);
485 if (conn_queue.contains(edge_index))
487 conn_queue.remove(edge_index);
488 vis.conn_queue_remove(*ei);
496 std::pair<size_t,bool> compute_shortest_path()
500 weight_type start_top = start_queue.size() ? start_queue.top_key() : inf;
501 weight_type goal_top = goal_queue.size() ? goal_queue.top_key() : inf;
503 vis.begin_iteration();
506 if (!start_queue.size() && !goal_queue.size())
507 return std::make_pair(0,
false);
508 if (!start_queue.size() &&
get(start_distance,v_goal) == inf)
509 return std::make_pair(0,
false);
510 if (!goal_queue.size() &&
get(goal_distance,v_start) == inf)
511 return std::make_pair(0,
false);
516 if (!conn_queue.size())
break;
517 if (combine(conn_queue.top_key().path_length,goal_margin) > combine(start_top,goal_top))
break;
518 if (combine(conn_queue.top_key().start_dist,goal_margin) > start_top)
break;
519 if (combine(conn_queue.top_key().goal_dist,goal_margin) > goal_top)
break;
520 return std::make_pair(conn_queue.top_idx(),
true);
525 start_queue.contains(v_start) ?
false :
526 goal_queue.contains(v_goal) ?
true :
527 balancer(start_top,goal_top,start_queue.size(),goal_queue.size());
529 if (do_goal ==
false)
531 if (!start_queue.size())
532 return std::make_pair(0,
false);
534 Vertex u = vertex(start_queue.top_idx(), g);
536 vis.examine_vertex_start(u);
538 start_queue.remove_min();
539 vis.start_queue_remove(u);
540 if (
get(start_distance,u) >
get(start_distance_lookahead,u))
542 weight_type u_sdist =
get(start_distance_lookahead,u);
543 put(start_distance, u, u_sdist);
551 OutEdgeIter ei, ei_end;
552 for (boost::tie(ei,ei_end)=out_edges(u,g); ei!=ei_end; ei++)
554 Vertex v = target(*ei,g);
555 size_t v_idx =
get(vertex_index_map, v);
557 double uv_weight =
get(weight,*ei);
558 bool lookahead_changed = start_update_predecessor(u, v, uv_weight);
559 if (lookahead_changed)
560 start_update_vertex(v);
562 weight_type v_tdist =
get(goal_distance,v);
563 if (u_sdist != inf && !goal_queue.contains(v_idx) && v_tdist != inf && uv_weight != inf)
565 conn_key new_key(combine(combine(u_sdist, uv_weight), v_tdist), u_sdist, v_tdist);
566 conn_queue.insert(
get(edge_index_map,*ei), new_key);
567 vis.conn_queue_insert(*ei);
573 put(start_distance, u, inf);
574 start_update_vertex(u);
575 OutEdgeIter ei, ei_end;
576 for (boost::tie(ei,ei_end)=out_edges(u,g); ei!=ei_end; ei++)
578 Vertex v = target(*ei,g);
580 double uv_weight =
get(weight,*ei);
581 bool lookahead_changed = start_update_predecessor(u, v, uv_weight);
582 if (lookahead_changed)
583 start_update_vertex(v);
589 if (!goal_queue.size())
590 return std::make_pair(0,
false);
592 Vertex v = vertex(goal_queue.top_idx(), g);
594 vis.examine_vertex_goal(v);
596 goal_queue.remove_min();
597 vis.goal_queue_remove(v);
598 if (
get(goal_distance,v) >
get(goal_distance_lookahead,v))
600 weight_type v_tdist =
get(goal_distance_lookahead,v);
601 put(goal_distance, v, v_tdist);
608 InEdgeIter ei, ei_end;
609 for (boost::tie(ei,ei_end)=in_edges(v,g); ei!=ei_end; ei++)
611 Vertex u = source(*ei,g);
612 size_t u_idx =
get(vertex_index_map, u);
614 double uv_weight =
get(weight,*ei);
615 bool lookahead_changed = goal_update_successor(u, v, uv_weight);
616 if (lookahead_changed)
617 goal_update_vertex(u);
619 weight_type u_sdist =
get(start_distance,u);
620 if (v_tdist != inf && !start_queue.contains(u_idx) && u_sdist != inf && uv_weight != inf)
622 conn_key new_key(combine(combine(u_sdist, uv_weight), v_tdist), u_sdist, v_tdist);
623 conn_queue.insert(
get(edge_index_map,*ei), new_key);
624 vis.conn_queue_insert(*ei);
630 put(goal_distance, v, inf);
631 goal_update_vertex(v);
632 InEdgeIter ei, ei_end;
633 for (boost::tie(ei,ei_end)=in_edges(v,g); ei!=ei_end; ei++)
635 Vertex u = source(*ei,g);
637 double uv_weight_new =
get(weight,*ei);
638 bool lookahead_changed = goal_update_successor(u, v, uv_weight_new);
639 if (lookahead_changed)
640 goal_update_vertex(u);
649 template <
class Graph>
653 typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
654 typedef typename boost::graph_traits<Graph>::edge_descriptor Edge;
655 inline void begin_iteration() {}
656 inline void examine_vertex_start(Vertex v) {}
657 inline void examine_vertex_goal(Vertex v) {}
658 inline void start_queue_insert(Vertex v) {}
659 inline void start_queue_update(Vertex v) {}
660 inline void start_queue_remove(Vertex v) {}
661 inline void goal_queue_insert(Vertex v) {}
662 inline void goal_queue_update(Vertex v) {}
663 inline void goal_queue_remove(Vertex v) {}
664 inline void conn_queue_insert(Edge e) {}
665 inline void conn_queue_update(Edge e) {}
666 inline void conn_queue_remove(Edge e) {}
672 template <
typename Vertex,
typename weight_type>
675 const double goalfrac;
678 weight_type start_top, weight_type goal_top,
679 size_t start_queuesize,
size_t goal_queuesize)
const
681 return ((1.0-goalfrac)*goal_top < (goalfrac)*start_top);
689 template <
typename Vertex,
typename weight_type>
692 const double goalfrac;
695 weight_type start_top, weight_type goal_top,
696 size_t start_queuesize,
size_t goal_queuesize)
const
698 return ((1.0-goalfrac)*goal_queuesize < (goalfrac)*start_queuesize);
This class implements incremental bidirectional Dijkstra's search for the single-pair shortest path p...
Definition: incbi.h:50
Balance expansions to the side with the smallest OPEN set cardinality.
Definition: incbi.h:690
Balance expansions to the side with the shortest distance.
Definition: incbi.h:673