00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 # ifndef DIJKSTRA_H
00063 # define DIJKSTRA_H
00064
00065 # include <ahFunction.H>
00066 # include <tpl_graph.H>
00067 # include <archeap.H>
00068 # include <tpl_find_path.H>
00069
00070 namespace Aleph {
00071
00072
00073 # define DNI(p) ((Node_Info*) NODE_COOKIE((p)))
00074
00075 # define TREENODE(p) (((Tree_Node_Info*)DNI(p))->tree_node)
00076 # define ACC(p) (DNI(p)->dist) // Acceso a la distancia acumulada
00077 # define HEAPNODE(p) (DNI(p)->heap_node)
00078 # define DAI(p) ((Arc_Info*) ARC_COOKIE(p))
00079 # define ARC_DIST(p) (Distance () (p))
00080 # define TREEARC(p) (((Tree_Arc_Info*)DAI(p))->tree_arc)
00081 # define POT(p) (DAI(p)->pot)
00082 # define GRAPHNODE(p) (static_cast<typename GT::Node*>(NODE_COOKIE(p)))
00083
00084 template <class GT,
00085 class Distance,
00086 class Op = Aleph::plus<typename Distance::Distance_Type>
00087 >
00088 struct Dft_Plus
00089 {
00090 Op & op;
00091
00092 Dft_Plus(Op && __op = Op()) : op(__op) { }
00093
00094 Dft_Plus(Op & __op) : op(__op) { }
00095
00096 typename Distance::Distance_Type
00097 operator () (typename GT::Arc * ,
00098 const typename Distance::Distance_Type & op1,
00099 const typename Distance::Distance_Type & op2)
00100 {
00101 return op(op1, op2);
00102 }
00103
00104 typename Distance::Distance_Type
00105 operator () (const typename Distance::Distance_Type & op1,
00106 const typename Distance::Distance_Type & op2)
00107 {
00108 return op(op1, op2);
00109 }
00110 };
00111
00112
00163 template <class GT,
00164 class Distance,
00165 class Plus = Dft_Plus<GT, Distance,
00166 Aleph::plus<typename Distance::Distance_Type> >,
00167 class Compare = Aleph::less<typename Distance::Distance_Type>,
00168 class SA = Default_Show_Arc<GT> >
00169 class Dijkstra_Min_Paths
00170 {
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 struct Arc_Info
00186 {
00187 typename Distance::Distance_Type pot;
00188 };
00189
00190
00191 struct Tree_Arc_Info : public Arc_Info
00192 {
00193 typename GT::Arc * tree_arc;
00194 typename Distance::Distance_Type pot;
00195 };
00196
00197
00198 struct Get_Potential_Arc : public Distance
00199 {
00200 Get_Potential_Arc() { }
00201
00202 Get_Potential_Arc(Distance & d) : Distance(d) { }
00203
00204 typename Distance::Distance_Type operator () (typename GT::Arc *a)
00205 {
00206 Arc_Info * arc_info = (Arc_Info*) ARC_COOKIE(a);
00207 return arc_info->pot;
00208 }
00209 };
00210
00211
00212 struct Node_Info
00213 {
00214 typename Distance::Distance_Type dist;
00215 void * heap_node;
00216
00217 Node_Info() : dist(Distance::Zero_Distance), heap_node(NULL)
00218 {
00219
00220 }
00221 };
00222
00223
00224 struct Tree_Node_Info : public Node_Info
00225 {
00226 typename GT::Node * tree_node;
00227 typename Distance::Distance_Type dist;
00228 void * heap_node;
00229
00230 Tree_Node_Info() : tree_node(NULL)
00231 {
00232
00233 }
00234 };
00235
00236
00237 struct Dijkstra_Heap_Info
00238 {
00239 typedef typename
00240 ArcHeap<GT, Get_Potential_Arc, Compare, Dijkstra_Heap_Info>::Node Node;
00241
00242 Node *& operator () (typename GT::Node * p)
00243 {
00244 return (Node*&) HEAPNODE(p);
00245 }
00246 };
00247
00248
00249 struct Initialize_Node
00250 {
00251 void operator () (GT & g, typename GT::Node * p)
00252 {
00253 g.reset_bit(p, Aleph::Dijkstra);
00254 NODE_COOKIE(p) = new Node_Info;
00255 }
00256 };
00257
00258
00259 struct Destroy_Node
00260 {
00261 void operator () (GT &, typename GT::Node * p)
00262 {
00263 delete DNI(p);
00264 }
00265 };
00266
00267
00268 struct Initialize_Arc
00269 {
00270 void operator () (GT & g, typename GT::Arc * a)
00271 {
00272 g.reset_bit(a, Aleph::Dijkstra);
00273 ARC_COOKIE(a) = new Arc_Info;
00274 POT(a) = Distance::Zero_Distance;
00275 }
00276 };
00277
00278
00279 struct Destroy_Arc
00280 {
00281 void operator () (GT &, typename GT::Arc * ga)
00282 {
00283 delete DAI(ga);
00284 }
00285 };
00286
00287
00288 struct Initialize_Tree_Node
00289 {
00290 void operator () (GT & g, typename GT::Node * p)
00291 {
00292 g.reset_bit(p, Aleph::Dijkstra);
00293 NODE_COOKIE(p) = new Tree_Node_Info;
00294 }
00295 };
00296
00297
00298 struct Destroy_Tree_Node
00299 {
00300 void operator () (GT &, typename GT::Node * p)
00301 {
00302 Tree_Node_Info * aux = (Tree_Node_Info *) DNI(p);
00303 typename GT::Node * tp = TREENODE(p);
00304 if (tp != NULL)
00305 {
00306 NODE_COOKIE(p) = NODE_COOKIE(tp) = NULL;
00307 GT::map_nodes (p, tp);
00308 }
00309 else
00310 NODE_COOKIE(p) = NULL;
00311
00312 delete aux;
00313 }
00314 };
00315
00316
00317 struct Initialize_Tree_Arc
00318 {
00319 void operator () (GT & g, typename GT::Arc * a)
00320 {
00321 g.reset_bit(a, Aleph::Dijkstra);
00322 ARC_COOKIE(a) = new Tree_Arc_Info;
00323 POT(a) = Distance::Zero_Distance;
00324 TREEARC(a) = NULL;
00325 }
00326 };
00327
00328
00329 struct Destroy_Tree_Arc
00330 {
00331 void operator () (GT &, typename GT::Arc * ga)
00332 {
00333 Tree_Arc_Info * aux = (Tree_Arc_Info *) DAI(ga);
00334 typename GT::Arc * ta = TREEARC(ga);
00335 if (ta != NULL)
00336 {
00337 I(IS_ARC_VISITED(ga, Aleph::Dijkstra));
00338 GT::map_arcs (ga, ta);
00339 }
00340
00341 delete aux;
00342 }
00343 };
00344
00345 typedef Dijkstra_Heap_Info Heap_Info;
00346
00347 typedef ArcHeap<GT, Get_Potential_Arc, Compare, Heap_Info> Heap;
00348
00349 SA & sa;
00350 Get_Potential_Arc get_pot;
00351 Plus & plus;
00352 Heap heap;
00353 bool painted;
00354 GT * ptr_g;
00355 typename GT::Node * s;
00356
00357 public:
00358
00359
00360
00368 Dijkstra_Min_Paths(Plus && __plus = Plus(),
00369 Distance && dist = Distance(),
00370 Compare && cmp = Compare(),
00371 SA && __sa = SA())
00372 : sa(__sa), get_pot(dist), plus(__plus), heap(get_pot, cmp, Heap_Info()),
00373 painted(false), ptr_g(NULL), s(NULL)
00374 {
00375
00376 }
00377
00379 Dijkstra_Min_Paths(Plus & __plus, Distance & dist, Compare & cmp, SA & __sa)
00380 : sa(__sa), get_pot(dist), plus(__plus), heap(get_pot, cmp, Heap_Info()),
00381 painted(false), ptr_g(NULL), s(NULL)
00382 {
00383
00384 }
00385
00386 private:
00387
00388 template <class IN, class IA>
00389 void init(GT & g, typename GT::Node * start)
00390 {
00391 heap.empty();
00392
00393 ptr_g = &g;
00394 s = start;
00395
00396 Operate_On_Nodes<GT, IN> () (g);
00397
00398 (Operate_On_Arcs <GT, IA> (sa)) (g);
00399 }
00400
00401 template <class DN, class DA>
00402 void uninit()
00403 {
00404 Operate_On_Nodes <GT, DN> () (*ptr_g);
00405
00406 (Operate_On_Arcs <GT, DA, SA> (sa)) (*ptr_g);
00407 }
00408
00409 public:
00410
00420 void compute_min_paths_tree(GT & g, typename GT::Node * start, GT & tree)
00421 {
00422 init<Initialize_Tree_Node, Initialize_Tree_Arc>(g, start);
00423
00424 clear_graph(tree);
00425
00426 NODE_BITS(start).set_bit(Aleph::Dijkstra, true);
00427 ACC(start) = Distance::Zero_Distance;
00428 TREENODE(start) = tree.insert_node(start->get_info());
00429 NODE_COOKIE(TREENODE(start)) = start;
00430
00431 for (Out_Iterator<GT, SA> it(start, sa); it.has_curr(); it.next())
00432 {
00433 typename GT::Arc * arc = it.get_current_arc();
00434 POT(arc) = ARC_DIST(arc);
00435 heap.put_arc(arc, it.get_tgt_node());
00436 }
00437
00438 const size_t & n = g.get_num_nodes();
00439
00440 while (tree.get_num_nodes() < n)
00441 {
00442 typename GT::Arc * garc = heap.get_min_arc();
00443 if (IS_ARC_VISITED(garc, Aleph::Dijkstra))
00444 continue;
00445
00446 ARC_BITS(garc).set_bit(Aleph::Dijkstra, true);
00447
00448 typename GT::Node * gsrc = g.get_src_node(garc);
00449 typename GT::Node * gtgt = g.get_tgt_node(garc);
00450
00451
00452 if (IS_NODE_VISITED(gsrc, Aleph::Dijkstra) and
00453 IS_NODE_VISITED(gtgt, Aleph::Dijkstra))
00454 continue;
00455
00456 if (IS_NODE_VISITED(gtgt, Aleph::Dijkstra))
00457 Aleph::swap(gsrc, gtgt);
00458
00459 NODE_BITS(gtgt).set_bit(Aleph::Dijkstra, true);
00460
00461 typename GT::Node * ttgt = tree.insert_node(gtgt->get_info());
00462 TREENODE(gtgt) = ttgt;
00463
00464 typename GT::Arc * tarc =
00465 tree.insert_arc(TREENODE(gsrc), TREENODE(gtgt), garc->get_info());
00466 TREEARC(garc) = tarc;
00467
00468 ACC(gtgt) = plus(ACC(gsrc), ARC_DIST(garc));
00469 const typename Distance::Distance_Type & acc = ACC(gtgt);
00470
00471
00472 for (Out_Iterator<GT, SA> it(gtgt, sa); it.has_curr(); it.next())
00473 {
00474 typename GT::Arc * arc = it.get_current_arc();
00475 if (IS_ARC_VISITED(arc, Aleph::Dijkstra))
00476 continue;
00477
00478 typename GT::Node * tgt = it.get_tgt_node();
00479 if (IS_NODE_VISITED(tgt, Aleph::Dijkstra))
00480 continue;
00481
00482 POT(arc) = plus (arc, acc, ARC_DIST(arc));
00483 heap.put_arc(arc, tgt);
00484 }
00485 }
00486
00487 uninit<Destroy_Tree_Node, Destroy_Tree_Arc> ();
00488 }
00489
00504 void compute_partial_min_paths_tree(GT & g,
00505 typename GT::Node * start,
00506 typename GT::Node * end,
00507 GT & tree)
00508 {
00509 init <Initialize_Tree_Node, Initialize_Tree_Arc> (g, start);
00510 clear_graph(tree);
00511
00512 NODE_BITS(start).set_bit(Aleph::Dijkstra, true);
00513 ACC(start) = Distance::Zero_Distance;
00514 TREENODE(start) = tree.insert_node(start->get_info());
00515 NODE_COOKIE(TREENODE(start)) = start;
00516
00517 for (Out_Iterator<GT, SA> it(start, sa); it.has_curr(); it.next())
00518 {
00519 typename GT::Arc * arc = it.get_current_arc();
00520 POT(arc) = ARC_DIST(arc);
00521 heap.put_arc(arc, it.get_tgt_node());
00522 }
00523
00524 const size_t & n = g.get_num_nodes();
00525
00526 while (tree.get_num_nodes() < n)
00527 {
00528 typename GT::Arc * garc = heap.get_min_arc();
00529
00530 if (IS_ARC_VISITED(garc, Aleph::Dijkstra))
00531 continue;
00532
00533 ARC_BITS(garc).set_bit(Aleph::Dijkstra, true);
00534
00535 typename GT::Node * gsrc = g.get_src_node(garc);
00536 typename GT::Node * gtgt = g.get_tgt_node(garc);
00537
00538
00539 if (IS_NODE_VISITED(gsrc, Aleph::Dijkstra) and
00540 IS_NODE_VISITED(gtgt, Aleph::Dijkstra))
00541 continue;
00542
00543 if (IS_NODE_VISITED(gtgt, Aleph::Dijkstra))
00544 Aleph::swap(gsrc, gtgt);
00545
00546 typename GT::Node * ttgt = tree.insert_node(gtgt->get_info());
00547 TREENODE(gtgt) = ttgt;
00548 NODE_BITS(gtgt).set_bit(Aleph::Dijkstra, true);
00549
00550 typename GT::Arc * tarc =
00551 tree.insert_arc(TREENODE(gsrc), TREENODE(gtgt), garc->get_info());
00552 TREEARC(garc) = tarc;
00553
00554 if (gtgt == end)
00555 break;
00556
00557 ACC(gtgt) = plus(ACC(gsrc), ARC_DIST(garc));
00558 const typename Distance::Distance_Type & acc = ACC(gtgt);
00559
00560
00561 for (Out_Iterator<GT, SA> it(gtgt, sa); it.has_curr(); it.next())
00562 {
00563 typename GT::Arc * arc = it.get_current_arc();
00564 if (IS_ARC_VISITED(arc, Aleph::Dijkstra))
00565 continue;
00566
00567 typename GT::Node * tgt = it.get_tgt_node();
00568 if (IS_NODE_VISITED(tgt, Aleph::Dijkstra))
00569 continue;
00570
00571 POT(arc) = plus(arc, acc, ARC_DIST(arc));
00572 heap.put_arc(arc, tgt);
00573 }
00574 }
00575
00576 uninit <Destroy_Tree_Node, Destroy_Tree_Arc> ();
00577 }
00578
00582 struct Painted
00583 {
00584 Dijkstra_Min_Paths * ptr;
00585 typename Distance::Distance_Type dist;
00586
00587 Painted(Dijkstra_Min_Paths * p)
00588 : ptr(p), dist(Distance::Zero_Distance)
00589 {
00590
00591 }
00592
00593 bool operator () (typename GT::Arc * a)
00594 {
00595 if (not IS_ARC_VISITED(a, Aleph::Dijkstra))
00596 return false;
00597
00598 dist = ptr->plus(a, dist, ARC_DIST(a));
00599
00600 return true;
00601 }
00602 };
00603
00613 void paint_partial_min_paths_tree(GT & g,
00614 typename GT::Node * start,
00615 typename GT::Node * end)
00616 {
00617 init<Initialize_Node, Initialize_Arc> (g, start);
00618
00619 NODE_BITS(start).set_bit(Aleph::Dijkstra, true);
00620 ACC(start) = Distance::Zero_Distance;
00621
00622 for (Out_Iterator<GT, SA> it(start, sa); it.has_curr(); it.next())
00623 {
00624 typename GT::Arc * arc = it.get_current_arc();
00625 POT(arc) = ARC_DIST(arc);
00626 heap.put_arc(arc, it.get_tgt_node());
00627 }
00628
00629 const size_t & n = g.get_num_nodes();
00630 size_t tn = 1;
00631
00632 while (tn < n)
00633 {
00634 typename GT::Arc * garc = heap.get_min_arc();
00635 if (IS_ARC_VISITED(garc, Aleph::Dijkstra))
00636 continue;
00637
00638 ARC_BITS(garc).set_bit(Aleph::Dijkstra, true);
00639
00640 typename GT::Node * src = g.get_src_node(garc);
00641 typename GT::Node * tgt = g.get_tgt_node(garc);
00642
00643
00644 if (IS_NODE_VISITED(src, Aleph::Dijkstra) and
00645 IS_NODE_VISITED(tgt, Aleph::Dijkstra))
00646 continue;
00647
00648 if (IS_NODE_VISITED(tgt, Aleph::Dijkstra))
00649 Aleph::swap(src, tgt);
00650
00651 NODE_BITS(tgt).set_bit(Aleph::Dijkstra, true);
00652
00653 ++tn;
00654
00655 if (tgt == end)
00656 break;
00657
00658 ACC(tgt) = plus(ACC(src), ARC_DIST(garc));
00659
00660 const typename Distance::Distance_Type & acc = ACC(tgt);
00661
00662
00663 for (Out_Iterator<GT, SA> it(tgt, sa); it.has_curr(); it.next())
00664 {
00665 typename GT::Arc * a = it.get_current_arc();
00666 if (IS_ARC_VISITED(a, Aleph::Dijkstra))
00667 continue;
00668
00669 typename GT::Node * t = it.get_tgt_node();
00670 if (IS_NODE_VISITED(t, Aleph::Dijkstra))
00671 continue;
00672
00673 POT(a) = plus(a, acc, ARC_DIST(a));
00674 heap.put_arc(a, t);
00675 }
00676 }
00677
00678 uninit<Destroy_Node, Destroy_Arc> ();
00679 painted = true;
00680 }
00681
00689 void paint_min_paths_tree(GT & g, typename GT::Node * start)
00690 {
00691 init<Initialize_Node, Initialize_Arc> (g, start);
00692
00693 NODE_BITS(start).set_bit(Aleph::Dijkstra, true);
00694 ACC(start) = Distance::Zero_Distance;
00695
00696 for (Out_Iterator<GT, SA> it(start, sa); it.has_curr(); it.next())
00697 {
00698 typename GT::Arc * arc = it.get_current_arc();
00699 POT(arc) = ARC_DIST(arc);
00700 heap.put_arc(arc, it.get_tgt_node());
00701 }
00702
00703 const size_t & n = g.get_num_nodes();
00704 size_t tn = 1;
00705
00706 while (tn < n)
00707 {
00708 typename GT::Arc * garc = heap.get_min_arc();
00709 if (IS_ARC_VISITED(garc, Aleph::Dijkstra))
00710 continue;
00711
00712 ARC_BITS(garc).set_bit(Aleph::Dijkstra, true);
00713
00714 typename GT::Node * src = g.get_src_node(garc);
00715 typename GT::Node * tgt = g.get_tgt_node(garc);
00716
00717
00718 if (IS_NODE_VISITED(src, Aleph::Dijkstra) and
00719 IS_NODE_VISITED(tgt, Aleph::Dijkstra))
00720 continue;
00721
00722 if (IS_NODE_VISITED(tgt, Aleph::Dijkstra))
00723 Aleph::swap(src, tgt);
00724
00725 NODE_BITS(tgt).set_bit(Aleph::Dijkstra, true);
00726
00727 ++tn;
00728
00729 ACC(tgt) = plus(ACC(src), ARC_DIST(garc));
00730 const typename Distance::Distance_Type & acc = ACC(tgt);
00731
00732
00733 for (Out_Iterator<GT, SA> it(tgt, sa); it.has_curr(); it.next())
00734 {
00735 typename GT::Arc * a = it.get_current_arc();
00736 if (IS_ARC_VISITED(a, Aleph::Dijkstra))
00737 continue;
00738
00739 typename GT::Node * t = it.get_tgt_node();
00740 if (IS_NODE_VISITED(t, Aleph::Dijkstra))
00741 continue;
00742
00743 POT(a) = plus(a, acc, ARC_DIST(a));
00744 heap.put_arc(a, t);
00745 }
00746 }
00747
00748 uninit<Destroy_Node, Destroy_Arc> ();
00749 painted = true;
00750 }
00751
00765 typename Distance::Distance_Type
00766 find_min_path(GT & g,
00767 typename GT::Node * start, typename GT::Node * end,
00768 Path<GT> & min_path)
00769 {
00770 paint_partial_min_paths_tree(g, start, end);
00771
00772 Painted paint(this);
00773 (Find_Path_Depth_First<GT, Painted> (paint)) (g, start, end, min_path);
00774
00775 return paint.dist;
00776 }
00777
00799 void operator () (GT & g, typename GT::Node * s, GT & tree)
00800 {
00801 compute_min_paths_tree(g, s, tree);
00802 }
00803
00817 typename Distance::Distance_Type
00818 copy_painted_min_paths_tree(GT & g, GT & tree)
00819 {
00820 if (not painted)
00821 throw std::domain_error("Graph has not previusly painted");
00822
00823 Painted paint(this);
00824 (Copy_Graph<GT, Default_Show_Node<GT>, Painted> (paint)) (tree, g);
00825
00826 return paint.dist;
00827 }
00828
00830 typename Distance::Distance_Type operator () (GT & g,
00831 typename GT::Node * s,
00832 typename GT::Node * e,
00833 Path<GT> & path)
00834 {
00835 return find_min_path (g, s, e, path);
00836 }
00837
00860 typename Distance::Distance_Type
00861 get_min_path(typename GT::Node * end, Path<GT> & path)
00862 {
00863 if (ptr_g == NULL)
00864 throw std::domain_error("Min path has not been computed");
00865
00866 if (not painted)
00867 throw std::domain_error("Graph has not previusly painted");
00868
00869 Painted paint(this);
00870 (Find_Path_Depth_First<GT, Painted> (paint)) (*ptr_g, s, end, path);
00871
00872 return paint.dist;
00873 }
00874
00876 struct Total
00877 {
00878 Dijkstra_Min_Paths * ptr;
00879 typename Distance::Distance_Type dist;
00880
00881 Total(Dijkstra_Min_Paths * p)
00882 : ptr(p), dist(Distance::Zero_Distance)
00883 {
00884
00885 }
00886
00887 bool operator () (typename GT::Arc * a)
00888 {
00889 dist = ptr->plus(a, dist, ARC_DIST(a));
00890
00891 return true;
00892 }
00893 };
00894
00916 typename Distance::Distance_Type
00917 get_min_path(GT & tree, typename GT::Node * end, Path<GT> & path)
00918 {
00919 if (ptr_g == NULL)
00920 throw std::domain_error("Min path has not been computed");
00921
00922 typename GT::Node * ts = mapped_node<GT>(s);
00923 typename GT::Node * te = mapped_node<GT>(end);
00924
00925 Path<GT> tree_path(tree);
00926 Total total(this);
00927 (Find_Path_Depth_First<GT, Total> (total)) (tree, ts, te, tree_path);
00928
00929 path.clear_path();
00930 path.init(s);
00931 typename Path<GT>::Iterator it(tree_path);
00932 for (it.next(); it.has_curr(); it.next())
00933 path.append( mapped_node<GT>(it.get_current_node()));
00934
00935 return total.dist;
00936 }
00937 };
00938
00939
00940
00941 # undef DNI
00942 # undef TREENODE
00943 # undef ACC
00944 # undef HEAPNODE
00945 # undef DAI
00946 # undef ARC_DIST
00947 # undef TREEARC
00948 # undef POT
00949 # undef GRAPHNODE
00950 }
00951 # endif // DIJKSTRA_H