User Manual, Developers Guide and API Documentation

AllPossibleGroupsGrouper.cpp

Go to the documentation of this file.
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 

Generated on Mon May 21 03:31:54 2012 for openWNS by  doxygen 1.5.5