Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

dijkstra.hxx

Go to the documentation of this file.
00001 // Copyright (C) 2003, 2004, 2005 Laboratoire de Recherche en Informatique
00002 
00003 // This file is part of Qolyester.
00004 
00005 // Qolyester is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 
00010 // Qolyester is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018 
00019 #ifndef QOLYESTER_DAEMON_ALG_DIJKSTRA_HXX
00020 # define QOLYESTER_DAEMON_ALG_DIJKSTRA_HXX 1
00021 
00022 # include <ext/hash_map>
00023 
00024 # include "gra/graph.hh"
00025 # include "net/ipaddress.hh"
00026 # include "utl/comparator.hh"
00027 # include "utl/log.hh"
00028 
00029 # include "dijkstra.hh"
00030 
00031 namespace olsr {
00032 
00033   extern debug_ostream_t        debug;
00034   extern gra::AdjGraph          path_net;
00035 
00036   namespace alg {
00037     // Declarations of the two dijkstra data structures.  nextmap_t
00038     // maps node addresses into addresses of the next node towards the
00039     // first node.  hopsmap_t maps node addresses into the actual
00040     // number of hops.  Infinite number of hops is reprensented by the
00041     // absence of a node in the hopsmap.
00042     typedef std::hash_map<address_t, unsigned>  weightmap_t;
00043     typedef std::hash_map<address_t, address_t> nextmap_t;
00044     typedef std::hash_map<address_t, unsigned>  hopsmap_t;
00045 
00046     // Sorting comparator of the nodes remaining to be processed.
00047     struct sort_less {
00048       // We need to pass a reference to the instance of hopsmap_t to
00049       // use.
00050       sort_less(const hopsmap_t& hm,
00051                 const weightmap_t& wm)
00052         : _hm(hm),
00053           _wm(wm)
00054       {}
00055 
00056       bool operator()(const gra::AdjNode* a, const gra::AdjNode* b) const {
00057         // Get the number of hops towards each of the nodes.
00058         weightmap_t::const_iterator     wa = _wm.find(a->endpoint());
00059         weightmap_t::const_iterator     wb = _wm.find(b->endpoint());
00060 
00061         hopsmap_t::const_iterator     ha = _hm.find(a->endpoint());
00062         hopsmap_t::const_iterator     hb = _hm.find(b->endpoint());
00063 
00064         // If both of the nodes are at infinite number of hops, order
00065         // simply by node address.  If only one of the two is at
00066         // infinity, make it greater than the other.
00067         if (wb == _wm.end())
00068           if (wa == _wm.end())
00069             return a->endpoint() < b->endpoint();
00070           else
00071             return true;
00072 
00073         if (wa == _wm.end())
00074           return false;
00075 
00076         if (wa->second > wb->second)
00077           return true;
00078         else if (wa->second < wb->second)
00079           return false;
00080 
00081         if (hb == _hm.end())
00082           if (ha == _hm.end())
00083             return a->endpoint() < b->endpoint();
00084           else
00085             return true;
00086 
00087         if (ha == _hm.end())
00088           return false;
00089 
00090         // From now on, we know that both nodes are not at infinity.
00091 
00092         // Order the nodes primary by number of hops.
00093         if (ha->second < hb->second)
00094           return true;
00095         else if (hb->second < ha->second)
00096           return false;
00097 
00098         // Order the nodes secondary by weight.
00099         if (b->weight() < a->weight())
00100           return true;
00101         else if (a->weight() < b->weight())
00102           return false;
00103 
00104         // Last, order the nodes by address.
00105         return a->endpoint() < b->endpoint();
00106       }
00107     private:
00108       const hopsmap_t&          _hm;
00109       const weightmap_t&        _wm;
00110     };
00111 
00112     // Declaration of the node hash set type.
00113     typedef std::hash_set<const gra::AdjNode*,
00114                           gra::hash_AdjNode,
00115                           utl::pequal_to<gra::AdjNode> >        npset_t;
00116 
00117     // Declaration of the remaining node set type.
00118     typedef std::set<const gra::AdjNode*, sort_less>    sortremaining_t;
00119 
00120     // The Dijkstra algorithm.  The first argument is a reference to
00121     // the route set to be filled and the second argument is the set
00122     // of source nodes addresses.
00123     void        dijkstra(rrouteset_t& routes,
00124                          std::map<address_t, address_t>& sources_map) {
00125       nextmap_t         next_map;
00126       hopsmap_t         hops_map;
00127       weightmap_t       weight_map;
00128 
00129       debug << path_net << std::endl;
00130 
00131       npset_t   rem;
00132 
00133       // Insert all the nodes of the graph into the remaining set.
00134       for (gra::nodeset_t::const_iterator n = path_net.nodes().begin();
00135            n != path_net.nodes().end(); ++n)
00136         rem.insert(&*n);
00137 
00138       debug << "dijkstra {\n";
00139 
00140       // Initialize the hops and next map, by inserting the source
00141       // nodes.
00142       debug << "  sources {";
00143       for (std::map<address_t, address_t>::const_iterator s =
00144              sources_map.begin();
00145            s != sources_map.end(); ++s) {
00146         pathnet_t::nset_t::const_iterator       n =
00147           path_net.nodes().find(gra::AdjNode::make_key(s->first));
00148         assert(n != path_net.nodes().end());
00149         debug << " " << s->first;
00150         next_map[s->first] = s->first;
00151         hops_map[s->first] = 0;
00152         weight_map[s->first] = n->weight();
00153       }
00154       debug << " }\n";
00155 
00156       // Loop while there are remaining nodes to be reached.
00157       while (!hops_map.empty()) {
00158         assert(!rem.empty());
00159 
00160         // Populate the sorted remaining set.
00161         sortremaining_t srem(rem.begin(), rem.end(),
00162                              sort_less(hops_map, weight_map));
00163 
00164         debug << "  round {\n";
00165         for (sortremaining_t::const_iterator i = srem.begin();
00166              i != srem.end(); ++i) {
00167           debug << "    " << (*i)->endpoint() << " ";
00168           nextmap_t::const_iterator n = next_map.find((*i)->endpoint());
00169           hopsmap_t::const_iterator h = hops_map.find((*i)->endpoint());
00170           weightmap_t::const_iterator w = weight_map.find((*i)->endpoint());
00171           if (n == next_map.end())
00172             debug << "_ ";
00173           else
00174             debug << next_map[(*i)->endpoint()] << " ";
00175           if (h == hops_map.end())
00176             debug << "_ ";
00177           else
00178             debug << h->second << " ";
00179           if (w == weight_map.end())
00180             debug << "_\n";
00181           else
00182             debug << w->second << "\n";
00183         }
00184         debug << "  }" << std::endl;
00185 
00186         // The first node (in iteration order) in the sorted remaining
00187         // set is the node that is to be added next to the reached
00188         // set.
00189         const gra::AdjNode&     closest = **srem.begin();
00190 
00191         // Remove the node from the remaining set.
00192         rem.erase(&closest);
00193         srem.erase(&closest);
00194 
00195         // Get new hop count and next node address for relaxation.
00196 
00197         hopsmap_t::iterator     hops = hops_map.find(closest.endpoint());
00198         nextmap_t::iterator     next = next_map.find(closest.endpoint());
00199         weightmap_t::iterator   weight = weight_map.find(closest.endpoint());
00200 
00201         if (hops == hops_map.end() ||
00202             next == next_map.end() ||
00203             weight == weight_map.end())
00204           break; // We are now considering an unreachable node, stop here.
00205 
00206         unsigned        next_hops = hops->second + 1;
00207 
00208         // Remove the node from the hops map.
00209         hops_map.erase(hops);
00210         weight_map.erase(weight);
00211 
00212         if (closest.weight() == 0)
00213           continue;
00214 
00215         // The relaxation /per se/
00216 
00217         // Iterate on the node set.
00218         for (npset_t::const_iterator n = rem.begin(); n != rem.end(); ++n) {
00219           // Consider only the nodes that are adjacent to the current
00220           // node.
00221           pathnet_t::aset_t::const_iterator     a =
00222             path_net.arcs().find(gra::AdjInfo::make_key(closest.endpoint(),
00223                                                         (*n)->endpoint(),
00224                                                         topo));
00225           // The following case is put to allow the use of 2-hop
00226           // neighbors information on the condition that the 1-hop
00227           // neighbor is symmetric, i.e. it is one of the source
00228           // nodes.
00229           if (a == path_net.arcs().end() &&
00230               sources_map.find(closest.endpoint()) != sources_map.end())
00231             a = path_net.arcs().find(gra::AdjInfo::make_key(closest.endpoint(),
00232                                                             (*n)->endpoint(),
00233                                                             twohop));
00234 
00235           if (a != path_net.arcs().end()) {
00236             // Get the hops map entry and update it, along with the
00237             // next map entry.
00238             unsigned                    next_weight = MAX(weight->second,
00239                                                           (*n)->weight());
00240             //        weight->second + a->weight();
00241             hopsmap_t::iterator         h = hops_map.find((*n)->endpoint());
00242             weightmap_t::iterator       w = weight_map.find((*n)->endpoint());
00243             if (((w == weight_map.end() || w->second <= next_weight) &&
00244                  (h == hops_map.end() || h->second > next_hops)) ||
00245                 ((w == weight_map.end() || w->second < next_weight) &&
00246                  (h == hops_map.end() || h->second >= next_hops))) {
00247               weight_map[(*n)->endpoint()] = next_weight;
00248               hops_map[(*n)->endpoint()] = next_hops;
00249               next_map[(*n)->endpoint()] = next->second;
00250             }
00251           }
00252         }
00253       }
00254 
00255       // Remove the source nodes from the next map.
00256       for (std::map<address_t, address_t>::const_iterator s =
00257              sources_map.begin();
00258            s != sources_map.end(); ++s)
00259         next_map.erase(s->first);
00260 
00261       // Build the route set based on the next map.
00262       for (nextmap_t::const_iterator i = next_map.begin();
00263            i != next_map.end(); ++i) {
00264         debug << "  route { " << i->first << " : " << i->second << " }\n";
00265 
00266         std::map<address_t, address_t>::iterator        m =
00267           sources_map.find(i->second);
00268         if (m != sources_map.end())
00269           routes.insert(net::RemoteRoute(i->first, ADDRESS_SIZE * 8,
00270                                          m->second));
00271         else
00272           routes.insert(net::RemoteRoute(i->first, ADDRESS_SIZE * 8,
00273                                          i->second));
00274       }
00275 
00276       debug << "}" << std::endl;;
00277     }
00278 
00279   } // namespace alg
00280 
00281 } // namespace olsr
00282 
00283 #endif // !QOLYESTER_DAEMON_ALG_DIJKSTRA_HXX

Generated on Thu Jul 28 21:21:46 2005 for Qolyester daemon by  doxygen 1.4.1