Wiselib
|
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