Wiselib
wiselib.testing/algorithms/energy_preservation/ants_duty_cycling/ant_hallway_duty_cycling_algorithm.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 #ifndef __ANTS_HALLWAY_DUTY_CYCLING_ALGORITHM_H__
00020 #define __ANTS_HALLWAY_DUTY_CYCLING_ALGORITHM_H__
00021 
00022 #include "algorithms/energy_preservation/ants_duty_cycling/ants_duty_cycling_message.h"
00023 #include "util/pstl/pair.h"
00024 #include "util/pstl/list_static.h"
00025 #include "util/delegates/delegate.hpp"
00026 
00027 // TODO: change shawn os()-> calls to wiselib calls
00028 
00029 //TODO: REMOVE!!!!!!!
00030 #include "sys/processor.h"
00031 #include "sys/event_scheduler.h"
00032 #include "sys/misc/random/random_variable.h"
00033 #include "sys/misc/random/random_variable_keeper.h"
00034 #include "sys/node.h"
00035 #include "sys/simulation/simulation_controller.h"
00036 #include "sys/simulation/simulation_environment.h"
00037 #include "sys/taggings/basic_tags.h"
00038 #include "sys/tag.h"
00039 #include "sys/comm_models/disk_graph_model.h"
00040 
00041 // #define ANTS_HALLWAY_DUTY_CYCLING_DEBUG
00042 
00043 namespace wiselib
00044 {
00045 
00048    template<typename OsModel_P,
00049             typename Radio_P,
00050             typename Timer_P,
00051             typename Clock_P,
00052             typename Debug_P = typename OsModel_P::Debug>
00053    class AntsDutyCyclingAlgorithm
00054    {
00055    public:
00056       typedef OsModel_P OsModel;
00057       typedef Radio_P Radio;
00058       typedef Timer_P Timer;
00059       typedef Clock_P Clock;
00060       typedef Debug_P Debug;
00061 
00062       typedef AntsDutyCyclingAlgorithm<OsModel, Radio, Timer, Clock, Debug> self_type;
00063 
00064       typedef typename Radio::node_id_t node_id_t;
00065       typedef typename Radio::size_t size_t;
00066       typedef typename Radio::block_data_t block_data_t;
00067       typedef typename Radio::message_id_t message_id_t;
00068 
00069       typedef pair<int, typename Clock::time_t> Event;
00070       typedef list_static<OsModel, Event, 50> EventList;
00071       typedef typename EventList::iterator EventListIterator;
00072 
00073       typedef typename Clock::time_t time_t;
00074 
00075       typedef AntDutyCyclingMessage<OsModel, Radio> Message;
00076 
00077       typedef delegate1<void, int> energy_preservation_delegate_t;
00078       // --------------------------------------------------------------------
00079       enum ErrorCodes
00080       {
00081          SUCCESS = OsModel::SUCCESS,
00082          ERR_UNSPEC = OsModel::ERR_UNSPEC,
00083          ERR_NOTIMPL = OsModel::ERR_NOTIMPL
00084       };
00085       // --------------------------------------------------------------------
00086       enum EnergyPreservationActivity
00087       {
00088          EPA_ACTIVE = 1,
00089          EPA_INACTIVE
00090       };
00091       // --------------------------------------------------------------------
00094       AntsDutyCyclingAlgorithm();
00095       ~AntsDutyCyclingAlgorithm();
00097       // --------------------------------------------------------------------
00101       void enable( void );
00103       void disable( void );
00104 // TODO
00105 #ifdef SHAWN
00106       void set_configuration( shawn::Node* node );
00107 #endif
00108 
00109       // --------------------------------------------------------------------
00112       // --------------------------------------------------------------------
00113       template<class T, void (T::*TMethod)(int)>
00114       inline int reg_changed_callback( T *obj_pnt )
00115       {
00116          callback_ = energy_preservation_delegate_t::from_method<T, TMethod>( obj_pnt );
00117          return 0;
00118       }
00119       // --------------------------------------------------------------------
00120       inline int unreg_changed_callback( int )
00121       {
00122          callback_ = energy_preservation_delegate_t();
00123          return SUCCESS;
00124       }
00125       // --------------------------------------------------------------------
00126       inline void notify_receivers( EnergyPreservationActivity value )
00127       {
00128          if (callback_)
00129             callback_( value );
00130       }
00132       // --------------------------------------------------------------------
00135       void receive( node_id_t from, size_t len, block_data_t *data );
00137       // --------------------------------------------------------------------
00140       void enable_transmission_phase( void *userdata );
00141       void algorithm_step( void *userdata );
00142       void disable_transmission_phase( void *userdata );
00144       // --------------------------------------------------------------------
00145       inline double activity()
00146       { return S_; }
00147       // --------------------------------------------------------------------
00148       inline double battery()
00149       {
00150          return battery_;
00151       }
00152       // --------------------------------------------------------------------
00153       inline void set_battery( double battery )
00154       {
00155          if ( battery < 0.0 )
00156              battery = 0.0;
00157          if ( battery > 1.0 )
00158              battery = 1.0;
00159          battery_ = battery;
00160       }
00161       // --------------------------------------------------------------------
00162       inline bool active()
00163       { return active_; }
00164       // --------------------------------------------------------------------
00165       int init( Radio& radio, Timer& timer, Clock& clock, Debug& debug )
00166       {
00167          radio_ = &radio;
00168          timer_ = &timer;
00169          clock_ = &clock;
00170          debug_ = &debug;
00171          return SUCCESS;
00172       }
00173       // --------------------------------------------------------------------
00174       int init()
00175       {
00176          enable();
00177          return SUCCESS;
00178       }
00179       // --------------------------------------------------------------------
00180       int destruct()
00181       {
00182          disable();
00183          return SUCCESS;
00184       }
00185       // --------------------------------------------------------------------
00186       void event_triggered( int events );
00187 
00188    private:
00189       Radio& radio()
00190       { return *radio_; }
00191       // --------------------------------------------------------------------
00192       Timer& timer()
00193       { return *timer_; }
00194       // --------------------------------------------------------------------
00195       Clock& clock()
00196       { return *clock_; }
00197       // --------------------------------------------------------------------
00198       Debug& debug()
00199       { return *debug_; }
00200       // --------------------------------------------------------------------
00201       typename Radio::self_pointer_t radio_;
00202       typename Timer::self_pointer_t timer_;
00203       typename Clock::self_pointer_t clock_;
00204       typename Debug::self_pointer_t debug_;
00205       // --------------------------------------------------------------------
00206       void update_active_state();
00207       void try_spontaneous_awakening();
00208       void update_radius();
00209       void update_probability_awakening( int events );
00210       void update_actvity();
00211       // --------------------------------------------------------------------
00212       enum MessageIds
00213       {
00214          ANTS_DUTY_CYCLING_MESSAGE_ID = 148
00215       };
00216       // --------------------------------------------------------------------
00217       energy_preservation_delegate_t callback_;
00218 
00219       double battery_;
00220       bool active_;
00221       double radius_;
00222       double transmission_range_;
00223       double application_consumption_;
00224       time_t last_time_;
00225 
00226       double S_, h_, f_;
00227 
00228       double energy_consumption_awake_, energy_consumption_sleep_;
00229       double activation_threshold_;
00230       double probability_awakening_;
00231       double probability_awakening_min_, probability_awakening_max_;
00232       double spontaneous_awakening_activity_level_;
00233       double radius_min_, radius_max_;
00234       double g_;
00235       double cloud_;
00236 
00237       double time_step_;
00238       typename Clock::time_t event_storage_time_;
00239       double event_denominator_;
00240 
00241       // TODO
00242       shawn::Node *node_;
00243       shawn::ConstRandomVariableHandle time_step_rnd_;
00244       shawn::ConstRandomVariableHandle uni_rnd_;
00245 
00246       EventList event_list_;
00247    };
00248    // -----------------------------------------------------------------------
00249    // -----------------------------------------------------------------------
00250    // -----------------------------------------------------------------------
00251    template<typename OsModel_P,
00252             typename Radio_P,
00253             typename Timer_P,
00254             typename Clock_P,
00255             typename Debug_P>
00256    AntsDutyCyclingAlgorithm<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P>::
00257    AntsDutyCyclingAlgorithm()
00258       : callback_  ( energy_preservation_delegate_t() ),
00259          battery_   ( 1.0 ),
00260          active_    ( true ),
00261          radius_    ( 0.8 ),
00262          transmission_range_ ( 1.0 ),
00263          application_consumption_ ( 0.001 ),
00264          last_time_ ( time_t() ),
00265          S_         ( 0 ),
00266          h_         ( 0 ),
00267          f_         ( 0.0027 ),
00268          event_storage_time_ ( 2 ),
00269          event_denominator_ (100)
00270    {
00271       // TODO!
00272       node_ = 0;
00273    };
00274    // -----------------------------------------------------------------------
00275    template<typename OsModel_P,
00276             typename Radio_P,
00277             typename Timer_P,
00278             typename Clock_P,
00279             typename Debug_P>
00280    AntsDutyCyclingAlgorithm<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P>::
00281    ~AntsDutyCyclingAlgorithm()
00282    {
00283 #ifdef ANTS_DUTY_CYCLING_DEBUG
00284       debug().debug( "AntsDutyCyclingAlgorithm:dtor\n" );
00285 #endif
00286    };
00287    // -----------------------------------------------------------------------
00288    template<typename OsModel_P,
00289             typename Radio_P,
00290             typename Timer_P,
00291             typename Clock_P,
00292             typename Debug_P>
00293    void
00294    AntsDutyCyclingAlgorithm<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P>::
00295    enable( void )
00296    {
00297 #ifdef ANTS_DUTY_CYCLING_DEBUG
00298       debug().debug( "AntsDutyCyclingAlgorithm: Boot for %i\n", radio().id(  ) );
00299 #endif
00300 
00301       // TODO:
00302       node_->template write_simple_tag<double>( "battery", 1.0 );
00303       node_->template write_simple_tag<double>( "consumed-app", 0.0 );
00304       node_->template write_simple_tag<double>( "consumed-rx", 0.0 );
00305       node_->template write_simple_tag<double>( "consumed-tx", 0.0 );
00306       node_->template write_simple_tag<double>( "consumed-idle", 0.0 );
00307       node_->template write_simple_tag<double>( "consumed-active", 0.0 );
00308 
00309       radio().enable_radio(  );
00310       radio().template reg_recv_callback<self_type, &self_type::receive>( this );
00311 
00312       active_ = true;
00313       notify_receivers( EPA_ACTIVE );
00314       // FIXME
00315 //       radio().set_app_active( active_ );
00316 
00317       last_time_ = clock().time( );
00318 
00319       time_t next_step = 1 - (clock().time( ) - (int)clock().time(  ));
00320       timer().template set_timer<self_type, &self_type::enable_transmission_phase>( int(next_step * 1000), this, 0 );
00321    }
00322    // -----------------------------------------------------------------------
00323    template<typename OsModel_P,
00324             typename Radio_P,
00325             typename Timer_P,
00326             typename Clock_P,
00327             typename Debug_P>
00328    void
00329    AntsDutyCyclingAlgorithm<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P>::
00330    disable( void )
00331    {
00332 #ifdef ANTS_DUTY_CYCLING_DEBUG
00333       debug().debug(  "AntsDutyCyclingAlgorithm: Disable\n" );
00334 #endif
00335 // TODO
00336 //       radio().unreg_recv_callback(  callback_id_ );
00337       radio().disable(  );
00338    }
00339    // -----------------------------------------------------------------------
00340 // TODO
00341 #ifdef SHAWN
00342    template<typename OsModel_P,
00343             typename Radio_P,
00344             typename Timer_P,
00345             typename Clock_P,
00346             typename Debug_P>
00347    void
00348    AntsDutyCyclingAlgorithm<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P>::
00349    set_configuration( shawn::Node* node )
00350    {
00351       node_ = node;
00352       const shawn::SimulationEnvironment& se = node_->world().simulation_controller().environment();
00353 
00354       uni_rnd_ = node_->world().simulation_controller().
00355                       random_variable_keeper().find( "uni[0;1]" );
00356 
00357       // TODO
00358       std::string time_step_prob = se.required_string_param( "time_step_prob" );
00359       time_step_rnd_ = node_->world().simulation_controller().
00360                      random_variable_keeper().find( time_step_prob );
00361       time_step_ = *time_step_rnd_;
00362 
00363       // TODO
00364       energy_consumption_awake_ = se.optional_double_param(
00365          "energy_consumption_awake", energy_consumption_awake_ );
00366       energy_consumption_sleep_ = se.optional_double_param(
00367          "energy_consumption_sleep", energy_consumption_sleep_ );
00368       activation_threshold_ = se.optional_double_param(
00369          "activation_threshold", activation_threshold_ );
00370       probability_awakening_min_ = se.optional_double_param(
00371          "probability_awakening_min", probability_awakening_min_ );
00372       probability_awakening_max_ = se.optional_double_param(
00373          "probability_awakening_max", probability_awakening_max_ );
00374       spontaneous_awakening_activity_level_ = se.optional_double_param(
00375          "spontaneous_awakening_activity_level", spontaneous_awakening_activity_level_ );
00376       radius_min_ = se.optional_double_param(
00377          "radius_min", radius_min_ );
00378       radius_max_ = se.optional_double_param(
00379          "radius_max", radius_max_ );
00380       // parameter already set for disk graph model
00381       transmission_range_ = se.required_double_param( "range" );
00382       application_consumption_ = se.optional_double_param(
00383          "application_consumption", application_consumption_ );
00384       g_ = se.optional_double_param( "g", g_ );
00385       cloud_ = se.optional_double_param( "cloud", cloud_ );
00386       event_storage_time_ = se.optional_double_param( "storage_time", event_storage_time_ );
00387       event_denominator_ = se.optional_double_param( "event_denominator", event_denominator_ );
00388 
00389       S_ = spontaneous_awakening_activity_level_;
00390       h_ = S_;
00391 
00392       probability_awakening_ = 0.0;
00393    }
00394 #endif
00395    // -----------------------------------------------------------------------
00396    template<typename OsModel_P,
00397             typename Radio_P,
00398             typename Timer_P,
00399             typename Clock_P,
00400             typename Debug_P>
00401    void
00402    AntsDutyCyclingAlgorithm<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P>::
00403    receive( node_id_t from, size_t len, block_data_t *data )
00404    {
00405       if ( from == radio().id() )
00406          return;
00407 
00408       message_id_t msg_id = *data;
00409       if ( msg_id == ANTS_DUTY_CYCLING_MESSAGE_ID )
00410       {
00411          Message *message = (Message *)data;
00412          h_ += message->activity();
00413       }
00414    }
00415    // -----------------------------------------------------------------------
00416    template<typename OsModel_P,
00417             typename Radio_P,
00418             typename Timer_P,
00419             typename Clock_P,
00420             typename Debug_P>
00421    void
00422    AntsDutyCyclingAlgorithm<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P>::
00423    enable_transmission_phase( void *userdata )
00424    {
00425       // FIXME
00426 //       radio().enable_radio();
00427       timer().template set_timer<self_type, &self_type::algorithm_step>(
00428                                   int(time_step_ * 1000), this, 0 );
00429    }
00430    // -----------------------------------------------------------------------
00431    template<typename OsModel_P,
00432             typename Radio_P,
00433             typename Timer_P,
00434             typename Clock_P,
00435             typename Debug_P>
00436    void
00437    AntsDutyCyclingAlgorithm<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P>::
00438    algorithm_step( void *userdata )
00439    {
00440 #ifdef ANTS_HALLWAY_DUTY_CYCLING_DEBUG
00441       debug().debug(  "AntsDutyCyclingAlgorithm: step at %i at %f \n",  radio().id(  ), node_->world().current_time() );
00442 #endif
00443 //       if ( battery_ < 0.01 )
00444 //       {
00445 //          active_ = false;
00446 //          notify_receivers( EPA_INACTIVE );
00447 //          radio().set_app_active(  active_ );
00448 //          S_ = 0.0;
00449 //       }
00450 //       else
00451 //       {
00452 
00453          while (!event_list_.empty())
00454          {
00455             EventListIterator it = event_list_.begin();
00456             if ( clock().time() - it->second > event_storage_time_ )
00457             {
00458                event_list_.pop_front();
00459                continue;
00460             }
00461             break;
00462          }
00463 
00464          int events = 0;
00465          for ( EventListIterator
00466                   it = event_list_.begin();
00467                   it != event_list_.end();
00468                   ++it )
00469          {
00470             events += it->first;
00471          }
00472          if ( events != 0 )
00473             std::cout << events << " events in last " << event_storage_time_ << " time units." << std::endl;
00474 
00475          update_actvity();
00476          update_active_state();
00477          update_probability_awakening( events );
00478          try_spontaneous_awakening();
00479          update_radius();
00480          if (active_)
00481          {
00482             Message message;
00483             message.set_msg_id( ANTS_DUTY_CYCLING_MESSAGE_ID );
00484             message.set_activity( S_ );
00485             radio().send(  radio().BROADCAST_ADDRESS,
00486                      message.buffer_size(), (block_data_t*)&message );
00487          }
00488 //       }
00489 
00490       last_time_ = clock().time();
00491       timer().template set_timer<self_type, &self_type::disable_transmission_phase>(
00492                                   int(time_step_ * 1000), this, 0 );
00493    }
00494    // -----------------------------------------------------------------------
00495    template<typename OsModel_P,
00496             typename Radio_P,
00497             typename Timer_P,
00498             typename Clock_P,
00499             typename Debug_P>
00500    void
00501    AntsDutyCyclingAlgorithm<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P>::
00502    disable_transmission_phase( void *userdata )
00503    {
00504       // FIXME
00505 //       radio().disable_radio();
00506       time_t next_step = 1 - (clock().time() - (int)clock().time());
00507       timer().template set_timer<self_type, &self_type::enable_transmission_phase>(
00508                                   int(next_step * 1000), this, 0 );
00509    }
00510    // ----------------------------------------------------------------------
00511    template<typename OsModel_P,
00512             typename Radio_P,
00513             typename Timer_P,
00514             typename Clock_P,
00515             typename Debug_P>
00516    void
00517    AntsDutyCyclingAlgorithm<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P>::
00518    event_triggered( int events )
00519    {
00520       if ( !active_ )
00521          return;
00522 
00523       std::cout << "Triggered " << events << " event(s)!" << std::endl;
00524       Event ev;
00525       ev.first = events;
00526       ev.second = clock().time();
00527       event_list_.push_back( ev );
00528    }
00529    // ----------------------------------------------------------------------
00530    template<typename OsModel_P,
00531             typename Radio_P,
00532             typename Timer_P,
00533             typename Clock_P,
00534             typename Debug_P>
00535    void
00536    AntsDutyCyclingAlgorithm<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P>::
00537    update_active_state()
00538    {
00539       if ( S_ >= activation_threshold_ )
00540       {
00541 std::cout << "S_ >= activation_threshold_: " << S_ << " >= " << activation_threshold_ << std::endl;
00542          active_ = true;
00543          notify_receivers( EPA_ACTIVE );
00544       }
00545       else
00546       {
00547          active_ = false;
00548          notify_receivers( EPA_INACTIVE );
00549       }
00550       // FIXME
00551 //       radio().set_app_active(  active_ );
00552    }
00553    // ----------------------------------------------------------------------
00554    template<typename OsModel_P,
00555             typename Radio_P,
00556             typename Timer_P,
00557             typename Clock_P,
00558             typename Debug_P>
00559    void
00560    AntsDutyCyclingAlgorithm<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P>::
00561    try_spontaneous_awakening()
00562    {
00563       if ( !active_ )
00564       {
00565          // TODO
00566          double p = *uni_rnd_;
00567          if ( p <= probability_awakening_ )
00568          {
00569 std::cout << "Spontaneously awaked. Probability was " << probability_awakening_ << std::endl;
00570             S_ = spontaneous_awakening_activity_level_;
00571             active_ = true;
00572             notify_receivers( EPA_ACTIVE );
00573             // FIXME
00574 //             radio().set_app_active(  active_ );
00575          }
00576          else
00577             std::cout << "No spontaneous awakening. Probability was " << probability_awakening_ << std::endl;
00578       }
00579    }
00580    // ----------------------------------------------------------------------
00581    template<typename OsModel_P,
00582             typename Radio_P,
00583             typename Timer_P,
00584             typename Clock_P,
00585             typename Debug_P>
00586    void
00587    AntsDutyCyclingAlgorithm<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P>::
00588    update_radius()
00589    {
00590       radius_ = radius_min_ * ( 1 - battery_ ) + radius_max_ * battery_;
00591 
00592       double ratio = radius_ / transmission_range_;
00593       double value = ratio;
00594       if ( ratio <= .15/2.)
00595          value = 0.;
00596       else if( ratio <= (.15+.32)/2. )
00597          value = 0.15;
00598        else if( ratio <= (.32+.49)/2. )
00599          value = 0.32;
00600        else if( ratio <= (.49+.66)/2. )
00601          value = 0.49;
00602        else if( ratio <= (.66+.83)/2. )
00603          value = 0.66;
00604        else if( ratio <= (.83+.1)/2. )
00605          value = 0.83;
00606        else
00607          value = 1.0;
00608 
00609 //        if ( ratio <= .15 )
00610 //           value = 0.15;
00611 //        else if( ratio <= .32 )
00612 //           value = 0.32;
00613 //        else if( ratio <= .49 )
00614 //           value = 0.49;
00615 //        else if( ratio <= .66 )
00616 //           value = 0.66;
00617 //        else if( ratio <= .83 )
00618 //           value = 0.83;
00619 //        else
00620 //           value = 1.0;
00621 
00622 //       std::cout << "UPADTE to " << ratio << "; value is " << value << std::endl;
00623 
00624 // TODO
00625 //        node_->set_transmission_range( value );
00626    }
00627    // ----------------------------------------------------------------------
00628    template<typename OsModel_P,
00629             typename Radio_P,
00630             typename Timer_P,
00631             typename Clock_P,
00632             typename Debug_P>
00633    void
00634    AntsDutyCyclingAlgorithm<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P>::
00635    update_probability_awakening( int events )
00636    {
00637       double k = (double)events / event_denominator_;
00638       if ( k > 1 )
00639          k = 1;
00640 
00641       probability_awakening_ =
00642          probability_awakening_min_ * ( 1 - k ) +
00643          probability_awakening_max_ * k;
00644 
00645       if ( k != 0 && k != 1 )
00646          std::cout << "eventcounter: k=" << k << "; pa=" << probability_awakening_ << std::endl;
00647    }
00648    // ----------------------------------------------------------------------
00649    template<typename OsModel_P,
00650             typename Radio_P,
00651             typename Timer_P,
00652             typename Clock_P,
00653             typename Debug_P>
00654    void
00655    AntsDutyCyclingAlgorithm<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P>::
00656    update_actvity()
00657    {
00658       S_ = tanh(g_*h_);
00659       h_ = S_;
00660    }
00661 
00662 }
00663 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines