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