Recursivamente regresando al inicio Aleph-w: Algoritmos y estructuras de datos

Dijkstra.H

00001 
00002 /*
00003   This file is part of Aleph-w system
00004 
00005   Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
00006   Leandro Rabindranath León
00007   All rights reserved.
00008 
00009   Redistribution and use in source and binary forms, with or without
00010   modification, are permitted provided that the following conditions are
00011   met: 
00012   1. Redistributions of source code must retain the above copyright 
00013      notice, this list of conditions and the following disclaimer.
00014   2. Redistributions in binary form must reproduce the above copyright 
00015      notice, this list of conditions and the following disclaimer in the 
00016      documentation and/or other materials provided with the distribution.
00017   3. All advertising materials mentioning features or use of this software
00018      must display the following acknowledgement:
00019 
00020      Copyright (c) 2002-2011 Leandro Rabindranath León. See details of 
00021      licence.     
00022 
00023      This product includes software developed by the Hewlett-Packard
00024      Company, Free Software Foundation and Silicon Graphics Computer
00025      Systems, Inc. 
00026   4. Neither the name of the <organization> nor the
00027      names of its contributors may be used to endorse or promote products
00028      derived from this software without specific prior written permission.
00029 
00030 THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
00031 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00032 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00033 DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
00034 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00035 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00036 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00037 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00038 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00039 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00040 
00041   Aleph-w is distributed in the hope that it will be useful, but WITHOUT
00042   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00043   or FITNESS FOR A PARTICULAR PURPOSE.
00044 
00045   I request users of this software to return to 
00046 
00047   Leandro Rabindranath Leon
00048   CEMISID 
00049   Ed La Hechicera 
00050   3er piso, ala sur
00051   Facultad de Ingenieria 
00052   Universidad de Los Andes 
00053   Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA    or
00054 
00055   lrleon@ula.ve
00056   leandro.r.leon@gmail.com
00057 
00058   any improvements or extensions that they make and grant me the rights
00059   to redistribute these changes.  
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     // conversión de cookie a Node_Info 
00073 # define DNI(p) ((Node_Info*) NODE_COOKIE((p)))
00074     // Acceso al nodo del árbol en el grafo
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) { /* empty */ }
00093 
00094   Dft_Plus(Op & __op) : op(__op) { /* empty */ }
00095 
00096       typename Distance::Distance_Type 
00097   operator () (typename GT::Arc * /* 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   // Aunque fundamentalmente el algoritmo es el mismo, hay dos enfoques
00172   // para calcular el camino mínimo. El primero es pintar el árbol
00173   // abarcador de todos los caminos mínimos a partir de un nodo
00174   // start. Por pintar se entiende que la solución se encuentra dentro
00175   // del mismo grafo y que se distingue mediante marcas.
00176   //
00177   // El otro enfoque consiste en construir un árbol abarcador separado.
00178   //
00179   // Según un enfoque u otro, el grafo se inicializa con información
00180   // distinta. Así, las clases que comiencen con el prefijo "Tree" son
00181   // clases que atañen a la solucipon que construye un árbol abarcador
00182   // separado. 
00183 
00184   // Información a colocar en el arco para la versión que pinta
00185   struct Arc_Info
00186   {
00187     typename Distance::Distance_Type pot; // potencial del arco
00188   };
00189 
00190   // Información a colocar en el arco para la versión que construye árbol
00191   struct Tree_Arc_Info : public Arc_Info
00192   {
00193     typename GT::Arc * tree_arc; // imagen en árbol 
00194     typename Distance::Distance_Type pot; // potencial del arco
00195   };
00196 
00197   // Wrapper de acceso a la distancia (mediante la clase parámetro Distance)
00198   struct Get_Potential_Arc : public Distance
00199   {
00200     Get_Potential_Arc() { /* empty */ }
00201 
00202     Get_Potential_Arc(Distance & d) : Distance(d) { /* empty */ }
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   // Información a colocar en el nodo para la versión que pinta
00212   struct Node_Info
00213   {
00214     typename Distance::Distance_Type dist;      // distancia acumulada
00215     void *                           heap_node;
00216 
00217     Node_Info() : dist(Distance::Zero_Distance), heap_node(NULL) 
00218     { 
00219       // empty
00220     }
00221   };
00222 
00223   // Información a colocar en el nodo para la versión que construye árbol
00224   struct Tree_Node_Info : public Node_Info
00225   {
00226     typename GT::Node *              tree_node; // nodo árbol abarcador
00227     typename Distance::Distance_Type dist;      // distancia acumulada
00228     void *                           heap_node;
00229 
00230     Tree_Node_Info() : tree_node(NULL)
00231     { 
00232       // empty
00233     }
00234   };
00235 
00236   // Acceso al heap de arcos
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   // Inicialización de nodo para la versión que pinta
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   // Liberación de memoria de nodo para la versión que pinta
00259   struct Destroy_Node
00260   {
00261     void operator () (GT &, typename GT::Node * p)
00262     {
00263       delete DNI(p); //bloque a liberar
00264     }
00265   };
00266 
00267   // Inicialización de arco para la versión que pinta
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   // Liberación de memoria de arco para la versión que pinta
00279   struct Destroy_Arc
00280   {
00281     void operator () (GT &, typename GT::Arc * ga)
00282     {
00283       delete DAI(ga); 
00284     }
00285   };
00286 
00287   // Inicialización de memoria de nodo para la versión que construye árbol
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   // Liberación de memoria de nodo y mapeo para versión que construye árbol
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); //bloque a liberar
00303       typename GT::Node * tp = TREENODE(p); // imagen en árbol abarcador
00304       if (tp != NULL) // ¿está este nodo incluído en el árbol abarcador? 
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   // Inicialización de arco para la versión que construye árbol
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   // Liberación de memoria y mapeo para la versión que construye árbol
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) // ¿pertenece este arco al árbol abarcador?
00336     {    
00337       I(IS_ARC_VISITED(ga, Aleph::Dijkstra));
00338       GT::map_arcs (ga, ta); // sí ==> mapearlo
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   // Constructores
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     // empty
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     // empty
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); // limpiar árbol abarcador destino 
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)  // mientras tree no abarque a g
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           // ¿Están los dos nodos visitados?
00452     if (IS_NODE_VISITED(gsrc, Aleph::Dijkstra) and 
00453         IS_NODE_VISITED(gtgt, Aleph::Dijkstra))
00454       continue; // insertar arco causaría ciclo
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 = // insertar nuevo arco en tree 
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)); // total dist nodo inicial
00469     const typename Distance::Distance_Type & acc = ACC(gtgt);
00470 
00471     // por cada arco calcular potencial e insertarlo en heap
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; // causaría ciclo ==> no se mete en heap  
00481 
00482         POT(arc) = plus (arc, acc, ARC_DIST(arc)); // calcula potencial
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) // tree no abarque g
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     // ¿Están los dos nodos visitados?
00539     if (IS_NODE_VISITED(gsrc, Aleph::Dijkstra) and 
00540         IS_NODE_VISITED(gtgt, Aleph::Dijkstra))
00541       continue; // insertar arco causaría ciclo
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 = // insertar nuevo arco en tree 
00551       tree.insert_arc(TREENODE(gsrc), TREENODE(gtgt), garc->get_info());
00552     TREEARC(garc)           = tarc;
00553 
00554     if (gtgt == end) // ¿está end_node en árbol abarcador? 
00555       break; // sí ==> camino mínimo ya está en árbol abarcador
00556 
00557     ACC(gtgt) = plus(ACC(gsrc), ARC_DIST(garc)); // total dist nodo inicial
00558     const typename Distance::Distance_Type & acc = ACC(gtgt);
00559 
00560           // por cada arco calcular potencial e insertarlo en heap
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; // causaría ciclo ==> no se mete en heap  
00570 
00571         POT(arc) = plus(arc, acc, ARC_DIST(arc)); // calcula potencial
00572         heap.put_arc(arc, tgt);
00573       }
00574       }
00575 
00576     uninit <Destroy_Tree_Node, Destroy_Tree_Arc> ();
00577   }
00578 
00582   struct Painted     // muestra los arcos cuya bandera Dijstra sea true
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       /* empty */ 
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; // número de nodos pintados
00631 
00632     while (tn < n) // tree no abarque g
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     // ¿Están los dos nodos visitados?
00644     if (IS_NODE_VISITED(src, Aleph::Dijkstra) and 
00645         IS_NODE_VISITED(tgt, Aleph::Dijkstra))
00646       continue; // este arco causaría un ciclo
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; // simula que p se metió en el árbol abarcador
00654 
00655     if (tgt == end) // ¿está end_node en árbol abarcador? 
00656       break; // sí ==> camino mínimo ya está pintado
00657 
00658     ACC(tgt) = plus(ACC(src), ARC_DIST(garc)); // total dist nodo inicial
00659 
00660     const typename Distance::Distance_Type & acc = ACC(tgt);
00661 
00662     // por cada arco calcular potencial e insertarlo en heap
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; // causaría ciclo ==> no se mete en heap  
00672 
00673         POT(a) = plus(a, acc, ARC_DIST(a)); // calcula potencial
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; // número de nodos pintados
00705 
00706     while (tn < n) // tree no abarque g
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     // ¿Están los dos nodos visitados?
00718     if (IS_NODE_VISITED(src, Aleph::Dijkstra) and 
00719         IS_NODE_VISITED(tgt, Aleph::Dijkstra))
00720       continue; // este arco causaría un ciclo
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; // simula que p se metió en el árbol abarcador
00728 
00729     ACC(tgt) = plus(ACC(src), ARC_DIST(garc)); // total dist nodo inicial
00730     const typename Distance::Distance_Type & acc = ACC(tgt);
00731 
00732     // por cada arco calcular potencial e insertarlo en heap
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; // causaría ciclo ==> no se mete en heap  
00742 
00743         POT(a) = plus(a, acc, ARC_DIST(a)); // calcula potencial
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       /* empty */ 
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 } // end namespace Aleph
00951 # endif // DIJKSTRA_H

Leandro Rabindranath León