![]() |
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-2009 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 #include <WNS/scheduler/grouper/SINRHeuristic.hpp> 00029 00030 #include <WNS/pyconfig/View.hpp> 00031 #include <WNS/StaticFactory.hpp> 00032 00033 using namespace wns::scheduler; 00034 using namespace wns::scheduler::grouper; 00035 00036 STATIC_FACTORY_REGISTER_WITH_CREATOR(SINRHeuristic, GroupingProviderInterface, "SINRHeuristic", wns::PyConfigViewCreator); 00037 00038 00039 SINRHeuristic::SINRHeuristic(const wns::pyconfig::View& config) 00040 : TreeBasedGrouper(config) 00041 { 00042 } 00043 00044 float 00045 SINRHeuristic::groupingUtility(UserSet group, UserSet newGroup, ModeType mode) { 00046 // merge the two groups 00047 group.insert(newGroup.begin(), newGroup.end()); 00048 00049 std::map<UserID, wns::CandI> candis = 00050 getCandIsForGroup(group, mode); 00051 00052 double sum = 0.0; 00053 00054 for (UserSet::iterator iter = group.begin(); 00055 iter != group.end(); ++iter) 00056 { 00057 assure(candis.find(*iter) != candis.end(), "Where is my user gone?"); 00058 wns::Ratio sinr(candis[*iter].C / candis[*iter].I); 00059 //double tp = colleagues.registry->getPhyModeForSIR(candis[*iter].C / candis[*iter].I).second; 00060 if (colleagues.phyModeMapper->sinrIsAboveLimit(sinr)) { 00061 double tp = colleagues.phyModeMapper->getBestPhyMode(sinr)->getDataRate(); 00062 sum += tp; 00063 } else 00064 return 0.0; // don't allow user without service 00065 } 00066 return sum; 00067 } 00068 00069 00070 00071 float 00072 SINRHeuristic::getTPfromTreeLevel(TreeLevel level, std::map<UserSet, float> &groupTP) 00073 { 00074 float tpLevel = 0.0; 00075 for (TreeLevel::const_iterator iter = level.begin(); 00076 iter != level.end(); ++iter) 00077 if (groupTP[*iter] < 0.0001) 00078 return 0.0; 00079 else 00080 tpLevel += groupTP[*iter]; 00081 return tpLevel; 00082 } 00083 00084 00085 Grouping 00086 SINRHeuristic::treeAlgorithm(const UserSet activeUsers, unsigned int maxBeams, ModeType mode) 00087 { 00088 std::vector<TreeLevel> treeLevels; 00089 std::map<float, std::pair<unsigned int, unsigned int> > combinedTP; 00090 std::map<UserSet, float> groupTP; // database that stores TP for every group 00091 00092 std::vector<float> sdmaGain; 00093 sdmaGain.clear(); 00094 00095 // init the first level 00096 TreeLevel firstLevel; 00097 for (UserSet::const_iterator iter = activeUsers.begin(); 00098 iter != activeUsers.end(); ++iter) { 00099 UserSet oneUserGroup; 00100 00101 oneUserGroup.clear(); 00102 oneUserGroup.insert(*iter); 00103 00104 std::map<UserID, wns::CandI> candis = 00105 getCandIsForGroup(oneUserGroup, mode); 00106 00107 assure(candis.find(*iter) != candis.end(), "Where is my user gone?"); 00108 00109 // make sure we don't include users that can't even get a suitable SINR 00110 // when served alone 00111 wns::Ratio sinr(candis[*iter].C / candis[*iter].I); 00112 //float tp = colleagues.registry->getPhyModeForSIR(candis[*iter].C / candis[*iter].I).second; 00113 //if (phymode->getRate() > 0.0001) 00114 if (colleagues.phyModeMapper->sinrIsAboveLimit(sinr)) 00115 { 00116 double tp = colleagues.phyModeMapper->getBestPhyMode(sinr)->getDataRate(); 00117 groupTP[oneUserGroup] = tp; 00118 individualCandIs[*iter] = candis[*iter]; 00119 firstLevel.push_back(oneUserGroup); 00120 } else { // do nothing 00121 MESSAGE_BEGIN(NORMAL, logger, m, colleagues.registry->getNameForUser(colleagues.registry->getMyUserID())); 00122 m << ": discarding user " 00123 << colleagues.registry->getNameForUser(*iter) 00124 << " because even alone its SINR is too bad for transmission. SINR=" << sinr; 00125 MESSAGE_END(); 00126 } 00127 } 00128 treeLevels.push_back(firstLevel); 00129 unsigned int maxTreeHeight = firstLevel.size(); 00130 00131 // get the TP for the base case (no SDMA) and calculate the average TP per 00132 // slot. This is the reference value for our grouping gain 00133 float trivialTP = getTPfromTreeLevel(treeLevels[0], groupTP); 00134 float normalizedTrivialTP = trivialTP / float(treeLevels[0].size()); 00135 sdmaGain.push_back(1.0); // the first level (index 0) is the reference => gain = 1.0 00136 00137 00138 // then build the next higher levels by joining the two best-joinable groups 00139 // from the previous level 00140 for (unsigned int i = 0; i < maxTreeHeight; ++i) 00141 { 00142 combinedTP.clear(); 00143 // get all possible combinations of two groups, but don't calculate same 00144 // group twice 00145 for (unsigned int g1 = 0; g1 < treeLevels[i].size() - 1; ++g1) 00146 for (unsigned int g2 = g1+1; g2 < treeLevels[i].size(); ++g2) 00147 if (treeLevels[i][g1].size() + treeLevels[i][g2].size() <= maxBeams) 00148 // cost function is overwritten by specialized TreeGrouper variant 00149 combinedTP[groupingUtility(treeLevels[i][g1], treeLevels[i][g2], mode)] = 00150 std::make_pair<unsigned int, unsigned int>(g1,g2); 00151 // assure(costs.size(), "Not on upmost level but all groups too big 00152 // to join"); 00153 if (combinedTP.size() == 0) // could not join two groups, so we are done 00154 break; 00155 00156 std::pair<float, std::pair<unsigned int, unsigned int> > maxEntry = *(max_element(combinedTP.begin(), combinedTP.end())); 00157 std::pair<unsigned int, unsigned int> bestCombi = maxEntry.second; 00158 00159 // build the next level 00160 TreeLevel nextLevel; 00161 00162 // first join the the two best joinable groups and then save it 00163 UserSet newGroup = treeLevels[i][bestCombi.first]; 00164 newGroup.insert(treeLevels[i][bestCombi.second].begin(), 00165 treeLevels[i][bestCombi.second].end()); 00166 nextLevel.push_back(newGroup); 00167 00168 // the TP for the new group was delivered by the utility function 00169 groupTP[newGroup] = maxEntry.first; 00170 00171 // then add the others 00172 for (unsigned int g = 0; g < treeLevels[i].size(); ++g) 00173 if ((g != bestCombi.first) && (g != bestCombi.second)) 00174 nextLevel.push_back(treeLevels[i][g]); 00175 00176 // calculate the SDMA gain for next level 00177 sdmaGain.push_back((getTPfromTreeLevel(nextLevel, groupTP) / nextLevel.size()) / normalizedTrivialTP); 00178 treeLevels.push_back(nextLevel); 00179 // continue with the just constructed next level 00180 } 00181 00182 // now see who got the best sdmaGain and convert it to a grouping before returning 00183 00184 int maxIndex = max_element(sdmaGain.begin(), sdmaGain.end()) - sdmaGain.begin(); 00185 00186 MESSAGE_SINGLE(NORMAL, logger, "Selecting Level " << maxIndex << " resulting in a gain of " << sdmaGain[maxIndex]); 00187 00188 groupingGainProbeBus->put(sdmaGain[maxIndex]); 00189 00190 return convertTreeLevelToGrouping(treeLevels[maxIndex], mode); 00191 } 00192 00193 00194 00195 00196 00197
1.5.5