![]() |
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. 16, 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 #include <CONSTANZE/GeneratorMMPP.hpp> 00029 #include <CONSTANZE/Generator.hpp> 00030 #include <CONSTANZE/Binding.hpp> 00031 #include <CONSTANZE/ConstanzeComponent.hpp> 00032 00033 #include <WNS/module/Base.hpp> 00034 #include <WNS/distribution/Distribution.hpp> 00035 #include <WNS/node/Node.hpp> 00036 00037 #include <fstream> 00038 00039 using namespace constanze; 00040 using namespace wns::markovchain; 00041 00042 // objects of these classes are created by name: 00043 // the names are specified in Constanze.py as __plugin__ 00044 STATIC_FACTORY_REGISTER_WITH_CREATOR(constanze::GeneratorMMPP, constanze::GeneratorBase, "MMPP", wns::PyConfigViewCreator); 00045 STATIC_FACTORY_REGISTER_WITH_CREATOR(constanze::GeneratorMMPP, constanze::GeneratorBase, "CTMMPP", wns::PyConfigViewCreator); 00046 00047 /*************************** Generator *******************************/ 00048 00049 GeneratorMMPP::GeneratorMMPP( const wns::pyconfig::View& config) : 00050 GeneratorBase(config), // config goes into pyco (member) 00051 MarkovContinuousTimeTraffic(config.get<int>("numberOfChains")), // other base class 00052 //numberOfChains(config.get<int>("numberOfChains")), // already in MarkovBase class 00053 targetRate(0.0), 00054 loggerName(config.get<std::string>("logger.name")) 00055 { 00056 assure(config.knows("rateScale"),"missing rateScale parameter"); 00057 assure(config.knows("targetRate"),"missing targetRate parameter"); 00058 assure((config.isNone("rateScale") && !config.isNone("targetRate")) 00059 || (!config.isNone("rateScale") && config.isNone("targetRate")), 00060 "rateScale and targetRate are mutually exclusive. Set one to None!"); 00061 if (!config.isNone("rateScale")) { 00062 rateScale=config.get<double>("rateScale"); // in MarkovContinuosTimeTraffic class 00063 } else { 00064 targetRate=config.get<double>("targetRate"); 00065 } 00066 assure(rateScale>0.0,"bad rateScale"); 00067 transitionScale=config.get<double>("transitionScale"); // in MarkovContinuousTime class 00068 assure(transitionScale>0.0,"bad transitionScale"); 00069 // we have two loggers, one from each base class 00070 //logger = log; // from MarkovBase::logger GeneratorBase::log 00071 logger = wns::logger::Logger(log.getModuleName(), loggerName + ".CTMC"); 00072 logger.setLevel(log.getLevel()); // copy logging level 00073 00074 // sub structure "mmppParams": 00075 wns::pyconfig::View mmppParamsConfig(config, "mmppParams"); 00076 int startState = mmppParamsConfig.get<int>("startState"); // valid for all chains 00077 bool fromFile = mmppParamsConfig.get<bool>("fromFile"); 00078 std::string transitionDistributionSpec; 00079 if (mmppParamsConfig.knows("transitionDistribution") 00080 && !mmppParamsConfig.isNone("transitionDistribution")) { 00081 transitionDistributionSpec = mmppParamsConfig.get<std::string>("transitionDistribution"); 00082 } else { 00083 transitionDistributionSpec = "NegExp(X)"; 00084 } 00085 00086 MESSAGE_BEGIN(NORMAL, log, m, "New GeneratorMMPP: "); 00087 m << "C=" << numberOfChains << ", rs=" << rateScale << ", ts=" << transitionScale 00088 << ", TD=" << transitionDistributionSpec; 00089 MESSAGE_END(); 00090 00091 if (fromFile) { // read parameters from GDF file (format used in Opnet) 00092 // examples are in ./framework/libwns--main--3.0/PyConfig/wns/markov/*.gdf 00093 std::string filename = mmppParamsConfig.get<std::string>("filename"); 00094 MESSAGE_BEGIN(NORMAL, log, m, "reading from "); 00095 m << "filename=" << filename; 00096 MESSAGE_END(); 00097 //std::fstream in(filename.c_str(),std::ios::in); // opens automatically 00098 std::ifstream in(filename.c_str()); // opens automatically 00099 assure(in.good(),"error opening file "+filename); 00100 MarkovContinuousTimeTraffic::readNumberOfStates(in); 00101 MarkovContinuousTimeTraffic::readStatesFromFile(in); 00102 MarkovContinuousTimeTraffic::readTransitionsFromFile(in); 00103 in.close(); 00104 for(int chain=0; chain<numberOfChains; chain++) 00105 startStates[chain]=startState; // here: one value for all 00106 } else { // params from class MMPPparams 00107 int numberOfStates = mmppParamsConfig.get<int>("numberOfStates"); 00108 assure(mmppParamsConfig.len("transitionMatrix") == numberOfStates, "transitionMatrix: wrong dimension"); 00109 assure(mmppParamsConfig.len("stateList") == numberOfStates, "stateList: wrong dimension"); 00110 setNumberOfStates(numberOfStates); 00111 if (!mmppParamsConfig.knows("startStates") 00112 || mmppParamsConfig.isNone("startStates")) { // no startStates[] specified 00113 for(int chain=0; chain<numberOfChains; chain++) 00114 startStates[chain] = startState; 00115 } else { // startStates[] specified as an array 00116 assure(mmppParamsConfig.len("startStates") == numberOfChains, "startStates: wrong dimension"); 00117 for(int chain=0; chain<numberOfChains; chain++) { 00118 int aStartState = mmppParamsConfig.get<int>("startStates", chain); 00119 startStates[chain] = aStartState; 00120 } 00121 } // else: startStates[] specified as an array 00122 for(int state=0; state < numberOfStates; state++) { 00123 // get the state specifications: 00124 wns::pyconfig::View stateConfig = mmppParamsConfig.get("stateList", state); 00125 vectorOfStates[state] = TrafficSpec(stateConfig); // inherited member 00126 00127 // the following lines in MESSAGE_BEGIN/MESSAGE_END are 00128 // only for showing the parameters of the state: 00129 MESSAGE_BEGIN(NORMAL, log, m, "State["<<state<<"]: "); 00130 m << "iat=" << *(vectorOfStates[state].getInterArrivalTimeDistribution()) 00131 << ", packetSize=" << *(vectorOfStates[state].getPacketSizeDistribution()) 00132 << ", mean=" << vectorOfStates[state].getMeanRate() * rateScale << " bits/s"; 00133 MESSAGE_END(); 00134 00135 // get the matrix specification: 00136 std::stringstream index; 00137 index << state; 00138 std::string subviewName = "transitionMatrix" + 00139 std::string("[") + index.str() + std::string("]"); 00140 for(int col = 0; col < numberOfStates; ++col) { 00141 double rate = mmppParamsConfig.get<double>(subviewName,col); 00142 // rate *= transitionScale; // done here or in Markov* classes? 00143 //MESSAGE_SINGLE(NORMAL, log,"r["<<state<<","<<col<<"]="<<rate); 00144 setTransitionMatrixElement(state,col,rate); 00145 } // column 00146 } // forall rows (=states) 00147 } // else: taken from MMPPparams 00148 setTransitionDistributionSpec(transitionDistributionSpec); // can only be done after numberOfStates is known 00149 // now we have all parameters inside 00150 calculateStateProbabilities(); // also determines meanRate 00151 // use calculated meanRate to scale with rateScale to achieve targetRate 00152 if (!config.isNone("targetRate")) { // targetRate given 00153 assure(meanRate>0.0,"meanRate must be >0"); 00154 rateScale = targetRate / meanRate; 00155 MESSAGE_SINGLE(NORMAL, log, "scaling for targetRate="<< targetRate << " => rateScale=" << rateScale); 00156 // recalculate mean, min, max: 00157 calculateStateProbabilities(); 00158 } else { 00159 targetRate = meanRate; // from MarkovContinuousTimeTraffic 00160 } 00161 } // constructor 00162 00163 00164 GeneratorMMPP::~GeneratorMMPP() 00165 { 00166 MESSAGE_SINGLE(VERBOSE, log, "~GeneratorMMPP()"); 00167 cancelAllTimeouts(); // remove state transition events (from MultipleTimeout.hpp) 00168 } 00169 00170 // begin of the traffic generation 00171 void GeneratorMMPP::start() 00172 { 00173 MESSAGE_SINGLE(NORMAL, log, "GeneratorMMPP::start()"); 00174 // now we know the binding: 00175 //SubGenerator aSubGenerator(binding,log,NULL,NULL,rateScale); // empty 00176 SubGenerator aSubGenerator(this,log,NULL,NULL,rateScale); // empty 00177 subGenerators = std::vector<SubGenerator>(numberOfChains,aSubGenerator); // empty constructor needed here 00178 for(int chain=0; chain<numberOfChains; chain++) { 00179 wns::logger::Logger logSub("CONSTANZE", loggerName + ".Subgen[" + stringify(chain) + "]"); 00180 subGenerators[chain].reconfigLogger(logSub); 00181 } 00182 startEvents(); // prepares matrix and runs events 00183 } 00184 00185 // end of the traffic generation 00186 void GeneratorMMPP::stop() 00187 { 00188 MESSAGE_SINGLE(NORMAL, log, "GeneratorMMPP::stop()"); 00189 //cancelAllTimeouts(); // remove state transition events (from MultipleTimeout.hpp) 00190 // use a method in MarkovContinuousTime: 00191 stopMarkovProcess(); 00192 for(int chain=0; chain<numberOfChains; chain++) 00193 subGenerators[chain].stop(); 00194 } 00195 00196 void GeneratorMMPP::stateChangeNotification(const int &chainNumber) { 00197 //int newState = actualStates[chainNumber]; 00198 int newState = getActualStateIndex(chainNumber); 00199 MESSAGE_SINGLE(NORMAL, log, "GeneratorMMPP::stateChangeNotification(chain="<<chainNumber<<") to state "<<newState); 00200 //TrafficSpec newTrafficSpec = vectorOfStates[newState]; 00201 const TrafficSpec *newTrafficSpec = getStateContent(newState); 00202 // reconfig automatically starts events: 00203 subGenerators[chainNumber].reconfig( 00204 newTrafficSpec->getInterArrivalTimeDistribution(), 00205 newTrafficSpec->getPacketSizeDistribution()); 00206 } 00207 00208 /* onTimeout() is handled by the parent class. A hook would be like that: 00209 void GeneratorMMPP::onTimeout(const int &chainNumber) { 00210 MarkovContinuousTimeTraffic::onTimeout(chainNumber); // parent class 00211 } // onTimeout() 00212 */ 00213 00214
1.5.5