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

Bellman_Ford.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 BELLMAN_FORD_H
00063 # define BELLMAN_FORD_H
00064 
00065 # include <tpl_dynListQueue.H>
00066 # include <tpl_avl.H>
00067 # include <tpl_graph_utils.H>
00068 # include <Tarjan.H>
00069 
00070 namespace Aleph {
00071 # define NI(p) (static_cast<Bellman_Ford_Node_Info<GT, Distance>*>(NODE_COOKIE(p)))
00072 # define IDX(p) (NI(p)->idx)
00073 # define ACU(p) (NI(p)->acum)
00074 
00075 template <class GT, class Distance> struct Bellman_Ford_Node_Info
00076 {
00077   int                              idx;
00078   typename Distance::Distance_Type acum;
00079 };
00150 template <class GT, class Distance, 
00151           class Compare = Aleph::less<typename Distance::Distance_Type>, 
00152           class Plus    = Aleph::plus<typename Distance::Distance_Type>, 
00153           class SA      = Default_Show_Arc<GT> > inline
00154 bool bellman_ford_min_spanning_tree(GT & g, typename GT::Node * start_node, 
00155                                     GT & tree) 
00156 {
00157   if (not g.is_digraph())
00158     throw std::domain_error("Bellman-Ford algorithm only operates on digraphs");
00159   clear_graph(tree); // limpiar árbol abarcador destino 
00160   DynArray<typename GT::Node*> pred(g.get_num_nodes());
00161   DynArray<typename GT::Arc*>  arcs(g.get_num_nodes());
00162   {
00163     typename GT::Node_Iterator it(g);
00164     for (int i = 0; it.has_current(); ++i, it.next())
00165       {
00166         pred[i] = NULL; 
00167         arcs[i] = NULL;
00168         typename GT::Node * p = it.get_current_node();
00169         g.reset_bit(p, Aleph::Min); // colocar bit en cero
00170         Bellman_Ford_Node_Info <GT, Distance> * ptr = 
00171           new Bellman_Ford_Node_Info <GT, Distance>;
00172         ptr->idx  = i;                        
00173         ptr->acum = Distance::Max_Distance; // infinito
00174         NODE_BITS(p).set_bit(Min, false); 
00175         NODE_BITS(p).set_bit(Breadth_First, false); 
00176         NODE_COOKIE(p) = ptr;
00177     }
00178   }
00179   ACU(start_node) = Distance::Zero_Distance;
00180   g.reset_bit_arcs(Min); 
00181   for (int i = 0, n = g.get_num_nodes() - 1; i < n; ++i)
00182     for (Arc_Iterator<GT, SA> it(g); it.has_current(); it.next())
00183       {
00184         typename GT::Arc * arc  = it.get_current_arc();
00185         typename GT::Node * src = g.get_src_node(arc);
00186         typename GT::Node * tgt = g.get_tgt_node(arc);
00187         const typename Distance::Distance_Type & acum_src = ACU(src);
00188         if (acum_src == Distance::Max_Distance)
00189           continue;
00190 
00191         const typename Distance::Distance_Type & dist = Distance () (arc);
00192         typename Distance::Distance_Type & acum_tgt = ACU(tgt);
00193         const typename Distance::Distance_Type sum = Plus () (acum_src, dist);
00194         if (Compare () (sum, acum_tgt)) // ¿sum < acum_tgt?
00195           {
00196             const int & idx = IDX(tgt);
00197             pred[idx]       = src;
00198             arcs[idx]       = arc;
00199             acum_tgt        = sum;
00200           }
00201       }
00202   bool negative_cycle = false;
00203       // recorrer todos los arcos en búsqueda de un ciclo negativo
00204   for (Arc_Iterator<GT, SA> it(g); it.has_current(); it.next())
00205     {
00206       typename GT::Arc * arc  = it.get_current_arc();
00207       typename GT::Node * src = g.get_src_node(arc);
00208       const typename Distance::Distance_Type & acum_src = ACU(src);
00209       if (acum_src == Distance::Max_Distance)
00210         continue;
00211 
00212       typename GT::Node * tgt = g.get_tgt_node(arc);
00213       const typename Distance::Distance_Type & dist = Distance () (arc);
00214       typename Distance::Distance_Type & acum_tgt   = ACU(tgt);
00215       const typename Distance::Distance_Type sum    = Plus ()(acum_src, dist);
00216 
00217       if (Compare () (sum, acum_tgt)) // ¿se relaja arco?
00218         {     // sí ==> ciclo negativo!
00219           negative_cycle  = true; 
00220           const int & idx = IDX(tgt);
00221           pred[idx]       = src;
00222           arcs[idx]       = arc;
00223           acum_tgt        = sum;
00224         }
00225     }
00226 
00227       // liberar memoria de los cookies de los nodos
00228   for (Node_Iterator<GT> it(g); it.has_current(); it.next())
00229     {
00230       typename GT::Node * p = it.get_current_node();
00231       delete NI(p);
00232       NODE_COOKIE(p) = NULL;
00233     }
00234 
00235   if (negative_cycle) // ¿hay ciclos negativos?
00236     // liberar memoria de los cookies de los nodos y terminar
00237 
00238     {
00239           // liberar memoria de los cookies de los nodos
00240       for (Node_Iterator<GT> it(g); it.has_current(); it.next())
00241         {
00242           typename GT::Node * p = it.get_current_node();
00243           delete NI(p);
00244           NODE_COOKIE(p) = NULL;
00245         }
00246       return true;
00247     }
00248 
00249   for (int i = 0; i < g.get_num_nodes(); ++i) 
00250     {
00251       typename GT::Arc * garc = arcs[i];
00252       if (garc == NULL) 
00253         continue;
00254 
00255       typename GT::Node * gsrc = g.get_src_node(garc);
00256       typename GT::Node * tsrc = NULL;
00257       if (IS_NODE_VISITED(gsrc, Min))
00258         tsrc = mapped_node<GT> (gsrc);
00259       else
00260         {
00261           NODE_BITS(gsrc).set_bit(Min, true); // marcar bit
00262           delete NI(gsrc);
00263           tsrc = tree.insert_node(gsrc->get_info());
00264           GT::map_nodes(gsrc, tsrc);
00265         }
00266 
00267       typename GT::Node * gtgt = g.get_tgt_node(garc);
00268       typename GT::Node * ttgt = NULL;
00269       if (IS_NODE_VISITED(gtgt, Min))
00270         ttgt = mapped_node<GT> (gtgt);
00271       else
00272         {
00273           NODE_BITS(gtgt).set_bit(Min, true); // marcar bit
00274           delete NI(gtgt);
00275           ttgt = tree.insert_node(gtgt->get_info());
00276           GT::map_nodes(gtgt, ttgt);
00277         }
00278       typename GT::Arc * tarc = tree.insert_arc(tsrc, ttgt, garc->get_info());
00279       GT::map_arcs(garc, tarc);
00280       ARC_BITS(garc).set_bit(Min, true);
00281     }
00282   return false; // no hay ciclos negativos
00283 }
00284 
00285     template <class GT> inline static 
00286 void put_in_queue(DynListQueue<typename GT::Node*> & q, typename GT::Node * p)
00287 {
00288   q.put(p);
00289   NODE_BITS(p).set_bit(Breadth_First, true); 
00290 }
00291     template <class GT> inline static typename GT::Node * 
00292 get_from_queue(DynListQueue<typename GT::Node*> & q)
00293 {
00294   typename GT::Node * p = q.get();
00295   NODE_BITS(p).set_bit(Breadth_First, false);
00296   return p;
00297 }
00298 template <class GT> inline static bool is_in_queue(typename GT::Node * p)
00299 {
00300   return IS_NODE_VISITED(p, Breadth_First);
00301 }
00302 
00382 template <class GT, class Distance, 
00383           class Compare = Aleph::less<typename Distance::Distance_Type>, 
00384           class Plus    = Aleph::plus<typename Distance::Distance_Type>, 
00385           class SA      = Default_Show_Arc<GT> > inline
00386 bool q_bellman_ford_min_spanning_tree(GT & g, typename GT::Node * start_node, 
00387                                       GT & tree)
00388 {
00389   if (not g.is_digraph())
00390     throw std::domain_error("Bellman-Ford algorithm only operates on digraphs");
00391   clear_graph(tree); // limpiar árbol abarcador destino 
00392   DynArray<typename GT::Node*> pred(g.get_num_nodes());
00393   DynArray<typename GT::Arc*>  arcs(g.get_num_nodes());
00394   {
00395     typename GT::Node_Iterator it(g);
00396     for (int i = 0; it.has_current(); ++i, it.next())
00397       {
00398         pred[i] = NULL; 
00399         arcs[i] = NULL;
00400         typename GT::Node * p = it.get_current_node();
00401         g.reset_bit(p, Aleph::Min); // colocar bit en cero
00402         Bellman_Ford_Node_Info <GT, Distance> * ptr = 
00403           new Bellman_Ford_Node_Info <GT, Distance>;
00404         ptr->idx  = i;                        
00405         ptr->acum = Distance::Max_Distance; // infinito
00406         NODE_BITS(p).set_bit(Min, false); 
00407         NODE_BITS(p).set_bit(Breadth_First, false); 
00408         NODE_COOKIE(p) = ptr;
00409     }
00410   }
00411   ACU(start_node) = Distance::Zero_Distance;
00412   g.reset_bit_arcs(Min); 
00413   DynListQueue<typename GT::Node*> q;
00414   typename GT::Node __sentinel;
00415   typename GT::Node * sentinel = &__sentinel;
00416   put_in_queue <GT> (q, sentinel);
00417   put_in_queue <GT> (q, start_node);
00418   for (int i = 0, n = g.get_num_nodes() - 1; not q.is_empty(); )
00419     {
00420       typename GT::Node * src = get_from_queue <GT> (q); 
00421       if (src == sentinel) // ¿se saca el centinela?
00422         if (i++ == n) 
00423           break;
00424         else
00425           put_in_queue <GT> (q, sentinel);
00426 
00427           // recorrer y relajar arcos del nodo src
00428       for (Node_Arc_Iterator<GT, SA> it(src); it.has_current(); it.next()) 
00429         {
00430           typename GT::Arc * arc = it.get_current_arc();
00431           const typename Distance::Distance_Type & acum_src = ACU(src);
00432           if (acum_src == Distance::Max_Distance)
00433             continue;
00434 
00435           typename GT::Node * tgt = it.get_tgt_node();
00436           const typename Distance::Distance_Type & w = Distance () (arc);
00437           const typename Distance::Distance_Type sum_src = 
00438             Plus () (acum_src, w);
00439           typename Distance::Distance_Type & acum_tgt = ACU(tgt);
00440           if (Compare () (sum_src, acum_tgt)) // relajar arco
00441             {
00442               const int & idx = IDX(tgt);
00443               pred[idx]       = src;
00444               arcs[idx]       = arc;
00445               acum_tgt        = sum_src;
00446               if (not is_in_queue <GT> (tgt))
00447                 put_in_queue <GT> (q, tgt);
00448             }
00449         }
00450     }
00451   bool negative_cycle = false;
00452       // recorrer todos los arcos en búsqueda de un ciclo negativo
00453   for (Arc_Iterator<GT, SA> it(g); it.has_current(); it.next())
00454     {
00455       typename GT::Arc * arc  = it.get_current_arc();
00456       typename GT::Node * src = g.get_src_node(arc);
00457       const typename Distance::Distance_Type & acum_src = ACU(src);
00458       if (acum_src == Distance::Max_Distance)
00459         continue;
00460 
00461       typename GT::Node * tgt = g.get_tgt_node(arc);
00462       const typename Distance::Distance_Type & dist = Distance () (arc);
00463       typename Distance::Distance_Type & acum_tgt   = ACU(tgt);
00464       const typename Distance::Distance_Type sum    = Plus ()(acum_src, dist);
00465 
00466       if (Compare () (sum, acum_tgt)) // ¿se relaja arco?
00467         {     // sí ==> ciclo negativo!
00468           negative_cycle  = true; 
00469           const int & idx = IDX(tgt);
00470           pred[idx]       = src;
00471           arcs[idx]       = arc;
00472           acum_tgt        = sum;
00473         }
00474     }
00475 
00476       // liberar memoria de los cookies de los nodos
00477   for (Node_Iterator<GT> it(g); it.has_current(); it.next())
00478     {
00479       typename GT::Node * p = it.get_current_node();
00480       delete NI(p);
00481       NODE_COOKIE(p) = NULL;
00482     }
00483 
00484   if (negative_cycle) // ¿hay ciclos negativos?
00485     // liberar memoria de los cookies de los nodos y terminar
00486 
00487     {
00488           // liberar memoria de los cookies de los nodos
00489       for (Node_Iterator<GT> it(g); it.has_current(); it.next())
00490         {
00491           typename GT::Node * p = it.get_current_node();
00492           delete NI(p);
00493           NODE_COOKIE(p) = NULL;
00494         }
00495       return true;
00496     }
00497 
00498   for (int i = 0; i < g.get_num_nodes(); ++i) 
00499     {
00500       typename GT::Arc * garc = arcs[i];
00501       if (garc == NULL) 
00502         continue;
00503 
00504       typename GT::Node * gsrc = g.get_src_node(garc);
00505       typename GT::Node * tsrc = NULL;
00506       if (IS_NODE_VISITED(gsrc, Min))
00507         tsrc = mapped_node<GT> (gsrc);
00508       else
00509         {
00510           NODE_BITS(gsrc).set_bit(Min, true); // marcar bit
00511           delete NI(gsrc);
00512           tsrc = tree.insert_node(gsrc->get_info());
00513           GT::map_nodes(gsrc, tsrc);
00514         }
00515 
00516       typename GT::Node * gtgt = g.get_tgt_node(garc);
00517       typename GT::Node * ttgt = NULL;
00518       if (IS_NODE_VISITED(gtgt, Min))
00519         ttgt = mapped_node<GT> (gtgt);
00520       else
00521         {
00522           NODE_BITS(gtgt).set_bit(Min, true); // marcar bit
00523           delete NI(gtgt);
00524           ttgt = tree.insert_node(gtgt->get_info());
00525           GT::map_nodes(gtgt, ttgt);
00526         }
00527       typename GT::Arc * tarc = tree.insert_arc(tsrc, ttgt, garc->get_info());
00528       GT::map_arcs(garc, tarc);
00529       ARC_BITS(garc).set_bit(Min, true);
00530     }
00531   return false; // no hay ciclos negativos
00532 }
00591  template <class GT, class Distance, 
00592            class Compare = Aleph::less<typename Distance::Distance_Type>, 
00593            class Plus    = Aleph::plus<typename Distance::Distance_Type>, 
00594            class SA      = Default_Show_Arc<GT> > 
00595 class Bellman_Ford_Min_Spanning_Tree
00596 { 
00597 public:
00598 
00615   bool operator () (GT & g, typename GT::Node * start_node, GT & tree)
00616   {
00617     return bellman_ford_min_spanning_tree <GT, Distance, Compare, Plus, SA>
00618       (g, start_node, tree);
00619   }
00620 };
00621 
00680  template <class GT, class Distance, 
00681            class Compare = Aleph::less<typename Distance::Distance_Type>, 
00682            class Plus    = Aleph::plus<typename Distance::Distance_Type>, 
00683            class SA      = Default_Show_Arc<GT> > 
00684 class Q_Bellman_Ford_Min_Spanning_Tree
00685 { 
00686 public:
00687 
00704   bool operator () (GT & g, typename GT::Node * start_node, GT & tree)
00705   {
00706     return q_bellman_ford_min_spanning_tree <GT, Distance, Compare, Plus, SA>
00707       (g, start_node, tree);
00708   }
00709 
00718       inline bool 
00719   has_negative_cycle(GT & g, typename GT::Node * s, Path<GT> & path) const;
00720 };
00763      template <class GT>
00764 bool search_cycle(GT & g, DynArray<typename GT::Node *> & pred,
00765                   DynArray<typename GT::Arc *>  & arcs, Path<GT> & cycle)
00766 {
00767   const size_t & n = pred.size(); // cantidad de nodos de g
00768   DynMapAvlTree<typename GT::Node*, typename GT::Node*> nodes_table; 
00769   GT aux; 
00770   for (int i = 0; i < n; ++i) // insertar nodos en aux
00771     {
00772       typename GT::Node * p = pred.access(i);
00773       if (p == NULL or NODE_COOKIE(p) != NULL) // ¿insertado y mapeado?
00774         continue; // sí ==> avance al siguiente
00775 
00776       typename GT::Node * q = aux.insert_node(p->get_info());
00777       GT::map_nodes(p, q);
00778       nodes_table.insert(q, p);
00779     }
00780 
00781   for (int i = 0; i < n; ++i) // insertar arcos en aux
00782     {
00783       typename GT::Arc * a = arcs.access(i);
00784       if (a == NULL or ARC_COOKIE(a) != NULL)
00785         continue;
00786 
00787       typename GT::Node * gsrc = g.get_src_node(a);
00788       typename GT::Node * gtgt = g.get_tgt_node(a);
00789       if (NODE_COOKIE(gsrc) == NULL or NODE_COOKIE(gtgt) == NULL)
00790         continue; // src o tgt no está en pred ==> no en ciclo
00791 
00792       typename GT::Node * aux_src = mapped_node<GT> (gsrc);
00793       typename GT::Node * aux_tgt = mapped_node<GT> (gtgt);
00794       aux.insert_arc(aux_src, aux_tgt);
00795     }
00796   Path<GT> path; // buscar ciclo en aux mediante algo de Tarjan
00797   if (not Compute_Cycle_In_Digraph <GT> () (aux, path))
00798     return false; // no existe ciclo
00799 
00800   cycle.set_graph(g); // mapear ciclo en aux al camino cyle en g
00801 
00802   for (typename Path<GT>::Iterator it(path); it.has_current(); it.next())
00803     cycle.append(nodes_table[it.get_current_node()]);
00804 
00805   return true;
00806 }
00807 
00829      template <class GT>
00830 class Search_Cycle
00831 {
00832 public:
00833 
00852   bool operator () (GT &                            g, 
00853                     DynArray<typename GT::Node *> & pred,
00854                     DynArray<typename GT::Arc *>  & arcs,
00855                     Path<GT> &                      cycle) const
00856   {
00857     return search_cycle <GT> (g, pred, arcs, cycle);
00858   }
00859 };
00860 
00906 template <class GT, class Distance, 
00907           class Compare = Aleph::less<typename Distance::Distance_Type>, 
00908           class Plus    = Aleph::plus<typename Distance::Distance_Type>, 
00909           class SA      = Default_Show_Arc<GT> > inline
00910 bool bellman_ford_negative_cycle(GT & g, typename GT::Node * start_node,
00911                                  Path<GT> & cycle)
00912 {
00913   GT tree; // árbol sobre el cual opera algoritmo de Bellman-Ford
00914   if (not g.is_digraph())
00915     throw std::domain_error("Bellman-Ford algorithm only operates on digraphs");
00916   clear_graph(tree); // limpiar árbol abarcador destino 
00917   DynArray<typename GT::Node*> pred(g.get_num_nodes());
00918   DynArray<typename GT::Arc*>  arcs(g.get_num_nodes());
00919   {
00920     typename GT::Node_Iterator it(g);
00921     for (int i = 0; it.has_current(); ++i, it.next())
00922       {
00923         pred[i] = NULL; 
00924         arcs[i] = NULL;
00925         typename GT::Node * p = it.get_current_node();
00926         g.reset_bit(p, Aleph::Min); // colocar bit en cero
00927         Bellman_Ford_Node_Info <GT, Distance> * ptr = 
00928           new Bellman_Ford_Node_Info <GT, Distance>;
00929         ptr->idx  = i;                        
00930         ptr->acum = Distance::Max_Distance; // infinito
00931         NODE_BITS(p).set_bit(Min, false); 
00932         NODE_BITS(p).set_bit(Breadth_First, false); 
00933         NODE_COOKIE(p) = ptr;
00934     }
00935   }
00936   ACU(start_node) = Distance::Zero_Distance;
00937   g.reset_bit_arcs(Min); 
00938   for (int i = 0, n = g.get_num_nodes() - 1; i < n; ++i)
00939     for (Arc_Iterator<GT, SA> it(g); it.has_current(); it.next())
00940       {
00941         typename GT::Arc * arc  = it.get_current_arc();
00942         typename GT::Node * src = g.get_src_node(arc);
00943         typename GT::Node * tgt = g.get_tgt_node(arc);
00944         const typename Distance::Distance_Type & acum_src = ACU(src);
00945         if (acum_src == Distance::Max_Distance)
00946           continue;
00947 
00948         const typename Distance::Distance_Type & dist = Distance () (arc);
00949         typename Distance::Distance_Type & acum_tgt = ACU(tgt);
00950         const typename Distance::Distance_Type sum = Plus () (acum_src, dist);
00951         if (Compare () (sum, acum_tgt)) // ¿sum < acum_tgt?
00952           {
00953             const int & idx = IDX(tgt);
00954             pred[idx]       = src;
00955             arcs[idx]       = arc;
00956             acum_tgt        = sum;
00957           }
00958       }
00959   bool negative_cycle = false;
00960       // recorrer todos los arcos en búsqueda de un ciclo negativo
00961   for (Arc_Iterator<GT, SA> it(g); it.has_current(); it.next())
00962     {
00963       typename GT::Arc * arc  = it.get_current_arc();
00964       typename GT::Node * src = g.get_src_node(arc);
00965       const typename Distance::Distance_Type & acum_src = ACU(src);
00966       if (acum_src == Distance::Max_Distance)
00967         continue;
00968 
00969       typename GT::Node * tgt = g.get_tgt_node(arc);
00970       const typename Distance::Distance_Type & dist = Distance () (arc);
00971       typename Distance::Distance_Type & acum_tgt   = ACU(tgt);
00972       const typename Distance::Distance_Type sum    = Plus ()(acum_src, dist);
00973 
00974       if (Compare () (sum, acum_tgt)) // ¿se relaja arco?
00975         {     // sí ==> ciclo negativo!
00976           negative_cycle  = true; 
00977           const int & idx = IDX(tgt);
00978           pred[idx]       = src;
00979           arcs[idx]       = arc;
00980           acum_tgt        = sum;
00981         }
00982     }
00983 
00984       // liberar memoria de los cookies de los nodos
00985   for (Node_Iterator<GT> it(g); it.has_current(); it.next())
00986     {
00987       typename GT::Node * p = it.get_current_node();
00988       delete NI(p);
00989       NODE_COOKIE(p) = NULL;
00990     }
00991 
00992   if (not negative_cycle)
00993     return false;
00994 
00995   Search_Cycle <GT> () (g, pred, arcs, cycle);
00996 
00997   return true;
00998 }
01046 template <class GT, class Distance, 
01047           class Compare = Aleph::less<typename Distance::Distance_Type>, 
01048           class Plus    = Aleph::plus<typename Distance::Distance_Type>, 
01049           class SA      = Default_Show_Arc<GT> > inline
01050 bool bellman_ford_negative_cycle(GT &                g, 
01051                                  typename GT::Node * start_node,
01052                                  GT &                tree,
01053                                  Path<GT> &          cycle)
01054 {
01055   if (not g.is_digraph())
01056     throw std::domain_error("Bellman-Ford algorithm only operates on digraphs");
01057   clear_graph(tree); // limpiar árbol abarcador destino 
01058   DynArray<typename GT::Node*> pred(g.get_num_nodes());
01059   DynArray<typename GT::Arc*>  arcs(g.get_num_nodes());
01060   {
01061     typename GT::Node_Iterator it(g);
01062     for (int i = 0; it.has_current(); ++i, it.next())
01063       {
01064         pred[i] = NULL; 
01065         arcs[i] = NULL;
01066         typename GT::Node * p = it.get_current_node();
01067         g.reset_bit(p, Aleph::Min); // colocar bit en cero
01068         Bellman_Ford_Node_Info <GT, Distance> * ptr = 
01069           new Bellman_Ford_Node_Info <GT, Distance>;
01070         ptr->idx  = i;                        
01071         ptr->acum = Distance::Max_Distance; // infinito
01072         NODE_BITS(p).set_bit(Min, false); 
01073         NODE_BITS(p).set_bit(Breadth_First, false); 
01074         NODE_COOKIE(p) = ptr;
01075     }
01076   }
01077   ACU(start_node) = Distance::Zero_Distance;
01078   g.reset_bit_arcs(Min); 
01079   DynListQueue<typename GT::Node*> q;
01080   typename GT::Node __sentinel;
01081   typename GT::Node * sentinel = &__sentinel;
01082   put_in_queue <GT> (q, sentinel);
01083   put_in_queue <GT> (q, start_node);
01084   for (int i = 0, n = g.get_num_nodes() - 1; not q.is_empty(); )
01085     {
01086       typename GT::Node * src = get_from_queue <GT> (q); 
01087       if (src == sentinel) // ¿se saca el centinela?
01088         if (i++ == n) 
01089           break;
01090         else
01091           put_in_queue <GT> (q, sentinel);
01092 
01093           // recorrer y relajar arcos del nodo src
01094       for (Node_Arc_Iterator<GT, SA> it(src); it.has_current(); it.next()) 
01095         {
01096           typename GT::Arc * arc = it.get_current_arc();
01097           const typename Distance::Distance_Type & acum_src = ACU(src);
01098           if (acum_src == Distance::Max_Distance)
01099             continue;
01100 
01101           typename GT::Node * tgt = it.get_tgt_node();
01102           const typename Distance::Distance_Type & w = Distance () (arc);
01103           const typename Distance::Distance_Type sum_src = 
01104             Plus () (acum_src, w);
01105           typename Distance::Distance_Type & acum_tgt = ACU(tgt);
01106           if (Compare () (sum_src, acum_tgt)) // relajar arco
01107             {
01108               const int & idx = IDX(tgt);
01109               pred[idx]       = src;
01110               arcs[idx]       = arc;
01111               acum_tgt        = sum_src;
01112               if (not is_in_queue <GT> (tgt))
01113                 put_in_queue <GT> (q, tgt);
01114             }
01115         }
01116     }
01117   bool negative_cycle = false;
01118       // recorrer todos los arcos en búsqueda de un ciclo negativo
01119   for (Arc_Iterator<GT, SA> it(g); it.has_current(); it.next())
01120     {
01121       typename GT::Arc * arc  = it.get_current_arc();
01122       typename GT::Node * src = g.get_src_node(arc);
01123       const typename Distance::Distance_Type & acum_src = ACU(src);
01124       if (acum_src == Distance::Max_Distance)
01125         continue;
01126 
01127       typename GT::Node * tgt = g.get_tgt_node(arc);
01128       const typename Distance::Distance_Type & dist = Distance () (arc);
01129       typename Distance::Distance_Type & acum_tgt   = ACU(tgt);
01130       const typename Distance::Distance_Type sum    = Plus ()(acum_src, dist);
01131 
01132       if (Compare () (sum, acum_tgt)) // ¿se relaja arco?
01133         {     // sí ==> ciclo negativo!
01134           negative_cycle  = true; 
01135           const int & idx = IDX(tgt);
01136           pred[idx]       = src;
01137           arcs[idx]       = arc;
01138           acum_tgt        = sum;
01139         }
01140     }
01141       // liberar memoria de los cookies de los nodos
01142   for (Node_Iterator<GT> it(g); it.has_current(); it.next())
01143     {
01144       typename GT::Node * p = it.get_current_node();
01145       delete NI(p);
01146       NODE_COOKIE(p) = NULL;
01147     }
01148 
01149   if (not negative_cycle)
01150         // liberar memoria de los cookies de los nodos
01151     for (Node_Iterator<GT> it(g); it.has_current(); it.next())
01152       {
01153         typename GT::Node * p = it.get_current_node();
01154         delete NI(p);
01155         NODE_COOKIE(p) = NULL;
01156       }
01157     {
01158       for (int i = 0; i < g.get_num_nodes(); ++i)
01159         {
01160           typename GT::Arc * garc = arcs[i];
01161           if (garc == NULL) 
01162             continue;
01163 
01164           typename GT::Node * gsrc = g.get_src_node(garc);
01165           typename GT::Node * tsrc = NULL;
01166           if (IS_NODE_VISITED(gsrc, Min))
01167             tsrc = static_cast<typename GT::Node*>(NODE_COOKIE(gsrc));
01168           else
01169             {
01170               NODE_BITS(gsrc).set_bit(Min, true); // marcar bit
01171               delete NI(gsrc);
01172               tsrc = tree.insert_node(gsrc->get_info());
01173               GT::map_nodes(gsrc, tsrc);
01174             }
01175 
01176           typename GT::Node * gtgt = g.get_tgt_node(garc);
01177           typename GT::Node * ttgt = NULL;
01178           if (IS_NODE_VISITED(gtgt, Min))
01179             ttgt = static_cast<typename GT::Node*>(NODE_COOKIE(gtgt));
01180           else
01181             {
01182               NODE_BITS(gtgt).set_bit(Min, true); // marcar bit
01183               delete NI(gtgt);
01184               ttgt = tree.insert_node(gtgt->get_info());
01185               GT::map_nodes(gtgt, ttgt);
01186             }
01187 
01188           typename GT::Arc * tarc = tree.insert_arc(tsrc, ttgt, garc->get_info());
01189           GT::map_arcs(garc, tarc);
01190           ARC_BITS(garc).set_bit(Min, true);
01191         }
01192       return false; // no hay ciclos negativos
01193     }
01194 
01195   Search_Cycle <GT> () (g, pred, arcs, cycle);
01196 
01197   return true;
01198 }
01253 template <class GT, class Distance, 
01254           class Compare = Aleph::less<typename Distance::Distance_Type>, 
01255           class Plus    = Aleph::plus<typename Distance::Distance_Type>, 
01256           class SA      = Default_Show_Arc<GT> > inline
01257 bool bellman_ford_negative_cycle(GT & g, Path<GT> & cycle)
01258 {
01259   DynDlist<DynDlist<typename GT::Node*> > blocks; 
01260 
01261   Tarjan_Connected_Components <GT, SA> () (g, blocks);
01262 
01263       // recorrer todos los bloques
01264   for (typename DynDlist<DynDlist<typename GT::Node*> >::Iterator 
01265          it(blocks); it.has_current(); it.next())
01266     {     
01267       DynDlist<typename GT::Node*> & block = it.get_current();
01268       if (block.size() == 1)
01269         continue;
01270 
01271       typename GT::Node * src = block.get_first(); // nodo inicio
01272       if (bellman_ford_negative_cycle<GT,Distance,Compare,Plus,SA>
01273           (g, src, cycle))
01274         return true;
01275     }
01276   return false;
01277 }
01316  template <class GT, class Distance, 
01317            class Compare = Aleph::less<typename Distance::Distance_Type>, 
01318            class Plus    = Aleph::plus<typename Distance::Distance_Type>, 
01319            class SA      = Default_Show_Arc<GT> > 
01320 class Bellman_Ford_Negative_Cycle
01321 { 
01322 public:
01323 
01334   bool operator () (GT & g, typename GT::Node * s, Path<GT> & path) const
01335   {
01336     return bellman_ford_negative_cycle <GT, Distance, Compare, Plus, SA>
01337       (g, s, path);
01338   }
01339 
01353       bool 
01354   operator () (GT & g, typename GT::Node * s, GT & tree, Path<GT> & path) const
01355   {
01356     return bellman_ford_negative_cycle <GT, Distance, Compare, Plus, SA>
01357       (g, s, tree, path);
01358   }
01359 
01379       bool 
01380   operator () (GT & g, Path<GT> & cycle) const
01381   {
01382     return
01383       bellman_ford_negative_cycle <GT, Distance, Compare, Plus, SA> (g, cycle);
01384   }
01385 };
01386 
01387     template <class GT, class Distance, class Compare, class Plus, class SA> 
01388 bool Q_Bellman_Ford_Min_Spanning_Tree
01389     <GT, Distance, Compare, Plus, SA>::
01390     has_negative_cycle(GT & g, typename GT::Node * s, Path<GT> & path) const
01391 {
01392   return bellman_ford_negative_cycle <GT, Distance, Compare, Plus, SA>
01393     (g, s, path);
01394 }
01395 
01396 # undef NI
01397 # undef IDX
01398 # undef ACU
01399 } // end namespace Aleph
01400 
01401 # endif // BELLMAN_FORD_H

Leandro Rabindranath León