Wiselib
wiselib.testing/algorithms/topology/flss/flss_topology_control.h
Go to the documentation of this file.
00001 /***************************************************************************
00002  ** This file is part of the generic algorithm library Wiselib.           **
00003  ** Copyright (C) 2008,2009 by the Wisebed (www.wisebed.eu) project.      **
00004  **                                                                       **
00005  ** The Wiselib is free software: you can redistribute it and/or modify   **
00006  ** it under the terms of the GNU Lesser General Public License as        **
00007  ** published by the Free Software Foundation, either version 3 of the    **
00008  ** License, or (at your option) any later version.                       **
00009  **                                                                       **
00010  ** The Wiselib 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 Lesser General Public License for more details.                   **
00014  **                                                                       **
00015  ** You should have received a copy of the GNU Lesser General Public      **
00016  ** License along with the Wiselib.                                       **
00017  ** If not, see <http://www.gnu.org/licenses/>.                           **
00018  **                                                                       **
00019  ** Author: Víctor López Ferrando, victorlopez90@gmail.com                **
00020  ***************************************************************************/
00021 #ifndef __ALGORITHMS_TOPOLOGY_FLSS_TOPOLOGY_H__
00022 #define __ALGORITHMS_TOPOLOGY_FLSS_TOPOLOGY_H__
00023 
00024 #include "algorithms/topology/lmst/lmst_topology_message.h"
00025 #include "algorithms/topology/topology_control_base.h"
00026 #include "util/pstl/priority_queue.h"
00027 #include "util/pstl/vector_static.h"
00028 #include "util/pstl/pair.h"
00029 #include <queue> // TODO: use pSTL queue
00030 #include <limits>
00031 
00032 
00033 #define DEBUG_FLSS_TOPOLOGY
00034 
00035 namespace wiselib
00036 {
00037 
00043    template<typename OsModel_P,
00044             uint16_t K,
00045             typename Localization_P,
00046             uint16_t MAX_NODES,
00047             typename Radio_P = typename OsModel_P::Radio,
00048             typename Timer_P = typename OsModel_P::Timer>
00049    class FlssTopology :
00050       public TopologyBase<OsModel_P>
00051    {
00052    public:
00053       typedef OsModel_P OsModel;
00054       typedef Localization_P Localization;
00055       typedef Radio_P Radio;
00056       typedef Timer_P Timer;
00057       typedef typename Localization::float_t float_t;
00058 
00059 #ifdef DEBUG_FLSS_TOPOLOGY
00060       typedef typename OsModel::Debug Debug;
00061 #endif
00062 
00063       typedef FlssTopology<OsModel_P, K, Localization_P, MAX_NODES, Radio_P, Timer_P> self_type;
00064       typedef LmstTopologyMessage<OsModel, Radio, float_t> TopologyMessage;
00065 
00066       typedef typename Localization::position_t Position;
00067 
00068       typedef typename Radio::node_id_t node_id_t;
00069       typedef typename Radio::size_t size_t;
00070       typedef typename Radio::block_data_t block_data_t;
00071 
00072       typedef typename Timer::millis_t millis_t;
00073 
00074       typedef pair<float_t, node_id_t> PPI;
00075       typedef vector_static<OsModel, node_id_t, MAX_NODES> Neighbors;
00076       static const uint8_t POSITION_SIZE = sizeof( Position );
00077 
00080       FlssTopology();
00081       ~FlssTopology();
00083 
00086       void enable( void );
00087       void disable( void );
00089 
00092       void timer_elapsed( void *userdata );
00094 
00097       void receive( node_id_t from, size_t len, block_data_t *data );
00099 
00100       inline void set_startup_time( millis_t startup_time )
00101       { startup_time_ = startup_time; };
00102 
00103       inline void set_work_period( millis_t work_period )
00104       { work_period_ = work_period; };
00105 
00106       Neighbors &topology() {
00107         return N;
00108       }
00109 
00110       float_t range_assignment() {
00111         return radius_;
00112       }
00113       
00114       void init( Radio& radio, Timer& timer, Debug& debug ) {
00115          radio_ = &radio;
00116          timer_ = &timer;
00117          debug_ = &debug;
00118       }
00119       
00120       void destruct() {
00121       }
00122 
00123    private:
00124 
00125       Radio& radio()
00126       { return *radio_; }
00127       
00128       Timer& timer()
00129       { return *timer_; }
00130       
00131       Debug& debug()
00132       { return *debug_; }
00133      
00134       Radio * radio_;
00135       Timer * timer_;
00136       Debug * debug_;
00137      
00140       enum FlssTopologyMsgIds {
00141          LtMsgIdBroadcastPosition = 200, 
00142          LtMsgIdNeighbourNotification = 201, 
00143       };
00144 
00147       Neighbors N; // Topology
00148       float_t radius_;
00150 
00151       millis_t startup_time_;
00152       millis_t work_period_;
00153 
00154       TopologyMessage positionMessage;
00155       uint8_t neighbourMessage;
00156 
00157       void generate_topology();
00158       int16_t max_flow(node_id_t source, node_id_t sink);
00159       int16_t find_path_bfs(node_id_t source, node_id_t sink);
00160       
00161       int n;
00162       const static int32_t inf = 2000000000;
00163       
00164       Localization localization_;
00165       
00166       typedef pair<int, int> PII;
00167       vector_static<OsModel, bool, MAX_NODES> seen;
00168       vector_static<OsModel, node_id_t, MAX_NODES> from;
00169       vector_static<OsModel, node_id_t, MAX_NODES> NV;
00170       vector_static<OsModel, Position, MAX_NODES> Pos;
00171       vector_static<OsModel, vector_static<OsModel, uint8_t, MAX_NODES>, MAX_NODES> capacity;
00172       vector_static<OsModel, vector_static<OsModel, node_id_t, MAX_NODES>, MAX_NODES> G;
00173       vector_static<OsModel, vector_static<OsModel, uint8_t, MAX_NODES>, MAX_NODES> capacity_bak;
00174       vector_static<OsModel, vector_static<OsModel, node_id_t, MAX_NODES>, MAX_NODES> G_bak;
00175       priority_queue< OsModel, pair<float_t, PII >, MAX_NODES*10 > E;
00176       std::queue<node_id_t> Q;
00177 
00178    };
00179    // -----------------------------------------------------------------------
00180    // -----------------------------------------------------------------------
00181    // -----------------------------------------------------------------------
00182    template<typename OsModel_P,
00183             uint16_t K,
00184             typename Localization_P,
00185             uint16_t MAX_NODES,
00186             typename Radio_P,
00187             typename Timer_P>
00188    FlssTopology<OsModel_P, K, Localization_P, MAX_NODES, Radio_P, Timer_P>::
00189    FlssTopology()
00190       : os_          ( 0 ),
00191       startup_time_ ( 2000 ),
00192       work_period_ ( 5000 ),
00193       positionMessage( LtMsgIdBroadcastPosition ),
00194       neighbourMessage( LtMsgIdNeighbourNotification )
00195    {};
00196    // -----------------------------------------------------------------------
00197    template<typename OsModel_P,
00198             uint16_t K,
00199             typename Localization_P,
00200             uint16_t MAX_NODES,
00201             typename Radio_P,
00202             typename Timer_P>
00203    FlssTopology<OsModel_P, K, Localization_P, MAX_NODES, Radio_P, Timer_P>::
00204    ~FlssTopology()
00205    {
00206 #ifdef DEBUG_FLSS_TOPOLOGY
00207       debug().debug( "%i: FlssTopology Destroyed\n", radio().id() );
00208 #endif
00209    };
00210    // -----------------------------------------------------------------------
00211    template<typename OsModel_P,
00212             uint16_t K,
00213             typename Localization_P,
00214             uint16_t MAX_NODES,
00215             typename Radio_P,
00216             typename Timer_P>
00217    void
00218    FlssTopology<OsModel_P, K, Localization_P, MAX_NODES, Radio_P, Timer_P>::
00219    enable( void )
00220    {
00221       radio().enable_radio();
00222 #ifdef DEBUG_FLSS_TOPOLOGY
00223       debug().debug( "%i: FlssTopology Boots\n", radio().id() );
00224 #endif
00225       radio().template reg_recv_callback<self_type, &self_type::receive>(
00226                                  this );
00227       timer().template set_timer<self_type, &self_type::timer_elapsed>(
00228                                  startup_time_, this, 0 );
00229 #ifdef DEBUG_FLSS_TOPOLOGY
00230       debug().debug( "%i: FlssTopology Enables Localization\n",
00231                     radio().id() );
00232 #endif
00233       localization_.enable();
00234    }
00235    // -----------------------------------------------------------------------
00236    template<typename OsModel_P,
00237             uint16_t K,
00238             typename Localization_P,
00239             uint16_t MAX_NODES,
00240             typename Radio_P,
00241             typename Timer_P>
00242    void
00243    FlssTopology<OsModel_P, K, Localization_P, MAX_NODES, Radio_P, Timer_P>::
00244    disable( void )
00245    {
00246 #ifdef DEBUG_FLSS_TOPOLOGY
00247       debug().debug( "%i: Called FlssTopology::disable\n", radio().id() );
00248 #endif
00249       localization_.disable();
00250    }
00251    // -----------------------------------------------------------------------
00252    template<typename OsModel_P,
00253             uint16_t K,
00254             typename Localization_P,
00255             uint16_t MAX_NODES,
00256             typename Radio_P,
00257             typename Timer_P>
00258    void
00259    FlssTopology<OsModel_P, K, Localization_P, MAX_NODES, Radio_P, Timer_P>::
00260    timer_elapsed( void* userdata )
00261    {
00262 #ifdef DEBUG_FLSS_TOPOLOGY
00263       debug().debug( "%i: Executing TimerElapsed 'FlssTopology'\n",
00264                     radio().id()  );
00265 #endif
00266 
00267 #ifdef DEBUG_FLSS_TOPOLOGY
00268       debug().debug( "%i: Generating topology\n",
00269                     radio().id()  );
00270 #endif
00271       generate_topology();
00272       TopologyBase<OsModel>::notify_listeners();
00273       for ( size_t i = 0; i < N.size(); ++i )
00274          radio().send( N[i], 1, (uint8_t*)&neighbourMessage );
00275       Position pos = localization_.position();
00276 #ifdef DEBUG_FLSS_TOPOLOGY
00277       debug().debug( "%i: Broadcasting position (%f, %f, %f)\n",
00278                     radio().id(), pos.x, pos.y, pos.z );
00279 #endif
00280       positionMessage.set_position( pos );
00281       radio().send( radio().BROADCAST_ADDRESS, 1 + POSITION_SIZE, (uint8_t*)&positionMessage );
00282 
00283       timer().template set_timer<self_type, &self_type::timer_elapsed>(
00284                                  work_period_, this, 0 );
00285    }
00286    // -----------------------------------------------------------------------
00287    template<typename OsModel_P,
00288             uint16_t K,
00289             typename Localization_P,
00290             uint16_t MAX_NODES,
00291             typename Radio_P,
00292             typename Timer_P>
00293    void
00294    FlssTopology<OsModel_P, K, Localization_P, MAX_NODES, Radio_P, Timer_P>::
00295    receive( node_id_t from, size_t len, block_data_t *data )
00296    {
00297       if ( from == radio().id() )
00298          return;
00299 
00300       uint8_t msg_id = *data;
00301       if ( msg_id == LtMsgIdBroadcastPosition )
00302       {
00303          TopologyMessage *msg = (TopologyMessage *)data;
00304          Position pos = msg->position();
00305 #ifdef DEBUG_FLSS_TOPOLOGY
00306          debug().debug( "%i: Received position msg from %i: (%f, %f, %f)\n",
00307                         radio().id(), from, pos.x, pos.y, pos.z );
00308 #endif
00309          NV.push_back( from );
00310          Pos.push_back( pos );
00311       }
00312       else if ( msg_id == LtMsgIdNeighbourNotification )
00313       {
00314 #ifdef DEBUG_FLSS_TOPOLOGY
00315          debug().debug( "%i: Received neighbourhood message from %i\n",
00316                        radio().id(), from );
00317 #endif
00318          size_t i = 0;
00319          while ( i < N.size() && N[i] != from )
00320             ++i;
00321          if ( i == N.size() )
00322          {
00323 #ifdef DEBUG_FLSS_TOPOLOGY
00324             debug().debug( "%i: Added node %i in N because I didn't have it\n",
00325                           radio().id(), from );
00326 #endif
00327             N.push_back( from );
00328          }
00329       }
00330    }
00331    // -----------------------------------------------------------------------
00332    template<typename OsModel_P,
00333             uint16_t K,
00334             typename Localization_P,
00335             uint16_t MAX_NODES,
00336             typename Radio_P,
00337             typename Timer_P>
00338    void
00339    FlssTopology<OsModel_P, K, Localization_P, MAX_NODES, Radio_P, Timer_P>::
00340    generate_topology()
00341    {
00342       // Generalized Kruskal algorithm to get the minimum spanning K-connected graph
00343       // Ford-fulkerson algorithm used to check K-connection
00344       E.clear();
00345       // Afegim l'arrel als veinss
00346       NV.push_back( radio().id() );
00347       n = NV.size();
00348       // Generem el graf i omplim la PQ amb arestes
00349       for (int i = 0; i < n; ++i)
00350          for (int j = i+1; j < n; ++j) {
00351             capacity[2*i][2*i+1] = 1;
00352             capacity[2*i+1][2*j] = 0;
00353             capacity[2*j+1][2*i] = 0;
00354             E.push(pair<float_t, PII >(dist(Pos[i], Pos[j]), PII(2*i+1,  2*j)));
00355          }
00356       for (int i=0; i<n; ++i)
00357          for (int j=0; j<n; ++j)
00358             if (capacity[i][j] > 0)
00359                G[i].push_back(j);
00360       G_bak = G;
00361       capacity_bak = capacity;
00362       for (int i = 0; i < E.size(); ++i) {
00363          if (max_flow(E.top().second.first, E.top().second.second) < K) {
00364             G[E.top().second.first][E.top().second.second] = true;
00365             G[E.top().second.second+1][E.top().second.first-1] = true;
00366          }
00367          bool finish = true;
00368          for (int i = 0; i < n-1; ++i)
00369             if (max_flow(2*i+1, 2*n-1) < K)
00370                finish = false;
00371          if (finish)
00372             break;
00373       }
00374       N.clear();
00375       for (int i = 0; i < n-1; ++i)
00376          if (G[2*i+1][2*n-2])
00377             N.push_back(i);
00378       NV.clear();
00379       Pos.clear();
00380    }
00381    // -----------------------------------------------------------------------
00382    template<typename OsModel_P,
00383             uint16_t K,
00384             typename Localization_P,
00385             uint16_t MAX_NODES,
00386             typename Radio_P,
00387             typename Timer_P>
00388    int16_t
00389    FlssTopology<OsModel_P, K, Localization_P, MAX_NODES, Radio_P, Timer_P>::
00390    max_flow(node_id_t source, node_id_t sink)
00391    {
00392       G = G_bak;
00393       capacity = capacity_bak;
00394       int16_t sol = 0;
00395       while (true) {
00396          int16_t path_capacity = find_path_bfs(source, sink);
00397          if (path_capacity == 0)
00398             break;
00399          else
00400             sol += path_capacity;
00401       }
00402       return sol;
00403    }
00404    // -----------------------------------------------------------------------
00405    template<typename OsModel_P,
00406             uint16_t K,
00407             typename Localization_P,
00408             uint16_t MAX_NODES,
00409             typename Radio_P,
00410             typename Timer_P>
00411    int16_t
00412    FlssTopology<OsModel_P, K, Localization_P, MAX_NODES, Radio_P, Timer_P>::
00413    find_path_bfs(node_id_t source, node_id_t sink)
00414    {
00415       for (int i = 0; i < n; ++i)
00416          seen[i] = false;
00417       for (int i = 0; i < n; ++i)
00418          from[i] = -1;
00419       Q = std::queue<node_id_t>();
00420       Q.push(source);
00421       seen[source] = true;
00422       while (not Q.empty()) {
00423          node_id_t where = Q.front();
00424          Q.pop();
00425          bool finish = false;
00426          for (int i = 0; i < G[where].size(); ++i)
00427             if ( not seen[G[where][i]] and capacity[where][G[where][i]] > 0 ) {
00428             Q.push(G[where][i]);
00429             seen[G[where][i]] = true;
00430             from[G[where][i]] = where;
00431             if (G[where][i] == sink) {
00432                finish = true;
00433                break;
00434             }
00435          }
00436          if (finish)
00437             break;
00438       }
00439       node_id_t where = sink, path_cap = inf;
00440       while (from[where] > -1) {
00441          node_id_t prev = from[where];
00442          path_cap = (path_cap < capacity[prev][where] ? path_cap : capacity[prev][where]);
00443          where = prev;
00444       }
00445       where = sink;
00446       while (from[where] > -1) {
00447          node_id_t prev = from[where];
00448          capacity[prev][where] -= path_cap;
00449          where = prev;
00450       }
00451       if (path_cap == inf)
00452          return 0;
00453       else
00454          return path_cap;
00455    }
00456 }
00457 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines