dijkstra.cc

Go to the documentation of this file.
00001 
00002 /*
00003  * dijkstra.cc
00004  * Copyright (C) 2000 by the University of Southern California
00005  * $Id: dijkstra.cc,v 1.5 2005/08/25 18:58:11 johnh Exp $
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License,
00009  * version 2, as published by the Free Software Foundation.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License along
00017  * with this program; if not, write to the Free Software Foundation, Inc.,
00018  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00019  *
00020  *
00021  * The copyright of this module includes the following
00022  * linking-with-specific-other-licenses addition:
00023  *
00024  * In addition, as a special exception, the copyright holders of
00025  * this module give you permission to combine (via static or
00026  * dynamic linking) this module with free software programs or
00027  * libraries that are released under the GNU LGPL and with code
00028  * included in the standard release of ns-2 under the Apache 2.0
00029  * license or under otherwise-compatible licenses with advertising
00030  * requirements (or modified versions of such code, with unchanged
00031  * license).  You may copy and distribute such a system following the
00032  * terms of the GNU GPL for this module and the licenses of the
00033  * other code concerned, provided that you include the source code of
00034  * that other code when and as the GNU GPL requires distribution of
00035  * source code.
00036  *
00037  * Note that people who make modified versions of this module
00038  * are not obligated to grant this special exception for their
00039  * modified versions; it is their choice whether to do so.  The GNU
00040  * General Public License gives permission to release a modified
00041  * version without this exception; this exception also makes it
00042  * possible to release a modified version which carries forward this
00043  * exception.
00044  *
00045  */
00046 
00047 /*
00048  * Implementation of Dijkstra's SPF algorithm
00049  * contributed to ns
00050  * George Riley, Georgia Tech, Winter 2000
00051  */
00052 
00053 #include "config.h"
00054 #ifdef HAVE_STL
00055 
00056 #include "routealgo/dijkstra.h"
00057 #include "routealgo/routealgo.h"
00058 #include "routealgo/tnode.h"
00059 
00060 #include <stdio.h>
00061 
00062 #ifndef TEST_DIJ
00063 // Declare a multimap for maintaining a sorted Q set
00064 typedef multimap<dist_t, nodeid_t> Q_t;
00065 typedef Q_t::iterator              Q_it;
00066 typedef Q_t::value_type            QPair_t;
00067 
00068 void Dijkstra(
00069               RNodeVec_t& N,
00070               nodeid_t root,
00071               RoutingVec_t& NextHop,
00072               RoutingVec_t& Parent)
00073 {  // Compute shortest path to all nodes from node S
00074 Q_t Q;
00075 Q_t S; // The completed set, with final weights
00076 
00077  // First make the Q set, with all infinity except the source
00078  for ( RNodeVec_it i = N.begin(); i != N.end(); i++)
00079    {
00080      if ((*i)->m_id == root)
00081        Q.insert(QPair_t(0, root));
00082      else
00083        Q.insert(QPair_t(INF, (*i)->m_id));
00084    }
00085  // Fill in all "NONE" in the next hop neighbors and predecessors
00086  NextHop.erase(NextHop.begin(), NextHop.end());
00087  Parent.erase(Parent.begin(), Parent.end());
00088  for (unsigned int i = 0; i < N.size(); i++)
00089    {
00090      NextHop.push_back(NODE_NONE);
00091      Parent.push_back(NODE_NONE);
00092    }
00093 
00094  while(Q.size() != 0)
00095    {
00096      Q_it u = Q.begin(); // Smallest
00097      if(0)printf("Smallest is node %ld dist %ld\n", u->second, u->first);
00098      S.insert(QPair_t(u->first, u->second)); // Add to S for later printout
00099      // Now relax each of the adjacent edges
00100      RNodeVec_it n;
00101      for (n = N.begin(); n != N.end() ;n++)
00102        {
00103          if ((*n)->m_id == u->second) break; // Found it
00104        }
00105      if (n == N.end())
00106        {
00107          printf("ERROR! Can't find node %ld\n", u->second);
00108          exit(1);
00109        }
00110      NodeWeight_t e(NODE_NONE, 0);
00111      while(1)
00112        { // Relax each adjacent node
00113          Q_it a;
00114          e = (*n)->NextAdj(e); // Next adj
00115          if (e.first == NODE_NONE) break; // Done..
00116          if(0)printf("Looking for adj node %ld\n", e.first);
00117          for (a = Q.begin(); a != Q.end(); a++)
00118            {
00119              if(0) printf("Searching,a->second %ld e.first %ld\n",
00120                       a->second,e.first);
00121              if (a->second == e.first) break; // Found it
00122            }
00123          if (a != Q.end())
00124            { // Not removed yet
00125              if(0)printf("Found it, edge weight is %d\n", e.second);
00126              dist_t d = u->first + e.second; // New distance to the adj
00127              if (d < a->first)
00128                { // Found new best path, remove and re-insert
00129                  // Update the next hop neighbor vector
00130                  if (u->second == root)
00131                    { // First hop
00132                      if(0)printf("Assuming first hop %ld\n",u->second);
00133                      NextHop[a->second] = a->second;
00134                    }
00135                  else
00136                    { // Else hop to new one through same one to me
00137                      NextHop[a->second] = NextHop[u->second];
00138                    }
00139                  // And re-insert new smaller dist into Q set
00140                  nodeid_t nid = a->second;
00141                  if(0)printf("Found new best d to node %ld dist %ld\n",nid, d);
00142                  if(0)printf("u->first %ld e->m_w %d\n", u->first, e.second);
00143                  Q.erase(a);
00144                  Q.insert(QPair_t(d, nid));
00145                  // And set parent
00146                  Parent[nid] = u->second;
00147                }
00148            }
00149        }
00150      Q.erase(u);
00151    }
00152   for (Q_it q = S.begin(); q != S.end(); q++)
00153     printf("Node %ld dist %ld\n", q->second, q->first);
00154 }
00155 #endif
00156 
00157 #ifdef TEST_DIJ
00158 RNodeVec_t Nodes;
00159 
00160 int main()
00161 {
00162 Node N0(0);
00163 Node N1(1);
00164 Node N2(2);
00165 Node N3(3);
00166 Node N4(4);
00167 RoutingVec_t NextHop;
00168 RoutingVec_t Parent;
00169 
00170  N0.AddAdj(1, 10);
00171  N0.AddAdj(2, 5);
00172 
00173  N1.AddAdj(3, 1);
00174  N1.AddAdj(2, 2);
00175 
00176  N2.AddAdj(4, 2);
00177  N2.AddAdj(1, 3);
00178  N2.AddAdj(3, 9);
00179 
00180  N3.AddAdj(4, 4);
00181 
00182  N4.AddAdj(0, 7);
00183  N4.AddAdj(3, 6);
00184 
00185  Nodes.push_back(&N0);
00186  Nodes.push_back(&N1);
00187  Nodes.push_back(&N2);
00188  Nodes.push_back(&N3);
00189  Nodes.push_back(&N4);
00190 
00191  for (nodeid_t i = 0; i < Nodes.size(); i++)
00192    { // Get shortest path for each root node
00193      printf("\nFrom root %ld\n", i);
00194      Dijkstra(Nodes, i, NextHop, Parent);
00195      PrintParents(Parent);
00196      for (unsigned int k = 0; k < Nodes.size(); k++)
00197        printf("Next hop for node %d is %ld\n", k, NextHop[k]);
00198      printf("Printing paths\n");
00199      for (nodeid_t j = 0; j < Nodes.size(); j++)
00200        {
00201          PrintRoute(i, j, Parent);
00202        }
00203    }
00204  return(0);
00205 }
00206 #endif
00207 
00208 #endif /* STL */

Generated on Tue Mar 6 16:47:44 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6