![]() |
User Manual, Developers Guide and API Documentation |
![]() |
00001 /******************************************************************************* 00002 * This file is part of openWNS (open Wireless Network Simulator) 00003 * _____________________________________________________________________________ 00004 * 00005 * Copyright (C) 2004-2007 00006 * Chair of Communication Networks (ComNets) 00007 * Kopernikusstr. 5, D-52074 Aachen, Germany 00008 * phone: ++49-241-80-27910, 00009 * fax: ++49-241-80-22242 00010 * email: info@openwns.org 00011 * www: http://www.openwns.org 00012 * _____________________________________________________________________________ 00013 * 00014 * openWNS is free software; you can redistribute it and/or modify it under the 00015 * terms of the GNU Lesser General Public License version 2 as published by the 00016 * Free Software Foundation; 00017 * 00018 * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY 00019 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 00020 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00021 * details. 00022 * 00023 * You should have received a copy of the GNU Lesser General Public License 00024 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00025 * 00026 ******************************************************************************/ 00027 00028 00029 #include <WNS/markovchain/MarkovBase.hpp> 00030 #include <WNS/events/CanTimeout.hpp> 00031 #include <WNS/logger/Logger.hpp> 00032 #include <WNS/module/Base.hpp> 00033 00034 #include <WNS/distribution/Uniform.hpp> 00035 00036 #include <boost/numeric/ublas/lu.hpp> 00037 00038 #ifndef WNS_MARKOVCHAIN_MARKOVDISCRETETIME_HPP 00039 #define WNS_MARKOVCHAIN_MARKOVDISCRETETIME_HPP 00040 00041 00042 namespace wns { namespace markovchain { 00043 00049 template<class T> 00050 class MarkovDiscreteTime : 00051 public wns::events::CanTimeout, 00052 public MarkovBase<T> 00053 { 00054 public: 00059 MarkovDiscreteTime(int _numberOfChains): 00060 wns::events::CanTimeout(), 00061 MarkovBase<T>(_numberOfChains), 00062 slotTime(1.0), 00063 startTime(0.0), 00064 stopTime(0.0) 00065 { 00066 MESSAGE_SINGLE(VERBOSE,MarkovBase<T>::logger, "MarkovDiscreteTime() called"); 00067 } // constructor 00068 00072 MarkovDiscreteTime(int _numberOfStates, 00073 int _numberOfChains, 00074 std::vector<T> states, 00075 TransitionMatrixType matrix, 00076 std::vector<int> startStates, 00077 simTimeType startTime, 00078 simTimeType slotTime, 00079 simTimeType stopTime): 00080 wns::events::CanTimeout(), 00081 MarkovBase<T>(_numberOfStates, _numberOfChains, states, matrix, startStates), 00082 slotTime(slotTime), 00083 startTime(startTime), 00084 stopTime(stopTime) 00085 { 00086 } // constructor 00087 00091 ~MarkovDiscreteTime() 00092 { 00093 } 00094 00098 void 00099 setSlotTime(simTimeType _slotTime) 00100 { 00101 slotTime = _slotTime; 00102 } 00103 00107 void 00108 setStartTime(simTimeType _startTime) 00109 { 00110 startTime = _startTime; 00111 } 00112 00116 void 00117 setStopTime(simTimeType _stopTime) 00118 { 00119 stopTime = _stopTime; 00120 } 00121 00125 std::string 00126 stringify(double x) const 00127 { 00128 std::ostringstream o; 00129 o << x; 00130 return o.str(); 00131 } 00132 00137 double 00138 calculateNextState(int chainNumber) 00139 { 00140 int currentState = MarkovBase<T>::actualStates[chainNumber]; 00141 int nextState; 00142 wns::distribution::StandardUniform* randomDist; 00143 00144 // generate a random value 00145 randomDist = new wns::distribution::StandardUniform(); 00146 double random = (*randomDist)(); 00147 00148 nextState = currentState; 00149 double probSum = 0.0; 00150 for (int st = 0; st < MarkovBase<T>::numberOfStates; st++){ 00151 double prob = MarkovBase<T>::transitionsMatrix(currentState, st); 00152 probSum += prob; 00153 if (random <= probSum) { 00154 nextState = st; 00155 break; 00156 } 00157 } // forall (possible next) states 00158 if (currentState != nextState) { 00159 MESSAGE_BEGIN(NORMAL, MarkovBase<T>::logger, m, "NextState(chain=" << chainNumber << "): "); 00160 m << "scheduled transition " << currentState << " -> " << nextState << " after " << slotTime << "s"; 00161 MESSAGE_END(); 00162 MarkovBase<T>::nextStates[chainNumber] = nextState; 00163 } 00164 00165 delete randomDist; 00166 return slotTime; 00167 } // calculateNextState 00168 00172 bool 00173 checkSum() 00174 { 00175 for (int i = 0;i < MarkovBase<T>::numberOfStates; i++) { 00176 double checkSum = 0.0; 00177 for (int j = 0; j < MarkovBase<T>::numberOfStates; j++) 00178 checkSum += MarkovBase<T>::transitionsMatrix(i, j); 00179 assure(fabs(checkSum - 1.0) < 1e-3, "wrong matrix row sum"); 00180 if (fabs(checkSum - 1.0) >= 1e-3) { 00181 MESSAGE_SINGLE(NORMAL,MarkovBase<T>::logger, "wrong matrix row sum"); 00182 return false; 00183 } 00184 } // for i 00185 return true; 00186 } // checkSum() 00187 00188 00193 void 00194 startEvents() 00195 { 00196 checkSum(); 00197 MESSAGE_SINGLE(NORMAL,MarkovBase<T>::logger, 00198 "startEvents(): startTime=" << startTime << 00199 ", stopTime=" << stopTime ); 00200 00201 wns::distribution::StandardUniform* randomDist = 00202 new wns::distribution::StandardUniform(); 00203 00204 for (int chainNumber = 0; chainNumber<MarkovBase<T>::numberOfChains; chainNumber++) { 00205 int startState = MarkovBase<T>::startStates[chainNumber]; 00206 assure((startState >= -1) && (startState < MarkovBase<T>::numberOfStates), "wrong start state"); 00207 if (startState < 0) { // random (not simple!) 00208 startState = 0; 00209 calculateStateProbabilities(); // only calculated once even if called up to C times here 00210 double random = (*randomDist)(); 00211 double probSum = 0.0; 00212 MESSAGE_SINGLE(NORMAL,MarkovBase<T>::logger, "determining random start state (r="<<random<<")"); 00213 int nos = MarkovBase<T>::numberOfStates; 00214 for(int i=0; i<nos; i++) { 00215 double p=MarkovBase<T>::stateProbabilities[i]; 00216 probSum += p; 00217 if (random <= probSum) { 00218 startState = i; break; 00219 } 00220 } 00221 } 00222 MarkovBase<T>::actualStates[chainNumber] = startState; 00223 MarkovBase<T>::nextStates[chainNumber] = startState; 00224 MESSAGE_BEGIN(NORMAL, MarkovBase<T>::logger, m, "startEvents(chain=" << chainNumber<<"):"); 00225 m << " startState=" << startState; 00226 MESSAGE_END(); 00227 00228 calculateNextState(chainNumber); 00229 00230 // this notifies the method of the derived class: 00231 stateChangeNotification(chainNumber); 00232 } // forall chains 00233 setTimeout(startTime + slotTime); // set the timer to a relative time 00234 /* startTime>0 can be a problem if the current time is already >0 */ 00235 delete randomDist; 00236 } // startEvents() 00237 00241 virtual void 00242 stateChangeNotification(const int &chainNumber) 00243 { 00244 #ifndef WNS_NO_LOGGING 00245 int newState = 00246 #endif 00247 MarkovBase<T>::actualStates[chainNumber]; 00248 MESSAGE_SINGLE(NORMAL, MarkovBase<T>::logger, "MarkovContinuousTime::stateChange(" << chainNumber << ") to state " << newState); 00249 } // stateChangeNotification() 00250 00254 virtual void 00255 stopMarkovProcess() 00256 { 00257 MESSAGE_SINGLE(NORMAL,MarkovBase<T>::logger, "MarkovProcess stopped."); 00258 if (hasTimeoutSet()) cancelTimeout(); 00259 // remove state transition events (from CanTimeout.hpp) 00260 } // stopMarkovProcess() 00261 00262 private: 00263 00264 friend class MarkovDiscreteTimeTest; 00265 00266 protected: 00267 00278 virtual void 00279 calculateStateProbabilities() 00280 { 00281 if (MarkovBase<T>::stateProbabilities[0]>=0.0) { return; } 00282 // ^ already calculated 00283 00284 int nos = MarkovBase<T>::numberOfStates; 00285 MESSAGE_BEGIN(VERBOSE, MarkovBase<T>::logger, m, "transitionMatrix=\n"); 00286 m << MarkovBase<T>::transitionsMatrix; 00287 MESSAGE_END(); 00288 00289 TransitionMatrixType Ptrans = boost::numeric::ublas::trans(MarkovBase<T>::transitionsMatrix); 00290 00291 MESSAGE_BEGIN(VERBOSE, MarkovBase<T>::logger, m, "System matrix P^T=\n"); 00292 m << Ptrans << "\n"; 00293 MESSAGE_END(); 00294 00295 TransitionMatrixType ident = boost::numeric::ublas::identity_matrix<double>(nos, nos); 00296 TransitionMatrixType PtransMinus = TransitionMatrixType(Ptrans - ident); 00297 00298 MESSAGE_BEGIN(VERBOSE, MarkovBase<T>::logger, m, "Matrix (P^T - I)=\n"); 00299 m << PtransMinus << "\n"; 00300 MESSAGE_END(); 00301 00302 // The "Replace an Equation" Approach (see W.J. Stewart Numeric Solution of Markov Chains 2.3.1.2) 00303 00304 boost::numeric::ublas::permutation_matrix<std::size_t> pm(PtransMinus.size1()); 00305 boost::numeric::ublas::vector<double> x(nos); 00306 00307 x = boost::numeric::ublas::zero_vector<double>(nos); 00308 x(nos - 1) = 1.0; 00309 00310 // Fill the last row of PtransMinus with 1.0 => PtransMinus1 00311 for(int col = 0; col < nos; col++) 00312 PtransMinus(nos - 1, col) = 1.0; 00313 00314 // Solve Qtrans1*result = x 00315 boost::numeric::ublas::lu_factorize(PtransMinus, pm); 00316 boost::numeric::ublas::lu_substitute(PtransMinus, pm, x); 00317 // Result is in x 00318 00319 for(int i = 0; i < nos; i++) 00320 MarkovBase<T>::stateProbabilities[i] = x(i); 00321 00322 MESSAGE_BEGIN(NORMAL, MarkovBase<T>::logger, m, "state probabilities: "); 00323 for(int i=0; i<nos; i++) { 00324 double p = MarkovBase<T>::stateProbabilities[i]; 00325 m << p << " "; 00326 } 00327 MESSAGE_END(); 00328 } 00329 00333 simTimeType slotTime; 00334 00338 simTimeType startTime; 00339 00343 simTimeType stopTime; 00344 00348 virtual void 00349 onTimeout () 00350 { 00351 for (int chainNumber = 0; chainNumber < MarkovBase<T>::numberOfChains; chainNumber++){ 00352 if (MarkovBase<T>::actualStates[chainNumber] != MarkovBase<T>::nextStates[chainNumber]){ 00353 MESSAGE_BEGIN(NORMAL, MarkovBase<T>::logger, m, "onTimeout(chain "<<chainNumber<<"): "); 00354 m << "state change " << MarkovBase<T>::actualStates[chainNumber] 00355 << " -> " << MarkovBase<T>::nextStates[chainNumber]; 00356 MESSAGE_END(); 00357 00358 MarkovBase<T>::actualStates[chainNumber] = MarkovBase<T>::nextStates[chainNumber]; 00359 stateChangeNotification(chainNumber); 00360 } else { // no state change 00361 MESSAGE_SINGLE(VERBOSE,MarkovBase<T>::logger, "onTimeout(chain "<<chainNumber<<"): stays in the state "<<MarkovBase<T>::nextStates[chainNumber]<< " "); 00362 } 00363 calculateNextState(chainNumber); 00364 } // forall chains 00365 00366 if ((stopTime == 0.0) || (wns::simulator::getEventScheduler()->getTime()+slotTime<stopTime)) { 00367 setTimeout(slotTime); // relative 00368 } // else: this was last event. Stop now 00369 } 00370 };// MarkovDiscreteTime 00371 00372 } } 00373 #endif // WNS_MARKOVCHAIN_MARKOVDISCRETETIME_HPP 00374 00375
1.5.5