Floyd.H

00001 
00002 /*
00003   This file is part of Aleph system
00004 
00005   Copyright (c) 2002, 2003, 2004, 2005, 2006
00006   UNIVERSITY LOS ANDES (ULA) Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA  
00007 
00008   - Center of Studies in Microelectronics & Distributed Systems (CEMISID) 
00009   - ULA Computer Science Department
00010   - FUNDACITE Mérida - Ministerio de Ciencia y Tecnología
00011 
00012   PERMISSION TO USE, COPY, MODIFY AND DISTRIBUTE THIS SOFTWARE AND ITS
00013   DOCUMENTATION IS HEREBY GRANTED, PROVIDED THAT BOTH THE COPYRIGHT
00014   NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES OF THE
00015   SOFTWARE, DERIVATIVE WORKS OR MODIFIED VERSIONS, AND ANY PORTIONS
00016   THEREOF, AND THAT BOTH NOTICES APPEAR IN SUPPORTING DOCUMENTATION.
00017 
00018   Aleph is distributed in the hope that it will be useful, but WITHOUT
00019   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00020   or FITNESS FOR A PARTICULAR PURPOSE.
00021 
00022   UNIVERSIDAD DE LOS ANDES requests users of this software to return to 
00023 
00024   Leandro Leon
00025   CEMISID 
00026   Ed La Hechicera 
00027   3er piso, ala sur
00028   Facultad de Ingenieria 
00029   Universidad de Los Andes 
00030   Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA    or
00031 
00032   lrleon@ula.ve
00033 
00034   any improvements or extensions that they make and grant Universidad 
00035   de Los Andes (ULA) the rights to redistribute these changes. 
00036 
00037   Aleph is (or was) granted by: 
00038   - Consejo de Desarrollo Cientifico, Humanistico, Tecnico de la ULA 
00039     (CDCHT)
00040   - Fundacite Mérida
00041 */
00042 
00043 
00044 # ifndef FLOYD_H
00045 # define FLOYD_H
00046 
00047 # include <ahFunction.H>
00048 # include <tpl_matgraph.H>
00049 
00050 namespace Aleph
00051 {
00052 
00053     template <class GT, class Distance, class Compare, class Plus> 
00054 void floyd_all_shortest_paths 
00055   (GT &                                            g, 
00056    Ady_Mat<GT, typename Distance::Distance_Type> & dist,
00057    Ady_Mat<GT, long> &                             path);
00058     template <class GT, class Distance> 
00059 void floyd_all_shortest_paths
00060   (GT &                                            g, 
00061    Ady_Mat<GT, typename Distance::Distance_Type> & dist, 
00062    Ady_Mat<GT, long> &                             path)
00063 {
00064   typedef typename Distance::Distance_Type Dist_T;
00065 
00066   floyd_all_shortest_paths
00067     <GT, Distance, Aleph::less<Dist_T>, Aleph::plus<Dist_T> > (g, dist, path);
00068 }
00069     template <class AM, class Distance>
00070 struct Initialize_Dist_Floyd
00071 {
00072   typedef typename AM::List_Graph_Type::Arc_Type Arc_Type;
00073   typedef typename AM::List_Graph_Type GT;
00074   typedef typename GT::Node Node;
00075   typedef typename GT::Arc Arc;
00076   typedef typename Distance::Distance_Type Distance_Type;
00077 
00078       // inicializa cada entrada de la matriz
00079   void operator () (AM & mat, 
00080                     Node * src, Node * tgt,
00081                     const long & i, const long & j,
00082                     Distance_Type & entry,
00083                     void *          p)
00084   {
00085     Ady_Mat <typename AM::List_Graph_Type, long> & path = 
00086       * reinterpret_cast <Ady_Mat <typename AM::List_Graph_Type, long> *> (p);
00087 
00088     if (i == j) // ¿es diagonal de la matriz?
00089       {    // sí ==> la distancia es cero
00090         entry = Distance::Zero_Distance;
00091         path(i, j) = j;
00092         return;
00093       }
00094     
00095     GT & g = mat.get_list_graph();
00096 
00097     Arc * arc = g.search_arc(src, tgt); // arco en representación con listas 
00098 
00099     if (arc == NULL) // ¿existe un arco?
00100       {    // sí ==> se coloca coste infinito
00101         entry = Distance::Max_Distance;
00102         return;
00103       }
00104         // existe arco ==> extraiga distancia 
00105     entry = Distance () (arc); // la coloca en cost(i, j)
00106     path(i, j) = j; // coloca camino directo
00107   }
00108 };
00186     template <class GT, typename Distance, class Compare, class Plus> 
00187 void floyd_all_shortest_paths
00188   (GT &                                            g, 
00189    Ady_Mat<GT, typename Distance::Distance_Type> & dist, 
00190    Ady_Mat<GT, long> &                             path)
00191 {
00192   typedef typename Distance::Distance_Type Dist_Type;
00193   typedef Ady_Mat <GT, Dist_Type> Dist_Mat;
00194 
00195   dist.template operate_all_arcs_matrix 
00196     <Initialize_Dist_Floyd <Dist_Mat, Distance> > (&path);
00197   const Dist_Type & max = Distance::Max_Distance;
00198   const long & n = g.get_num_nodes();
00199   for (int k = 0; k < n; ++k)
00200     for (int i = 0; i < n; ++i)
00201       if (dist(i, k) < max) // ¿es posible encontrar una distancia menor?
00202         for (int j = 0; j < n; ++j)
00203           {    // calcule nueva distancia pasando por k
00204             Dist_Type new_dist = Plus () (dist(i, k), dist(k, j));
00205             
00206             if (Compare()(new_dist, dist(i,j))) // ¿dist(i,j)<dist(i,k)+dist(k,j)?
00207               {
00208                 dist(i, j) = new_dist;   // actualice menor distancia
00209                 path(i, j) = path(i, k); // actualice nodo intermedio
00210               }
00211           }
00212 }
00213 
00214 } // end namespace Aleph
00215 
00216 # endif // FLOYD_H
00217 

Leandro R. León