![]() |
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/DoAGrouper.hpp> 00029 00030 #include <WNS/pyconfig/View.hpp> 00031 #include <WNS/StaticFactory.hpp> 00032 #include <WNS/CandI.hpp> 00033 00034 #include <list> 00035 #include <math.h> 00036 #include <algorithm> 00037 00038 using namespace wns::scheduler; 00039 using namespace wns::scheduler::grouper; 00040 00041 DoATreeBasedGrouper::DoATreeBasedGrouper(const wns::pyconfig::View& config) 00042 : TreeBasedGrouper(config), 00043 strategy(config.get<int>("strategy")) 00044 {} 00045 00046 float 00047 DoATreeBasedGrouper::getNormalizedDoA(UserID user) 00048 { 00049 float angle = this->friends.ofdmaProvider->estimateDoA(user.getNode()); 00050 00051 if (angle < 0.0) 00052 angle += 2*M_PI; 00053 return angle; 00054 } 00055 00056 00057 float 00058 DoATreeBasedGrouper::groupingCost(UserSet group, UserSet newGroup, 00059 ModeType /* mode */) { 00060 float total = 0.0; 00061 std::vector<float> costs; 00062 costs.clear(); 00063 00064 for (UserSet::const_iterator iter = newGroup.begin(); 00065 iter != newGroup.end(); ++iter) { 00066 float cost = groupingCostForAUser(group, *iter); 00067 costs.push_back(cost); 00068 total += cost; 00069 } 00070 00071 switch (strategy) { 00072 case 0: { 00073 // returns the average cost 00074 return total / float(newGroup.size()); 00075 break; 00076 } 00077 case 1: { 00078 // returns the maximum cost a group member experiences 00079 int maxIndex = max_element(costs.begin(), costs.end()) - costs.begin(); 00080 return costs[maxIndex]; 00081 break; 00082 } 00083 default:{ 00084 assure(0,"Wrong strategy"); 00085 } 00086 } 00087 assure(0, "Control structure meltdown"); 00088 return 0.0; // not reached 00089 } 00090 00091 00092 00093 Grouping 00094 DoATreeBasedGrouper::treeAlgorithm(const UserSet activeUsers, unsigned int maxBeams, ModeType mode) 00095 { 00096 std::vector<TreeLevel> treeLevels; 00097 std::map<float, std::pair<unsigned int, unsigned int> > costs; 00098 00099 // init the first level 00100 TreeLevel firstLevel; 00101 for (UserSet::const_iterator iter = activeUsers.begin(); 00102 iter != activeUsers.end(); ++iter) { 00103 UserSet oneUserGroup; 00104 00105 oneUserGroup.clear(); 00106 oneUserGroup.insert(*iter); 00107 00108 std::map<UserID, wns::CandI> candis = 00109 getCandIsForGroup(oneUserGroup, mode); 00110 00111 assure(candis.find(*iter) != candis.end(), "Where is my user gone?"); 00112 00113 // make sure we don't include users that can't even get a suitable SINR 00114 // when served alone 00115 wns::Ratio sinr(candis[*iter].C / candis[*iter].I); 00116 //if (colleagues.registry->getPhyModeForSIR( candis[*iter].C / candis[*iter].I ).second > 0.0001) 00117 //if (phymode->getRate() > 0.0001) 00118 if (colleagues.phyModeMapper->sinrIsAboveLimit(sinr)) 00119 { 00120 individualCandIs[*iter] = candis[*iter]; 00121 firstLevel.push_back(oneUserGroup); 00122 } else { 00123 // FIXME(fds)... 00124 // LOG_INFO("discarding user ", colleagues.registry->getNameForUser(*iter), " because even alone its SINR is too bad for transmission"); 00125 } 00126 } 00127 int maxTreeHeight = firstLevel.size(); 00128 treeLevels.push_back(firstLevel); 00129 00130 // then build the next higher levels by joining the two best-joinable groups 00131 // from the previous level 00132 for (int i = 0; i < maxTreeHeight; ++i) 00133 { 00134 costs.clear(); 00135 // get all possible combinations of two groups, but don't calculate same 00136 // group twice 00137 for (unsigned int g1 = 0; g1 < treeLevels[i].size() - 1; ++g1) 00138 for (unsigned int g2 = g1+1; g2 < treeLevels[i].size(); ++g2) 00139 if (treeLevels[i][g1].size() + treeLevels[i][g2].size() <= maxBeams) 00140 // cost function is overwritten by specialized TreeGrouper variant 00141 costs[groupingCost(treeLevels[i][g1], treeLevels[i][g2], mode)] = 00142 std::make_pair<unsigned int, unsigned int>(g1,g2); 00143 // assure(costs.size(), "Not on upmost level but all groups too big 00144 // to join"); 00145 if (costs.size() == 0) // could not join two groups, so we are done 00146 break; 00147 00148 std::pair<unsigned int, unsigned int> bestCombi = min_element(costs.begin(), costs.end())->second; 00149 00150 // build the next level 00151 TreeLevel nextLevel; 00152 00153 // first join the the two best joinable groups and then save it 00154 UserSet newGroup = treeLevels[i][bestCombi.first]; 00155 newGroup.insert(treeLevels[i][bestCombi.second].begin(), 00156 treeLevels[i][bestCombi.second].end()); 00157 nextLevel.push_back(newGroup); 00158 00159 // then add the others 00160 for(unsigned int g = 0; g < treeLevels[i].size(); ++g) 00161 if ((g != bestCombi.first) && (g != bestCombi.second)) 00162 nextLevel.push_back(treeLevels[i][g]); 00163 00164 treeLevels.push_back(nextLevel); 00165 // continue with the just constructed next level 00166 } 00167 00168 // get the TP for the base case (no SDMA) and calculate the average TP per 00169 // slot. This is the reference value for our grouping gain 00170 float trivialTP = getTPfromTreeLevelByMode(treeLevels[0], mode); 00171 float normalizedTrivialTP = trivialTP / float(treeLevels[0].size()); 00172 00173 std::vector<float> sdmaGain; 00174 sdmaGain.clear(); 00175 sdmaGain.push_back(1.0); // the first level (index 0) is the reference => gain = 1.0 00176 00177 // now calculate the gain (avg TP per group in grouping on each tree level 00178 // divided by the avg TP per one-user-group in the base case 00179 for (unsigned int i = 1; i < treeLevels.size(); ++i) { 00180 sdmaGain.push_back((getTPfromTreeLevelByMode(treeLevels[i], mode) / treeLevels[i].size()) / normalizedTrivialTP); 00181 MESSAGE_SINGLE(NORMAL, logger, "Level " << i << " has gain of " << sdmaGain[i]); 00182 } 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
1.5.5