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

Floyd.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 FLOYD_H
00063 # define FLOYD_H
00064 
00065 # include <ahFunction.H>
00066 # include <tpl_matgraph.H>
00067 
00068 namespace Aleph
00069 {
00070 template <class GT, typename Distance, 
00071           class Compare = Aleph::less<typename Distance::Distance_Type>, 
00072           class Plus    = Aleph::plus<typename Distance::Distance_Type>, 
00073           class SA      = Default_Show_Arc<GT> > 
00074 void floyd_all_shortest_paths 
00075   (GT &                                                g, 
00076    Ady_Mat<GT, typename Distance::Distance_Type, SA> & dist,
00077    Ady_Mat<GT, long, SA> &                             path);
00078 template <class AM, class Distance, class SA> struct Initialize_Dist_Floyd
00079 {
00080   typedef typename AM::List_Graph_Type::Arc_Type Arc_Type;
00081   typedef typename AM::List_Graph_Type GT;
00082   typedef typename GT::Node Node;
00083   typedef typename GT::Arc Arc;
00084   typedef typename Distance::Distance_Type Distance_Type;
00085 
00086       // inicializa cada entrada de la matriz
00087   void operator () (AM & mat, Node * src, Node * tgt, 
00088                     const long & i, const long & j, Distance_Type & entry,
00089                     void * p) const
00090   {
00091     Ady_Mat <typename AM::List_Graph_Type, long, SA> & path = 
00092       * (Ady_Mat <typename AM::List_Graph_Type, long> *) (p);
00093 
00094     if (i == j) // ¿es diagonal de la matriz?
00095       {    // sí ==> la distancia es cero
00096         entry = Distance::Zero_Distance;
00097         path(i, j) = j;
00098         return;
00099       }
00100     GT & g    = mat.get_list_graph();
00101     Arc * arc = search_arc(g, src, tgt); 
00102     if (arc == NULL) // ¿existe un arco?
00103       {    // sí ==> se coloca coste infinito
00104         entry = Distance::Max_Distance;
00105         return;
00106       }
00107         // existe arco ==> extraiga distancia 
00108     entry      = Distance () (arc); // la coloca en cost(i, j)
00109     path(i, j) = j;                 // coloca camino directo
00110   }
00111 };
00186 template <class GT, typename Distance, 
00187           class Compare = Aleph::less<typename Distance::Distance_Type>, 
00188           class Plus    = Aleph::plus<typename Distance::Distance_Type>, 
00189           class SA      = Default_Show_Arc<GT> > 
00190 void floyd_all_shortest_paths
00191   (GT &                                                g, 
00192    Ady_Mat<GT, typename Distance::Distance_Type, SA> & dist, 
00193    Ady_Mat<GT, long, SA> &                             path)
00194 {
00195   typedef typename Distance::Distance_Type Dist_Type;
00196   typedef Ady_Mat <GT, Dist_Type> Dist_Mat;
00197   dist.template operate_all_arcs_matrix 
00198     <Initialize_Dist_Floyd <Dist_Mat, Distance, SA> > (&path);
00199   const Dist_Type & max = Distance::Max_Distance;
00200   const long & n        = g.get_num_nodes();
00201   for (int k = 0; k < n; ++k)
00202     for (int i = 0; i < n; ++i)
00203       if (dist(i, k) < max) // ¿posible encontrar distancia menor?
00204         for (int j = 0; j < n; ++j)
00205           {    // calcule nueva distancia pasando por k
00206             Dist_Type new_dist = Plus () (dist(i, k), dist(k, j));
00207             if (Compare () (new_dist, dist(i,j)))//d(i,j)<d(i,k)+d(k,j)
00208               {
00209                 dist(i, j) = new_dist;   // actualice menor distancia
00210                 path(i, j) = path(i, k); // actualice nodo intermedio
00211               }
00212           }
00213 }
00214 
00281     template <class GT, typename Distance, 
00282               class Compare = Aleph::less<typename Distance::Distance_Type>, 
00283               class Plus    = Aleph::plus<typename Distance::Distance_Type>, 
00284               class SA      = Default_Show_Arc<GT> > 
00285 class Floyd_All_Shortest_Paths
00286 {
00287 public:
00288 
00300       void 
00301   operator () (GT &                                                g, 
00302                Ady_Mat<GT, typename Distance::Distance_Type, SA> & dist, 
00303                Ady_Mat<GT, long, SA> &                             path) const
00304   {
00305     floyd_all_shortest_paths <GT, Distance, Compare, Plus, SA> (g, dist, path);
00306   }
00307 };
00308 
00309     template <class Mat>
00310 void find_min_path(Mat & p, const long & src_index, const long & tgt_index,
00311                    Path<typename Mat::Graph_Type> & path);
00342     template <class Mat>
00343 void find_min_path(Mat & p, typename Mat::Node * src_node, 
00344                    typename Mat::Node * tgt_node,
00345                    Path<typename Mat::Graph_Type> & path)
00346 {
00347   find_min_path(p, p(src_node), p(tgt_node, path));
00348 }
00349 
00350     template <class Mat>
00351 class Find_Min_Path
00352 {
00353 public:
00354 
00355   void operator () (Mat &                                 p, 
00356                     typename Mat::Node *                  src_node, 
00357                     typename Mat::Node *                  tgt_node,
00358                     Path<typename Mat::Graph_Type> & path) const
00359   {
00360     find_min_path <Mat> (p, src_node, tgt_node, path);
00361   }
00362 
00363   void operator () (Mat &                                 p, 
00364                     const long & src_index, const long &  tgt_index,
00365                     Path<typename Mat::Graph_Type> & path) const
00366   {
00367     find_min_path <Mat> (p, src_index, tgt_index, path);
00368   }
00369 };
00370 
00404     template <class Mat> void 
00405 find_min_path(Mat & p, const long & src_idx, const long & tgt_idx,
00406               Path<typename Mat::Graph_Type> & path)
00407 {
00408   typedef typename Mat::Graph_Type GT;
00409   GT & g                  = p.get_list_graph();
00410   typename GT::Node * src = p(src_idx);
00411   path.set_graph(g, src);
00412   for (int i = src_idx, j; j != tgt_idx; i = j)
00413     {
00414       j = p(i, tgt_idx);
00415       path.append(p(j));
00416     }
00417 } 
00418 
00419 } // end namespace Aleph
00420 
00421 # endif // FLOYD_H
00422 

Leandro Rabindranath León