wns::scheduler::PowerCapabilities Strategy::getPowerCapabilities(const UserID user) const { /* This method changes the state "schedulerState->powerCapabilities". This is good and ok if all users are the same (default of all systems), but if they are different (future), APC must call this function anytime. */ switch (schedulerState->powerControlType) { case PowerControlDLMaster: { schedulerState->powerCapabilities = colleagues.registry->getPowerCapabilities(); break; } case PowerControlULMaster: { // peer unknown. Assume peer=UT. if (!user.isValid()) { MESSAGE_SINGLE(NORMAL, logger, "getPowerCapabilities(NULL): asking registry..."); schedulerState->powerCapabilities = colleagues.registry->getPowerCapabilities(user); MESSAGE_SINGLE(NORMAL, logger, "getPowerCapabilities(NULL): nominal=" << schedulerState->powerCapabilities.nominalPerSubband); return schedulerState->powerCapabilities; } schedulerState->powerCapabilities = colleagues.registry->getPowerCapabilities(user); break; } case PowerControlULSlave: { if (schedulerState->defaultTxPower!=wns::Power()) { // don't use powerCapabilities but masterBurst instead assure(schedulerState->defaultTxPower!=wns::Power(),"undefined defaultTxPower"); schedulerState->powerCapabilities.nominalPerSubband = schedulerState->defaultTxPower; schedulerState->powerCapabilities.maxPerSubband = schedulerState->defaultTxPower; // limit not used for slave schedulerState->powerCapabilities.maxOverall = schedulerState->defaultTxPower * 1000.0; } // not given (by masterBurst) because there is an InputSchedulingMap (new method) else { assure(schedulerState->currentState->strategyInput->inputSchedulingMap != wns::scheduler::SchedulingMapPtr(), "need inputSchedulingMap with txPower information"); // the power settings in inputSchedulingMap can be overwritten // if APC strategy is changed to use nominal power. Therefore we need these values: schedulerState->powerCapabilities = colleagues.registry->getPowerCapabilities(); } break; } default: { throw wns::Exception("invalid powerControlType"); } } // switch(powerControlType) if (user.isValid()) { MESSAGE_SINGLE(NORMAL, logger, "getPowerCapabilities(" << user.getName() << "): nominal=" << schedulerState->powerCapabilities.nominalPerSubband); } else { MESSAGE_SINGLE(NORMAL, logger, "getPowerCapabilities(NULL): nominal=" << schedulerState->powerCapabilities.nominalPerSubband); } assure(schedulerState->powerCapabilities.nominalPerSubband != wns::Power(), "undefined power nominalPerSubband="<<schedulerState->powerCapabilities.nominalPerSubband); return schedulerState->powerCapabilities; }
std::priority_queue<ProportionalFair::UserPreference> ProportionalFair::calculateUserPreferences(UserSet activeUsers, bool txStrategy) const { std::map<UserID, ChannelQualityOnOneSubChannel> sinrs; // preference for every user in a priority queue which automatically sorts std::priority_queue<UserPreference> preferences; assure(preferences.size()==0, "preferences.size() must be 0"); for ( UserSet::const_iterator iter = activeUsers.begin(); iter != activeUsers.end(); ++iter) { UserID user = *iter; assure(user.isValid(), "No valid user"); //determines the users SINRs depending on the tx/Rx mode of the strategy if (txStrategy) { sinrs[user] = colleagues.registry->estimateTxSINRAt(user); } else { sinrs[user] = colleagues.registry->estimateRxSINROf(user); } // calculate PhyModeRate for available users wns::Ratio sinr(sinrs[user].carrier / sinrs[user].interference); wns::service::phy::phymode::PhyModeInterfacePtr phyMode = colleagues.registry->getPhyModeMapper()->getBestPhyMode(sinr); assure(phyMode->isValid(),"invalid PhyMode"); // calculate userRate, which is the maximum possible data rate // for one subChannel for the best PhyMode available here float phyModeRate = phyMode->getDataRate(); // rate [b/s] of one subChannel float referenceRate; float pastDataRate = 1.0; // get the past data rate for this user: // iterate over the global past data rates map of all users and // find the past data rate for this user // there is exactly one pastDataRate value per userID int weight = colleagues.registry->getTotalNumberOfUsers(user); for (std::map<UserID, float>::const_iterator iter = pastDataRates.begin(); iter != pastDataRates.end(); ++iter) { if (iter->first/*userID*/ == user) { float dataRate = iter->second; // a RN must get a better share of the bandwidth // here: proportional to its number of users: assure(weight>0, "numberOfUsers(" <<user.getName()<<")=" << weight); dataRate /= static_cast<float>(weight); // dataRate now has the meaning of a weight. pastDataRate = dataRate; } } // for all userIDs in pastDataRates if (pastDataRate < 0.01) pastDataRate = 0.01; // preference is achievable current user rate divided by a history // factor that takes the past throughput of this user into account assure(maxRateOfSubchannel>0.0, "unknown maxRateOfSubchannel"); // goal is either rate (true) or resource (false) fairness if (rateFairness == true) { referenceRate = maxRateOfSubchannel; } else { referenceRate = phyModeRate; } // maxRateOfSubchannel is constant, with range [0..1][bit/s] float resultMaxThroughput = referenceRate / maxRateOfSubchannel; float resultPropFair = referenceRate / pastDataRate; // can be any range if (scalingBetweenMaxTPandPFair <= 0.5) { // variate the preference for each user, so that they differ a little bit (1%) // and the automatic sorting does not always give the same order // (would be a problem for identical preference weights). resultMaxThroughput *= (1 + 0.01*(*preferenceVariationDistribution)()); } float UserPref = (1.0-scalingBetweenMaxTPandPFair) * resultMaxThroughput +scalingBetweenMaxTPandPFair * resultPropFair; MESSAGE_SINGLE(NORMAL, logger, "getPreference("<<user.getName()<<"): weight=" << weight << ", pastDataRate= "<<pastDataRate<<" bit/s, UserPreference= "<<UserPref<<" (resultMaxThroughput="<<resultMaxThroughput<<",resultProportionalFair="<<resultPropFair<<")"); // calculate preferences for users and order them preferences.push(UserPreference(UserPref, user)); } return preferences; }