void DownlinkPacketScheduler::SelectFlowsToSchedule ()
{
#ifdef SCHEDULER_DEBUG
	std::cout << "\t Select Flows to schedule" << std::endl;
#endif

  ClearFlowsToSchedule ();

  RrcEntity *rrc = GetMacEntity ()->GetDevice ()->GetProtocolStack ()->GetRrcEntity ();
  RrcEntity::RadioBearersContainer* bearers = rrc->GetRadioBearerContainer ();


  for (std::vector<RadioBearer* >::iterator it = bearers->begin (); it != bearers->end (); it++)
	{
	  //SELECT FLOWS TO SCHEDULE
	  RadioBearer *bearer = (*it);
	  if (bearer->HasPackets () && bearer->GetDestination ()->GetNodeState () == NetworkNode::STATE_ACTIVE)
		{
		  //compute data to transmit
		  int dataToTransmit;
		  if (bearer->GetApplication ()->GetApplicationType () == Application::APPLICATION_TYPE_INFINITE_BUFFER)
			{
			  dataToTransmit = 100000000;
			}
		  else
			{
			  dataToTransmit = bearer->GetQueueSize ();
			}

		  //compute spectral efficiency
		  ENodeB *enb = (ENodeB*) GetMacEntity ()->GetDevice ();
		  ENodeB::UserEquipmentRecord *ueRecord = enb->GetUserEquipmentRecord (bearer->GetDestination ()->GetIDNetworkNode ());
		  std::vector<double> spectralEfficiency;
		  std::vector<int> cqiFeedbacks = ueRecord->GetCQI ();
		  int numberOfCqi = cqiFeedbacks.size ();
		  for (int i = 0; i < numberOfCqi; i++)
			{
			  double sEff = GetMacEntity ()->GetAmcModule ()->GetEfficiencyFromCQI (cqiFeedbacks.at (i));
			  spectralEfficiency.push_back (sEff);
			}

		  //create flow to scheduler record
		  InsertFlowToSchedule(bearer, dataToTransmit, spectralEfficiency, cqiFeedbacks);
		}
	  else
	    {}
	}
}
double
EnhancedUplinkPacketScheduler::ComputeSchedulingMetric (UserToSchedule* user, int subchannel)
{
  double metric;

  int channelCondition = user->m_channelContition.at (subchannel);
  double spectralEfficiency = GetMacEntity ()->GetAmcModule ()->GetSinrFromCQI (channelCondition);

  metric = spectralEfficiency * 180000;

  return metric;
}
void
DownlinkPacketScheduler::UpdateAverageTransmissionRate (void)
{
  RrcEntity *rrc = GetMacEntity ()->GetDevice ()->GetProtocolStack ()->GetRrcEntity ();
  RrcEntity::RadioBearersContainer* bearers = rrc->GetRadioBearerContainer ();

  for (std::vector<RadioBearer* >::iterator it = bearers->begin (); it != bearers->end (); it++)
    {
      RadioBearer *bearer = (*it);
      bearer->UpdateAverageTransmissionRate ();
    }
}
void
DownlinkPacketScheduler::DoSchedule (void)
{
#ifdef SCHEDULER_DEBUG
	std::cout << "Start DL packet scheduler for node "
			<< GetMacEntity ()->GetDevice ()->GetIDNetworkNode()<< std::endl;
#endif

  UpdateAverageTransmissionRate ();
  SelectFlowsToSchedule ();

  if (GetFlowsToSchedule ()->size() == 0)
	{}
  else
	{
	  RBsAllocation ();
	}

  StopSchedule ();
}
Beispiel #5
0
void
PacketScheduler::CheckForDLDropPackets ()
{
  RrcEntity *rrc = GetMacEntity ()->GetDevice ()->GetProtocolStack ()->GetRrcEntity ();
  RrcEntity::RadioBearersContainer* bearers = rrc->GetRadioBearerContainer ();

  for (std::vector<RadioBearer* >::iterator it = bearers->begin (); it != bearers->end (); it++)
    {
	  //delete packets from queue
	  (*it)->GetMacQueue ()->CheckForDropPackets (
			  (*it)->GetQoSParameters ()->GetMaxDelay (), (*it)->GetApplication ()->GetApplicationID ());

	  //delete fragment waiting in AM RLC entity
	  if ((*it)->GetRlcEntity()->GetRlcModel() == RlcEntity::AM_RLC_MODE)
	    {
		  AmRlcEntity* amRlc = (AmRlcEntity*) (*it)->GetRlcEntity();
		  amRlc->CheckForDropPackets (
				  (*it)->GetQoSParameters ()->GetMaxDelay (), (*it)->GetApplication ()->GetApplicationID ());
	    }
    }
}
void
DL_my_algo_PacketScheduler2::DoStopSchedule (void)
{
#ifdef SCHEDULER_DEBUG
  std::cout << "\t Creating Packet Burst" << std::endl;
#endif

  PacketBurst* pb = new PacketBurst ();

  //Create Packet Burst
  FlowsToSchedule *flowsToSchedule = GetFlowsToSchedule ();

  for (FlowsToSchedule::iterator it = flowsToSchedule->begin (); it != flowsToSchedule->end (); it++)
    {
	  FlowToSchedule *flow = (*it);

	  int availableBytes = flow->GetAllocatedBits ()/8;

	  if (availableBytes > 0)
	    {

		  flow->GetBearer ()->UpdateTransmittedBytes (availableBytes);

#ifdef SCHEDULER_DEBUG
	      std::cout << "\t  --> add packets for flow "
	    		  << flow->GetBearer ()->GetApplication ()->GetApplicationID () << std::endl;
#endif

	      RlcEntity *rlc = flow->GetBearer ()->GetRlcEntity ();
	      PacketBurst* pb2 = rlc->TransmissionProcedure (availableBytes);

#ifdef SCHEDULER_DEBUG
	      std::cout << "\t\t  nb of packets: " << pb2->GetNPackets () << std::endl;
#endif

	      if (pb2->GetNPackets () > 0)
	        {
	    	  std::list<Packet*> packets = pb2->GetPackets ();
	    	  std::list<Packet* >::iterator it;
	    	  for (it = packets.begin (); it != packets.end (); it++)
	    	    {
#ifdef SCHEDULER_DEBUG
	    		  std::cout << "\t\t  added packet of bytes " << (*it)->GetSize () << std::endl;
	    		  //(*it)->Print ();
#endif

	    		  Packet *p = (*it);
	    		  pb->AddPacket (p->Copy ());
	    	    }
	        }
	      delete pb2;
	    }
	  else
	    {}
    }

  //UpdateAverageTransmissionRate ();

  //SEND PACKET BURST

#ifdef SCHEDULER_DEBUG
  if (pb->GetNPackets () == 0)
    std::cout << "\t Send only reference symbols" << std::endl;
#endif

  GetMacEntity ()->GetDevice ()->SendPacketBurst (pb);
}
void
DL_my_algo_PacketScheduler2::RBsAllocation ()
{
#ifdef SCHEDULER_DEBUG
	std::cout << " ---- DL_my_algo_PacketScheduler2::my_algo";
#endif

  FlowsToSchedule* flows = GetFlowsToSchedule ();
  
  int nbOfRBs = GetMacEntity ()->GetDevice ()->GetPhy ()->GetBandwidthManager ()->GetDlSubChannels ().size ();

  //create a matrix of flow metrics
  double metrics[nbOfRBs][flows->size ()];
  /*
  for (int i = 0; i < nbOfRBs; i++)
    {
	  for (int j = 0; j < flows->size (); j++)
	    {
		  metrics[i][j] = ComputeSchedulingMetric (flows->at (j)->GetBearer (),
				                                   flows->at (j)->GetSpectralEfficiency ().at (i),
	    		                                   i);
	    }
    }*/

#ifdef SCHEDULER_DEBUG
  std::cout << ", available RBs " << nbOfRBs << ", flows " << flows->size () << std::endl;
  /*for (int ii = 0; ii < flows->size (); ii++)
    {
	  std::cout << "\t metrics for flow "
			  << flows->at (ii)->GetBearer ()->GetApplication ()->GetApplicationID () << ":";
	  for (int jj = 0; jj < nbOfRBs; jj++)
	    {
		  std::cout << " " << metrics[jj][ii];
	    }
	  std::cout << std::endl;
    }*/
#endif


  AMCModule *amc = GetMacEntity ()->GetAmcModule ();
  double l_dAllocatedRBCounter = 0;

  int l_iNumberOfUsers = ((ENodeB*)this->GetMacEntity()->GetDevice())->GetNbOfUserEquipmentRecords();

  bool * l_bFlowScheduled = new bool[flows->size ()];
  int l_iScheduledFlows = 0;
  std::vector<double> * l_bFlowScheduledSINR = new std::vector<double>[flows->size ()];
  
  int radius=NetworkManager::Init()->GetCellByID (0)->GetRadius()*1000;              //get radius
  std::vector<UserEquipment*>* users = NetworkManager::Init()->GetUserEquipmentContainer();
  int nbUE=users->size();
  int nbCell = NetworkManager::Init()->GetNbCell();
  int nbFlows = total_flow::Init()->get_total_flows();
  const double guarantee_MB=total_flow::Init()->get_data_rate();        
  const double guarantee_bit = (guarantee_MB*1000*8.0)/100 ;            //bit per TTI
  static std::vector<bool> IsCell_Center(nbUE*nbFlows , false);
  static std::vector<double> credit(nbUE,0.0);
  vector<bool> flag(nbUE*nbFlows, false);
  
  for (int i=0;i<nbUE;i++)
  {
        //---------------get ue radius----------
        double x=users->at(i)->GetMobilityModel ()->GetAbsolutePosition()->GetCoordinateX();    //ue x,y position
        double y=users->at(i)->GetMobilityModel ()->GetAbsolutePosition()->GetCoordinateY();
        
        double x1=users->at(i)->GetCell () ->GetCellCenterPosition ()->GetCoordinateX ();       //enb x,y position
        double y1=users->at(i)->GetCell () ->GetCellCenterPosition ()->GetCoordinateY ();
                             
        double ue_radius=sqrt( (x-x1)*(x-x1) + (y-y1)*(y-y1) );          
        //Enb ID = users->at(i)->GetCell ()->GetIdCell()
        //UEid = users->at(i)->GetIDNetworkNode()
                        
        if(ue_radius < radius*2.0/3){
                for(int k=i*nbFlows;k<(i+1)*nbFlows;k++){                             
                        IsCell_Center[k]=true;
                }
        }else{
                for(int k=i*nbFlows;k<(i+1)*nbFlows;k++){                           
                        IsCell_Center[k]=false;
                }
        }           
  }

  //RBs allocation
  std::vector<vector<double> >  my_metrics(nbOfRBs, vector<double>(flows->size ()));
  
  int max_edge_RB=0;
        double edge_demand_bit=0;
        double center_demand_bit=0;
        double total_demand_bit=0;
        for(int k=0;k<flows->size ();k++)
        {
                if(IsCell_Center[flows->at (k)->GetBearer ()->GetApplication ()->GetApplicationID ()]==false){
                      edge_demand_bit+=flows->at (k)->GetDataToTransmit(); 
                }else{
                        center_demand_bit+=flows->at (k)->GetDataToTransmit();
                }
        }
        if( ( edge_demand_bit/(edge_demand_bit + center_demand_bit) ) * nbOfRBs <  1.0/5.0*nbOfRBs){
                max_edge_RB=( edge_demand_bit/( edge_demand_bit + center_demand_bit) ) * nbOfRBs;
        } else{
                max_edge_RB=1.0/5.0*nbOfRBs;
        }
        total_demand_bit = edge_demand_bit + center_demand_bit;
        
   vector<double> copy_credit(nbUE , 0.0 );
   copy_credit.assign(credit.begin(), credit.end());
   for(int i=0;i<nbUE;i++){
        if(copy_credit[i]>0){
               copy_credit[i]=0; 
        }
   } 
   double min= *min_element(copy_credit.begin(), copy_credit.end());
   for(int i=0;i<nbUE;i++){
        copy_credit[i]-=min;
   }

   double max= *max_element(copy_credit.begin(), copy_credit.end());
   if(max==0){
        max=1;
   }
   double sum_credit=0;
   for(int i=0;i<nbUE;i++){
        //cout << "copy_credit[" << i << "] = " << copy_credit[i]/max << endl;
        sum_credit+=(2-copy_credit[i]/max);
   }

  vector<double> cqi(flows->size (),0.0);
  for (int j = 0; j < flows->size (); j++)
  {
      for (int s = 0; s < nbOfRBs; s++)
      { 
            cqi.at(j)+=flows->at (j)->GetCqiFeedbacks ().at(s);
      }
      cqi.at(j)/=nbOfRBs;
  }
  

  for (int s = 0; s < nbOfRBs; s++)
  {
      for (int j = 0; j < flows->size (); j++)
      {            
	        my_metrics[s][j] = mlwdf_ComputeSchedulingMetric (flows->at (j)->GetBearer (),
	                                   flows->at (j)->GetSpectralEfficiency ().at (s),
		                                   s,copy_credit[flows->at (j)->GetBearer ()->GetApplication ()->GetApplicationID ()/nbFlows]/max ,
                                                      sum_credit/nbUE ,flows->at (j)->GetDataToTransmit(),flows->at (j)->GetCqiFeedbacks ().at(s)/cqi.at(j));
      }
      
      for (int j = 0; j < flows->size (); j++)
      {
                metrics[s][j] = ComputeSchedulingMetric1 (flows->at (j)->GetBearer (),
                                           flows->at (j)->GetSpectralEfficiency ().at (s),
   		                                   s,flows->at (j)->GetDataToTransmit(),
		                                   total_demand_bit,copy_credit[flows->at (j)->GetBearer ()->GetApplication ()->GetApplicationID ()/nbFlows]/max ,
                                                      sum_credit/nbUE);
      }
	    
      if (l_iScheduledFlows == flows->size ())
          break;

      double targetMetric = 0;
      bool RBIsAllocated = false;
      FlowToSchedule* scheduledFlow;
      int l_iScheduledFlowIndex = 0;
      
      //std::cout << "avg_cqi = " << avg_cqi << std::endl;

      RBIsAllocated = false;
      if(s<max_edge_RB)
      {
            targetMetric=-1;
            for(int k=0;k<flows->size ();k++)
            {          
                if(metrics[s][k] > targetMetric && !l_bFlowScheduled[k] && flows->at (k)->GetDataToTransmit() >0 
                        && IsCell_Center[flows->at (k)->GetBearer ()->GetApplication ()->GetApplicationID ()]==false)
                {
                        targetMetric=metrics[s][k];
                        RBIsAllocated = true;
                        scheduledFlow = flows->at (k);
                        l_iScheduledFlowIndex = k;
                }
            }
            if(!RBIsAllocated)
            {
                targetMetric=-1;
                for(int k=0;k<flows->size ();k++)
                {
                        if(my_metrics[s][k] > targetMetric && !l_bFlowScheduled[k] && flows->at (k)->GetDataToTransmit() >0 )
                        {
                                targetMetric=my_metrics[s][k];
                                RBIsAllocated = true;
                                scheduledFlow = flows->at (k);
                                l_iScheduledFlowIndex = k;
                        }
                }        
            }
      }else
      {
           targetMetric=-1;
           l_iScheduledFlowIndex=0;
           for (int k = 0; k < flows->size (); k++)
           {    
               if (my_metrics[s][k] > targetMetric && !l_bFlowScheduled[k] && flows->at (k)->GetDataToTransmit() >0 )
               {
                        targetMetric = my_metrics[s][k];
                        RBIsAllocated = true;
                        scheduledFlow = flows->at (k);
                        l_iScheduledFlowIndex = k;               
                        //std::cout << "\tschedule to flow : " << flows->at (k)->GetBearer ()->GetApplication ()->GetApplicationID () << std::endl;  
               }                   
           }     
      }

        
      if (RBIsAllocated)
        {
          l_dAllocatedRBCounter++;

          scheduledFlow->GetListOfAllocatedRBs()->push_back (s); // the s RB has been allocated to that flow!

#ifdef SCHEDULER_DEBUG
         /* std::cout << "\t *** RB " << s << " assigned to the "
                  " flow " << scheduledFlow->GetBearer ()->GetApplication ()->GetApplicationID ()
                  << std::endl;*/
            std::cout << "\t *** RB " << s << " assigned to the "
                  " flow " << scheduledFlow->GetBearer ()->GetApplication ()->GetApplicationID ()
                  << "  cqi   " << scheduledFlow->GetCqiFeedbacks ().at (s)
                  << "  cell_center  " << IsCell_Center[scheduledFlow->GetBearer ()->GetApplication ()->GetApplicationID ()]
                  << std::endl;
#endif
          double sinr = amc->GetSinrFromCQI (scheduledFlow->GetCqiFeedbacks ().at (s));
          l_bFlowScheduledSINR[l_iScheduledFlowIndex].push_back(sinr);

          double effectiveSinr = GetEesmEffectiveSinr (l_bFlowScheduledSINR[l_iScheduledFlowIndex]);
          int mcs = amc->GetMCSFromCQI (amc->GetCQIFromSinr (effectiveSinr));
          int transportBlockSize = amc->GetTBSizeFromMCS (mcs, scheduledFlow->GetListOfAllocatedRBs ()->size ());
          if (transportBlockSize >= scheduledFlow->GetDataToTransmit() * 8)
          {
             #ifdef SCHEDULER_DEBUG   
              cout << "-- FLOW " << scheduledFlow->GetBearer ()->GetApplication ()->GetApplicationID () << ", demand = " << scheduledFlow->GetDataToTransmit()*8 << ", transportBlockSize = " 
              << transportBlockSize << endl;
              #endif
              l_bFlowScheduled[l_iScheduledFlowIndex] = true;
              l_iScheduledFlows++;
          }
        }
    }

  delete [] l_bFlowScheduled;
  delete [] l_bFlowScheduledSINR;


  //Finalize the allocation
  PdcchMapIdealControlMessage *pdcchMsg = new PdcchMapIdealControlMessage ();

  for (FlowsToSchedule::iterator it = flows->begin (); it != flows->end (); it++)
    {
      FlowToSchedule *flow = (*it);
      if (flow->GetListOfAllocatedRBs ()->size () > 0)
        {
          //cout << "----------------------------------" << endl;
          //this flow has been scheduled
          std::vector<double> estimatedSinrValues;
          for (int rb = 0; rb < flow->GetListOfAllocatedRBs ()->size (); rb++ )

            {
              double sinr = amc->GetSinrFromCQI (
                      flow->GetCqiFeedbacks ().at (flow->GetListOfAllocatedRBs ()->at (rb)));
	      //cout << "CQI = " << flow->GetCqiFeedbacks ().at (flow->GetListOfAllocatedRBs ()->at (rb)) << endl;
              estimatedSinrValues.push_back (sinr);
            }

          //compute the effective sinr
          double effectiveSinr = GetEesmEffectiveSinr (estimatedSinrValues);

          //get the MCS for transmission
          //cout << "effectiveCQI = " << amc->GetCQIFromSinr (effectiveSinr) << endl;
          int mcs = amc->GetMCSFromCQI (amc->GetCQIFromSinr (effectiveSinr));

          //define the amount of bytes to transmit
          //int transportBlockSize = amc->GetTBSizeFromMCS (mcs);
          int transportBlockSize = amc->GetTBSizeFromMCS (mcs, flow->GetListOfAllocatedRBs ()->size ());
          double bitsToTransmit = transportBlockSize;
          flow->UpdateAllocatedBits (bitsToTransmit);

#ifdef SCHEDULER_DEBUG
		  std::cout << "\t\t --> flow "	<< flow->GetBearer ()->GetApplication ()->GetApplicationID ()
				  << " has been scheduled: " <<
				  "\n\t\t\t nb of RBs " << flow->GetListOfAllocatedRBs ()->size () <<
				  "\n\t\t\t effectiveSinr " << effectiveSinr <<
				  "\n\t\t\t tbs " << transportBlockSize <<
				  "\n\t\t\t bitsToTransmit " << bitsToTransmit
				  << std::endl;
#endif

                credit[flow->GetBearer ()->GetApplication ()->GetApplicationID()/nbFlows]+=bitsToTransmit;               //new add

		  //create PDCCH messages
		  for (int rb = 0; rb < flow->GetListOfAllocatedRBs ()->size (); rb++ )
		    {
			  pdcchMsg->AddNewRecord (PdcchMapIdealControlMessage::DOWNLINK,
					  flow->GetListOfAllocatedRBs ()->at (rb),
									  flow->GetBearer ()->GetDestination (),
									  mcs);
		    }
	    }
    }

  if (pdcchMsg->GetMessage()->size () > 0)
    {
      GetMacEntity ()->GetDevice ()->GetPhy ()->SendIdealControlMessage (pdcchMsg);
    }
  delete pdcchMsg;
        
        for (int i = 0; i< nbUE ; i++ )                         //new add
	{
	        credit[i]-=guarantee_bit;
                //cout << "credit[" << i << "] = " << credit[i] << endl;
	}       
}
void
EnhancedUplinkPacketScheduler::RBsAllocation ()
{
	/* This is an implementation of an algorithm based on  first maximum expansion algorithm reported in
	 * L. Temiño, G. Berardinelli, S. Frattasi,  and P.E. Mogensen,
	 * "Channel-aware scheduling algorithms for SC-FDMA in LTE uplink",  in Proc. PIMRC 2008
	 * The main difference is that here we have a given number of RB's to allocate to the UE
	 * based on its pending queue status whereas the original attempts to allocate till another
	 * UE has a better channel response
	 */
#ifdef SCHEDULER_DEBUG
	std::cout << " ---- UL RBs Allocation";
#endif

	UsersToSchedule *users = GetUsersToSchedule ();
	UserToSchedule* scheduledUser;
	int nbOfRBs = GetMacEntity ()->GetDevice ()->GetPhy ()->GetBandwidthManager ()->GetUlSubChannels ().size ();

	int availableRBs;     // No of RB's not allocated
	int unallocatedUsers; // No of users who remain unallocated
	int selectedUser;     // user to be selected for allocation
	int selectedPRB;      // PRB to be selected for allocation
	double bestMetric;    // best metric to identify user/RB combination
	int left, right;      // index of left and left PRB's to check
	bool Allocated[nbOfRBs];
	bool allocationMade;
	double metrics[nbOfRBs][users->size ()];
	int requiredPRBs[users->size ()];


	//Some initialization
	availableRBs = nbOfRBs;
	unallocatedUsers = users->size ();
	for(int i=0; i < nbOfRBs; i++)
		Allocated[i] = false;

	//create a matrix of flow metrics
	for (int i = 0; i < nbOfRBs; i++)
	{
		for (int j = 0; j < users->size (); j++)
		{
			metrics[i][j] = ComputeSchedulingMetric (users->at (j), i);
		}
	}

	//create number of required PRB's per scheduled users
	for(int j=0; j < users->size(); j++)
	{
		scheduledUser = users->at(j);
#ifdef SCHEDULER_DEBUG
		cout << "\n" << "User "  << j; // << "CQI Vector";
#endif

		std::vector<double> sinrs;
		for (std::vector<int>::iterator c = scheduledUser->m_channelContition.begin ();
				c != scheduledUser->m_channelContition.end (); c++)
		{
			//cout << *c <<" ";
			sinrs.push_back (GetMacEntity ()->GetAmcModule ()->GetSinrFromCQI (*c));
		}


		double effectiveSinr =  GetEesmEffectiveSinr (sinrs);

		int mcs = GetMacEntity ()->GetAmcModule ()->GetMCSFromCQI (
			  GetMacEntity ()->GetAmcModule ()->GetCQIFromSinr (effectiveSinr));
		scheduledUser->m_selectedMCS = mcs;
		requiredPRBs[j] = (floor) (scheduledUser->m_dataToTransmit /
				  (GetMacEntity ()->GetAmcModule ()->GetTBSizeFromMCS (mcs, 1) / 8));
#ifdef SCHEDULER_DEBUG
		cout << " EffSINR = " << effectiveSinr << "  MCS = " << mcs << "\n";
#endif
	}

#ifdef SCHEDULER_DEBUG
  //std::cout << ", available RBs " << nbOfRBs << ", users " << users->size () << std::endl;
  for (int ii = 0; ii < users->size (); ii++)
    {
	  std::cout << "Metrics for user "
			  << users->at (ii)->m_userToSchedule->GetIDNetworkNode () << "\n";
	  for (int jj = 0; jj < nbOfRBs; jj++)
	    {
		  //std::cout  << setw(3) << metrics[jj][ii]/1000 << " ";
		  printf("%3d  ", (int) (metrics[jj][ii]/1000.0));
	    }
	  std::cout << std::endl;
    }
#endif

  //RBs allocation

  while(availableRBs > 0 && unallocatedUsers > 0) //
  {
	  // First step: find the best user-RB combo
	  selectedPRB = -1;
	  selectedUser = -1;
	  bestMetric = (double) (-(1<<30));

	  for(int i=0; i < nbOfRBs; i++)
	  {
		  if (!Allocated[i]){ // check only unallocated PRB's
			  for(int j=0; j < users->size (); j++)
			  {
				  if ( users->at (j)->m_listOfAllocatedRBs.size() == 0
						  && requiredPRBs[j] > 0) //only unallocated users requesting some RB's
					  if (bestMetric < metrics[i][j]){
						  selectedPRB = i;
						  selectedUser = j;
						  bestMetric = metrics[i][j];
					  }
			  }

		  }
	  }
	  // Now start allocating for the selected user at the selected PRB the required blocks
	  // using how many PRB's are needed for the user
	  if (selectedUser != -1)
	  {
		  scheduledUser = users->at(selectedUser);
		  scheduledUser->m_listOfAllocatedRBs.push_back (selectedPRB);
		  Allocated[selectedPRB] = true;
		  left =  selectedPRB - 1;
		  right = selectedPRB + 1;
		  availableRBs--;
		  unallocatedUsers--;

		  allocationMade = true;
		  for(int i = 1; i < requiredPRBs[selectedUser] && availableRBs > 0 && allocationMade; i++ )
		  { // search right and left of initial allocation
			  allocationMade = false;
			  if (left >=0 && Allocated[left] && right < nbOfRBs && Allocated[right])
				  break; // nothing is available, since we need to have contiguous allocation

			  if (    (right < nbOfRBs) && (! Allocated[right]) &&
					  (
							  ((left >=0) &&
							  (metrics[right][selectedUser] >= metrics[left][selectedUser])) // right is better than left
							  || (left < 0) || Allocated[left]// OR no more left
					  )
				)
			  {
				  //Allocate PRB at right to the user
				  Allocated[right] = true;
				  scheduledUser->m_listOfAllocatedRBs.push_back (right);
				  right++;
				  allocationMade = true;
				  availableRBs--;
			  } else if ( (left >=0) && (! Allocated[left]) &&
						  (
							  ((right < nbOfRBs) &&
							  (metrics[left][selectedUser] > metrics[right][selectedUser])) //left better than right
							  || (right >= nbOfRBs) || Allocated[right]// OR no more right
						   )
						)
			  {
				  //Allocate PRB at left to the user
				  Allocated[left] = true;
				  scheduledUser->m_listOfAllocatedRBs.push_back (left);
				  left--;
				  allocationMade = true;
				  availableRBs--;
			  }
		  } // end of for
		  if (allocationMade){
			  scheduledUser->m_transmittedData = GetMacEntity ()->GetAmcModule ()->
					  GetTBSizeFromMCS (scheduledUser->m_selectedMCS, scheduledUser->m_listOfAllocatedRBs.size()) / 8;
#ifdef SCHEDULER_DEBUG
			  printf("Scheduled User = %d mcs = %d Required RB's = %d Allocated RB's= %d\n",
		 				  scheduledUser->m_userToSchedule->GetIDNetworkNode(),
		 				  scheduledUser->m_selectedMCS,
		 				  requiredPRBs[selectedUser], scheduledUser->m_listOfAllocatedRBs.size() );
			  for(int i=0; i<scheduledUser->m_listOfAllocatedRBs.size(); i++)
				  printf("%d ", scheduledUser->m_listOfAllocatedRBs.at(i));
			  printf("\n------------------\n");
#endif
		  }
	  } else { // nothing to do exit the allocation loop
		  break;
	  }
  } //while

}
void
DownlinkPacketScheduler::RBsAllocation ()
{
#ifdef SCHEDULER_DEBUG
	std::cout << " ---- DownlinkPacketScheduler::RBsAllocation";
#endif


  FlowsToSchedule* flows = GetFlowsToSchedule ();
  int nbOfRBs = GetMacEntity ()->GetDevice ()->GetPhy ()->GetBandwidthManager ()->GetDlSubChannels ().size ();

  //create a matrix of flow metrics
  double metrics[nbOfRBs][flows->size ()];
  for (int i = 0; i < nbOfRBs; i++)
    {
	  for (int j = 0; j < flows->size (); j++)
	    {
		  metrics[i][j] = ComputeSchedulingMetric (flows->at (j)->GetBearer (),
				                                   flows->at (j)->GetSpectralEfficiency ().at (i),
	    		                                   i);
	    }
    }

#ifdef SCHEDULER_DEBUG
  std::cout << ", available RBs " << nbOfRBs << ", flows " << flows->size () << std::endl;
  for (int ii = 0; ii < flows->size (); ii++)
    {
	  std::cout << "\t metrics for flow "
			  << flows->at (ii)->GetBearer ()->GetApplication ()->GetApplicationID () << ":";
	  for (int jj = 0; jj < nbOfRBs; jj++)
	    {
		  std::cout << " " << metrics[jj][ii];
	    }
	  std::cout << std::endl;
    }
#endif


  AMCModule *amc = GetMacEntity ()->GetAmcModule ();
  double l_dAllocatedRBCounter = 0;

  int l_iNumberOfUsers = ((ENodeB*)this->GetMacEntity()->GetDevice())->GetNbOfUserEquipmentRecords();

  bool * l_bFlowScheduled = new bool[flows->size ()];
  int l_iScheduledFlows = 0;
  std::vector<double> * l_bFlowScheduledSINR = new std::vector<double>[flows->size ()];
  for (int k = 0; k < flows->size (); k++)
      l_bFlowScheduled[k] = false;

  //RBs allocation
  for (int s = 0; s < nbOfRBs; s++)
    {
      if (l_iScheduledFlows == flows->size ())
          break;

      double targetMetric = 0;
      bool RBIsAllocated = false;
      FlowToSchedule* scheduledFlow;
      int l_iScheduledFlowIndex = 0;

      for (int k = 0; k < flows->size (); k++)
        {
          if (metrics[s][k] > targetMetric && !l_bFlowScheduled[k]  && flows->at (k)->GetDataToTransmit() >0 )
            {
              targetMetric = metrics[s][k];
              RBIsAllocated = true;
              scheduledFlow = flows->at (k);
              l_iScheduledFlowIndex = k;
            }
        }

      if (RBIsAllocated)
        {
          l_dAllocatedRBCounter++;

          scheduledFlow->GetListOfAllocatedRBs()->push_back (s); // the s RB has been allocated to that flow!

#ifdef SCHEDULER_DEBUG
          std::cout << "\t *** RB " << s << " assigned to the "
                  " flow " << scheduledFlow->GetBearer ()->GetApplication ()->GetApplicationID ()
                  << std::endl;
#endif
          double sinr = amc->GetSinrFromCQI (scheduledFlow->GetCqiFeedbacks ().at (s));
          l_bFlowScheduledSINR[l_iScheduledFlowIndex].push_back(sinr);

          double effectiveSinr = GetEesmEffectiveSinr (l_bFlowScheduledSINR[l_iScheduledFlowIndex]);
          int mcs = amc->GetMCSFromCQI (amc->GetCQIFromSinr (effectiveSinr));
          int transportBlockSize = amc->GetTBSizeFromMCS (mcs, scheduledFlow->GetListOfAllocatedRBs ()->size ());
          if (transportBlockSize >= scheduledFlow->GetDataToTransmit() * 8)
          {
              l_bFlowScheduled[l_iScheduledFlowIndex] = true;
              l_iScheduledFlows++;
          }

        }
    }

  delete [] l_bFlowScheduled;
  delete [] l_bFlowScheduledSINR;


  //Finalize the allocation
  PdcchMapIdealControlMessage *pdcchMsg = new PdcchMapIdealControlMessage ();

  for (FlowsToSchedule::iterator it = flows->begin (); it != flows->end (); it++)
    {
      FlowToSchedule *flow = (*it);
      if (flow->GetListOfAllocatedRBs ()->size () > 0)
        {
          //this flow has been scheduled
          std::vector<double> estimatedSinrValues;
          for (int rb = 0; rb < flow->GetListOfAllocatedRBs ()->size (); rb++ )

            {
              double sinr = amc->GetSinrFromCQI (
                      flow->GetCqiFeedbacks ().at (flow->GetListOfAllocatedRBs ()->at (rb)));

              estimatedSinrValues.push_back (sinr);
            }

          //compute the effective sinr
          double effectiveSinr = GetEesmEffectiveSinr (estimatedSinrValues);

          //get the MCS for transmission

          int mcs = amc->GetMCSFromCQI (amc->GetCQIFromSinr (effectiveSinr));

          //define the amount of bytes to transmit
          //int transportBlockSize = amc->GetTBSizeFromMCS (mcs);
          int transportBlockSize = amc->GetTBSizeFromMCS (mcs, flow->GetListOfAllocatedRBs ()->size ());
          double bitsToTransmit = transportBlockSize;
          flow->UpdateAllocatedBits (bitsToTransmit);

#ifdef SCHEDULER_DEBUG
		  std::cout << "\t\t --> flow "	<< flow->GetBearer ()->GetApplication ()->GetApplicationID ()
				  << " has been scheduled: " <<
				  "\n\t\t\t nb of RBs " << flow->GetListOfAllocatedRBs ()->size () <<
				  "\n\t\t\t effectiveSinr " << effectiveSinr <<
				  "\n\t\t\t tbs " << transportBlockSize <<
				  "\n\t\t\t bitsToTransmit " << bitsToTransmit
				  << std::endl;
#endif

		  //create PDCCH messages
		  for (int rb = 0; rb < flow->GetListOfAllocatedRBs ()->size (); rb++ )
		    {
			  pdcchMsg->AddNewRecord (PdcchMapIdealControlMessage::DOWNLINK,
					  flow->GetListOfAllocatedRBs ()->at (rb),
									  flow->GetBearer ()->GetDestination (),
									  mcs);
		    }
	    }
    }

  if (pdcchMsg->GetMessage()->size () > 0)
    {
      GetMacEntity ()->GetDevice ()->GetPhy ()->SendIdealControlMessage (pdcchMsg);
    }
  delete pdcchMsg;
}