![]() |
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/AllPossibleGroupsGrouper.hpp> 00029 #include <WNS/scheduler/SchedulerTypes.hpp> 00030 00031 #include <WNS/service/phy/ofdma/Pattern.hpp> 00032 00033 using namespace wns::scheduler; 00034 using namespace wns::scheduler::grouper; 00035 00036 00037 void // I have to overload this to initialize the probe when I have the registry 00038 AllPossibleGroupsGrouper::setColleagues(RegistryProxyInterface* _registry) 00039 { 00040 //GroupingProviderInterface::setColleagues(_traffic, _registry); 00041 SpatialGrouper::setColleagues(_registry); 00042 } 00043 00044 std::map<UserID, wns::CandI> 00045 AllPossibleGroupsGrouper::getCandIs(std::vector<UserID> allUsers, 00046 std::bitset<MAX_STATIONS> bitset, ModeType mode) { 00047 std::map<UserID, wns::CandI> candis; 00048 candis.clear(); 00049 00050 unsigned int noOfStations = allUsers.size(); 00051 00052 switch(mode) { 00053 case tx: 00054 { 00055 if (beamforming){ 00056 00057 std::map<wns::node::Interface*, wns::Power> userNoiseIInterMap; 00058 userNoiseIInterMap.clear(); 00059 00060 for (unsigned int k = 0; k < noOfStations; ++k) 00061 if (bitset.test(k)) { 00062 userNoiseIInterMap[allUsers[k].getNode()] = 00063 colleagues.registry->estimateTxSINRAt(allUsers[k]).interference; 00064 } 00065 candis = convertMap(friends.ofdmaProvider->calculateCandIsTx(userNoiseIInterMap, x_friendliness, txPower)); 00066 } 00067 else{ // no beamforming 00068 assure(noOfStations == 1, "We don't do beamforming, so only one-user groups are supported"); 00069 UserID user = allUsers[0]; 00070 wns::scheduler::ChannelQualityOnOneSubChannel cqi = 00071 colleagues.registry->estimateTxSINRAt(user); 00072 candis[user] = wns::CandI(cqi.carrier, cqi.interference); 00073 } 00074 00075 break; 00076 } 00077 case rx: 00078 { 00079 if (beamforming){ 00080 std::vector<wns::node::Interface*> combination; 00081 combination.clear(); 00082 00083 for (unsigned int k = 0; k < noOfStations; ++k) 00084 if (bitset.test(k)) { 00085 combination.push_back(allUsers[k].getNode()); 00086 } 00087 candis = convertMap(friends.ofdmaProvider->calculateCandIsRx(combination, 00088 colleagues.registry->estimateRxSINROf(allUsers[0]).interference)); 00089 //use estimated interference of user 0 for all other 00090 //terminals as well, maybe average over all entries? 00091 //see TreeBasedGrouper 00092 } 00093 else{ // no beamforming 00094 00095 assure(noOfStations == 1, "We don't do beamforming, so only one-user groups are supported"); 00096 UserID user = allUsers[0]; 00097 wns::scheduler::ChannelQualityOnOneSubChannel cqi = 00098 colleagues.registry->estimateRxSINROf(user); 00099 candis[user] = wns::CandI(cqi.carrier, cqi.interference); 00100 } 00101 00102 break; 00103 } 00104 default: 00105 assure(0, "Wrong mode, can either be RX or TX"); 00106 } 00107 return candis; 00108 } 00109 00110 float 00111 AllPossibleGroupsGrouper::getTPperGroupTrivialGrouping(int noOfStations) 00112 { // what would be the throughput / #users when every user is served on its own, 00113 // i.e. not grouped 00114 00115 // we simply iterate over allPossibleGroups and extract all servedStations 00116 // bitsets that have exactly one bit - the ith - set. The matching bitsets 00117 // cannot be accessed directly because they are not necessarily at position 00118 // 2^i because invalid groups (too many beams, no service etc) got deleted 00119 00120 unsigned int j = 0; 00121 float totalTP = 0.0; 00122 00123 for (int i = 0; i < noOfStations; ++i) 00124 { 00125 while (!(allPossibleGroups[j].servedStations.test(i) && 00126 (allPossibleGroups[j].servedStations.count() == 1))) 00127 { 00128 ++j; 00129 if (j == allPossibleGroups.size()) 00130 { 00131 // make sure that j does not run out of bounds if the group with 00132 // the single user is not found. 00133 MESSAGE_SINGLE(NORMAL, logger, "AllPossibleGroupsGrouper: In this user set there are users that can't be served at all, not even alone"); 00134 j = 0; 00135 break; // stop this while loop - we won't find him anyway 00136 // because groups with unserved users got removed before 00137 } 00138 } 00139 totalTP += allPossibleGroups[j].throughPut; 00140 } 00141 return totalTP / float(noOfStations); 00142 } 00143 00144 std::vector<AllPossibleGroupsGrouper::Beams> 00145 AllPossibleGroupsGrouper::calculateAllPossibleGroups(std::vector<UserID> allUsers, unsigned int maxBeams, 00146 ModeType mode) 00147 { 00148 assure(allUsers.size() <= MAX_STATIONS, "That many stations are not supported, compile with bigger value for MAX_STATIONS"); 00149 00150 std::map<UserID, wns::CandI> candis; 00151 std::vector<Beams> beams; 00152 beams.clear(); 00153 00154 // Let allUsers.size() be the number of users for which all possible beam 00155 // combinations of up to maxBeams are to be calculated. Then the algorithm 00156 // creates all 2^n possible combinations of users to be served in parallel 00157 // and checks whether there are only maxBeams users served at once. 00158 00159 for (unsigned int bits = 1; bits < (unsigned int)(1 << allUsers.size()); ++bits) 00160 { 00161 bool userWithoutService = false; 00162 std::bitset<MAX_STATIONS> bitset(bits); 00163 if (bitset.count() > maxBeams) 00164 continue; 00165 00166 // The SINR calculation is different for RX- or TX-Mode 00167 candis = getCandIs(allUsers, bitset, mode); 00168 00169 // convert SINRS to Throughput 00170 float throughPut = 0.0; 00171 for (std::map<UserID, wns::CandI>::const_iterator iter = candis.begin(); 00172 iter != candis.end(); ++iter) { 00173 wns::Ratio sinr(iter->second.C/iter->second.I); 00174 //if (colleagues.registry->getPhyModeForSIR( iter->second.C/iter->second.I ).second < 0.001) 00175 if (colleagues.phyModeMapper->sinrIsAboveLimit(sinr)) { 00176 double tp = colleagues.phyModeMapper->getBestPhyMode(sinr)->getDataRate(); 00177 throughPut += tp; 00178 //throughPut += colleagues.registry->getPhyModeForSIR( iter->second.C/iter->second.I ).second; 00179 } else { // user with zero data rate, skip this beam 00180 userWithoutService = true; 00181 break; 00182 } 00183 } 00184 Beams currentBeam; 00185 currentBeam.servedStations = bitset; 00186 currentBeam.throughPut = throughPut; 00187 00188 // No empty beams or beams with user without service may be 00189 // saved. This is guaranteed because bits=1..n thus eliminating the 00190 // empty beam and because once a user without service is discovered, the 00191 // userWithoutService flag is set in checked below: 00192 if (!userWithoutService) 00193 beams.push_back(currentBeam); 00194 00195 } 00196 return beams; 00197 } 00198 00199 00200 00201 Grouping 00202 AllPossibleGroupsGrouper::convertPartitionToGrouping(Partition partition, ModeType mode, 00203 std::vector<UserID> allUsers) 00204 { 00205 Grouping grouping; 00206 unsigned int noOfStations = allUsers.size(); 00207 00208 00209 for (unsigned int i = 0 ; i < partition.groups.size(); ++i) { 00210 Group newGroup; 00211 Beams currentGroup = allPossibleGroups[partition.groups[i]]; 00212 std::vector<wns::node::Interface*> usersInGroup; 00213 usersInGroup.clear(); 00214 00215 for (unsigned int j = 0; j < noOfStations; ++j) 00216 if (currentGroup.servedStations.test(j)) 00217 usersInGroup.push_back(allUsers[j].getNode()); 00218 00219 // calculate the pattern for every user in the group 00220 for (unsigned int d = 0; d < usersInGroup.size(); ++d) { 00221 std::vector<wns::node::Interface*> undesireds; 00222 undesireds.clear(); 00223 00224 for (unsigned int u = 0; u < usersInGroup.size(); ++u) 00225 if (d != u) 00226 undesireds.push_back(usersInGroup[u]); 00227 // calculate users pattern with his co-scheduled users as undesireds 00228 if(mode == tx){ 00229 grouping.patterns[UserID(usersInGroup[d])] = friends.ofdmaProvider-> 00230 calculateAndSetBeam(usersInGroup[d], undesireds, x_friendliness); 00231 } 00232 else{ // rx case 00233 grouping.patterns[UserID(usersInGroup[d])] = friends.ofdmaProvider-> 00234 calculateAndSetBeam(usersInGroup[d], undesireds, colleagues.registry->estimateRxSINROf(UserID(usersInGroup[d])).interference); 00235 //see TreeBasedGrouper 00236 00237 } 00238 00239 assure(grouping.patterns[UserID(usersInGroup[d])] != 00240 wns::service::phy::ofdma::PatternPtr(), "Invalid pattern returned"); 00241 } 00242 00243 // calculate the SINR values for every user in the group 00244 newGroup = getCandIs(allUsers, currentGroup.servedStations, mode); 00245 // save it in grouping 00246 grouping.groups.push_back(newGroup); 00247 // and update the group look-up-table 00248 for (std::vector<wns::node::Interface*>::const_iterator iter = usersInGroup.begin(); 00249 iter != usersInGroup.end(); 00250 ++iter) 00251 grouping.userGroupNumber[UserID(*iter)] = i; 00252 00253 00254 // assure that the calculated total TP was not corrupted/mixed up 00255 #ifndef WNS_NDEBUG 00256 float throughPut = 0.0; 00257 for (Group::const_iterator iter = newGroup.begin(); 00258 iter != newGroup.end(); ++iter) { 00259 wns::Ratio sinr(iter->second.C/iter->second.I); 00260 if (colleagues.phyModeMapper->sinrIsAboveLimit(sinr)) { 00261 double tp = colleagues.phyModeMapper->getBestPhyMode(sinr)->getDataRate(); 00262 throughPut += tp; 00263 //throughPut += colleagues.registry->getPhyModeForSIR( iter->second.C/iter->second.I ).second; 00264 } else { // user with zero data rate, skip this beam 00265 assure(0, "Users with zero data rate should have been removed before"); 00266 } 00267 } 00268 double diff = throughPut - currentGroup.throughPut; 00269 assure((diff > -0.0001) && (diff < 0.0001), "Different throughputs calculated"); 00270 #endif 00271 00272 } 00273 return grouping; 00274 } 00275 00282 std::vector<UserID> 00283 AllPossibleGroupsGrouper::getServableUserVectorFromSet(const UserSet userSet, ModeType mode) { 00284 std::map<UserID, wns::CandI> candis; 00285 std::vector<UserID> userVector; 00286 00287 // convert UserSet to userVector needed for calculateAllPossibleGroups 00288 for (UserSet::const_iterator iter = userSet.begin(); 00289 iter != userSet.end(); ++iter) 00290 { 00291 switch(mode) { 00292 case tx: 00293 { 00294 if (beamforming){ 00295 std::map<wns::node::Interface*, wns::Power> userNoiseIInterMap; 00296 userNoiseIInterMap.clear(); 00297 userNoiseIInterMap[iter->getNode()] = colleagues.registry->estimateTxSINRAt(*iter).interference; 00298 candis = convertMap(friends.ofdmaProvider->calculateCandIsTx(userNoiseIInterMap, x_friendliness, txPower)); 00299 } 00300 else{ // no beamforming 00301 assure(userSet.size() == 1, "We don't do beamforming, so only one-user groups are supported"); 00302 UserID user = *iter; 00303 wns::scheduler::ChannelQualityOnOneSubChannel cqi = 00304 colleagues.registry->estimateTxSINRAt(user); 00305 candis[user] = wns::CandI(cqi.carrier, cqi.interference); 00306 } 00307 } 00308 break; 00309 case rx: 00310 { 00311 if (beamforming){ 00312 std::vector<wns::node::Interface*> combination; 00313 combination.clear(); 00314 combination.push_back(iter->getNode()); 00315 00316 candis = convertMap(friends.ofdmaProvider->calculateCandIsRx(combination, 00317 colleagues.registry->estimateRxSINROf(*iter).interference)); 00318 } 00319 else{ // no beamforming 00320 00321 assure(userSet.size() == 1, "We don't do beamforming, so only one-user groups are supported"); 00322 UserID user = *iter; 00323 wns::scheduler::ChannelQualityOnOneSubChannel cqi = 00324 colleagues.registry->estimateRxSINROf(user); 00325 candis[user] = wns::CandI(cqi.carrier, cqi.interference); 00326 } 00327 00328 } 00329 break; 00330 default: 00331 assure(0, "Unknown mode"); 00332 } 00333 wns::Ratio sinr(candis[*iter].C / candis[*iter].I); 00334 //if (colleagues.registry->getPhyModeForSIR(candis[*iter].C / candis[*iter].I).second > 0.0001) 00335 if (colleagues.phyModeMapper->sinrIsAboveLimit(sinr)) 00336 userVector.push_back(*iter); 00337 else { 00338 MESSAGE_BEGIN(VERBOSE, logger, m, colleagues.registry->getNameForUser(colleagues.registry->getMyUserID())); 00339 m << "removing user" 00340 << colleagues.registry->getNameForUser(*iter) 00341 << " because SINR is not sufficient even for serving the user alone"; 00342 MESSAGE_END(); 00343 00344 } 00345 } 00346 return userVector; 00347 } 00348 00349 00359 Grouping 00360 AllPossibleGroupsGrouper::getTxGrouping(const UserSet activeUsers, int maxBeams ) { 00361 assure(dynamic_cast<wns::service::phy::ofdma::DataTransmission*>(friends.ofdmaProvider), 00362 "Grouper needs an OFDMA Provider"); 00363 assure(colleagues.registry, "AllPossibleGroupsGrouper needs a registry"); 00364 00365 std::vector<UserID> userVector = getServableUserVectorFromSet(activeUsers, tx); 00366 allPossibleGroups = calculateAllPossibleGroups(userVector, maxBeams, tx); 00367 00368 MESSAGE_BEGIN(VERBOSE, logger, m, colleagues.registry->getNameForUser(colleagues.registry->getMyUserID())); 00369 m << "AllPossibleGroupsGrouper: calculated all possible groups, that's " 00370 << allPossibleGroups.size() 00371 << " groups"; 00372 MESSAGE_END(); 00373 00374 // now that I have all the possible groups that can build the partition 00375 Partition bestGrouping = makeGrouping(maxBeams, userVector.size()); 00376 00377 // now the currentBestGrouping is set to the best grouping 00378 // from that I have to construct the Grouping data structure that I have to 00379 // return 00380 00381 return convertPartitionToGrouping(bestGrouping, tx, userVector); 00382 } 00383 00393 Grouping 00394 AllPossibleGroupsGrouper::getRxGrouping(const UserSet activeUsers , int maxBeams) { 00395 assure(dynamic_cast<wns::service::phy::ofdma::DataTransmission*>(friends.ofdmaProvider), 00396 "Grouper needs an OFDMA Provider"); 00397 assure(colleagues.registry, "AllPossibleGroupsGrouper needs a registry"); 00398 00399 std::vector<UserID> userVector = getServableUserVectorFromSet(activeUsers, rx); 00400 allPossibleGroups = calculateAllPossibleGroups(userVector, maxBeams, rx); 00401 00402 MESSAGE_BEGIN(VERBOSE, logger, m, colleagues.registry->getNameForUser(colleagues.registry->getMyUserID())); 00403 m << "AllPossibleGroupsGrouper: calculated all possible groups, that's " 00404 << allPossibleGroups.size() 00405 << " groups"; 00406 MESSAGE_END(); 00407 00408 // now that I have all the possible groups that can build the partition 00409 Partition bestGrouping = makeGrouping(maxBeams, userVector.size()); 00410 00411 // now the currentBestGrouping is set to the optimal grouping 00412 // from that I have to construct the Grouping data structure that I have to 00413 // return 00414 00415 return convertPartitionToGrouping(bestGrouping, rx, userVector); 00416 } 00417 00418 00419
1.5.5