Пример #1
0
    def test_optimPCDTX(self):
        # test for simple problem with known outcome
        H = np.array([[[1. - 1j, -1.], [-1., 1.]], [[1. - 1j, 1.], [-1., 1.]],
                      [[0.5, 1.j], [1., -1.j]]])
        for k in np.arange(3):
            H[k, :, :] = scipy.dot(H[k, :, :], H[k, :, :].conj().T)
        noisepower = np.ones(3)
        rate = 1
        linkBandwidth = 1
        p0 = 10
        m = 2
        pS = 5
        pMax = 10

        obj, solution, status = optimMinPow.optimizePCDTX(
            H, noisepower, rate, linkBandwidth, pMax, p0, m, pS, 0)
        answerObj = 13.9204261
        answerSol = np.array([0.32342002, 0.24371824, 0.27855287, 0.15430887])
        np.testing.assert_almost_equal(obj, answerObj)
        np.testing.assert_almost_equal(solution, answerSol)

        for k in np.arange(H.shape[0]):
            ptx = optimMinPow2x2DTX.ptxOfMu(solution[k], rate, linkBandwidth,
                                            noisepower[k], H[k, :, :])
            rate_test = solution[k] * np.real(
                utils.ergMIMOCapacityCDITCSIR(H[k, :, :], ptx))
            np.testing.assert_almost_equal(rate_test, rate)
Пример #2
0
    def test_optimPCDTX_trivial(self):
        # test for simple problem with known outcome
        H = np.ones([3, 2, 2])
        for k in np.arange(3):
            H[k, :, :] = scipy.dot(H[k, :, :], H[k, :, :].conj().T)
        noisepower = np.ones(3)
        rate = 1
        linkBandwidth = 1
        p0 = 10
        m = 2
        pS = 5
        pMax = 10

        obj, solution, status = optimMinPow.optimizePCDTX(
            H, noisepower, rate, linkBandwidth, pMax, p0, m, pS, 0)
        answerObj = 17.000000115485285
        answerSol = np.array([0.33333334, 0.33333334, 0.33333334, 0.])
        np.testing.assert_almost_equal(obj, answerObj)
        np.testing.assert_almost_equal(solution, answerSol)

        for k in np.arange(H.shape[0]):
            ptx = optimMinPow2x2DTX.ptxOfMu(solution[k], rate, linkBandwidth,
                                            noisepower[k], H[k, :, :])
            rate_test = solution[k] * np.real(
                utils.ergMIMOCapacityCDITCSIR(H[k, :, :], ptx))
            np.testing.assert_almost_equal(rate_test, rate)
Пример #3
0
    def test_optimPCDTXrandomChannel(self):
        # test for simple problem with known outcome
        users = 22
        n_tx = 2
        n_rx = 2
        H = np.empty([users, n_tx, n_rx],
                     dtype=complex)  # very important to make it complex!
        for k in np.arange(users):
            H[k, :, :] = 10e-7 * utils.rayleighChannel(n_tx, n_rx)
            H[k, :, :] = scipy.dot(H[k, :, :], H[k, :, :].conj().T)
        noisepower = np.ones(users) * 4e-14
        rate = 1.2e7 / users  # bps
        linkBandwidth = 1e7
        p0 = 100
        m = 2.4
        pS = 50
        pMax = 40

        obj, solution, status = optimMinPow.optimizePCDTX(
            H, noisepower, rate, linkBandwidth, pMax, p0, m, pS, 0)

        # Test that all calls were correct and their order. What goes in must come out.
        for k in np.arange(users):
            ptx = optimMinPow2x2DTX.ptxOfMu(
                solution[k], rate, linkBandwidth, noisepower[k],
                H[k, :, :])  # power as a function of the MIMO link
            rate_test = solution[k] * np.real(
                utils.ergMIMOCapacityCDITCSIR(
                    H[k, :, :], ptx / noisepower[k])) * linkBandwidth  # bps
            np.testing.assert_almost_equal(rate_test, rate)
Пример #4
0
    def test_optimPCDTX(self):
        # test for simple problem with known outcome
        H = np.array([[[1.-1j,-1.],[-1.,1.]],[[1.-1j,1.],[-1.,1.]],[[0.5,1.j],[1.,-1.j]]])
        for k in np.arange(3):
            H[k,:,:] = scipy.dot(H[k,:,:], H[k,:,:].conj().T)
        noisepower = np.ones(3)
        rate = 1
        linkBandwidth = 1
        p0 = 10
        m = 2
        pS = 5
        pMax = 10

        obj, solution, status = optimMinPow.optimizePCDTX(H, noisepower, rate, linkBandwidth, pMax, p0, m, pS, 0)
        answerObj = 13.9204261
        answerSol = np.array([ 0.32342002,  0.24371824,  0.27855287,  0.15430887])
        np.testing.assert_almost_equal(obj, answerObj)
        np.testing.assert_almost_equal(solution, answerSol)

        for k in np.arange(H.shape[0]):
            ptx = optimMinPow2x2DTX.ptxOfMu(solution[k], rate, linkBandwidth, noisepower[k], H[k,:,:])
            rate_test = solution[k]*np.real(utils.ergMIMOCapacityCDITCSIR(H[k,:,:], ptx))
            np.testing.assert_almost_equal(rate_test, rate)
Пример #5
0
    def test_optimPCDTX_trivial(self):
        # test for simple problem with known outcome
        H = np.ones([3,2,2])
        for k in np.arange(3):
            H[k,:,:] = scipy.dot(H[k,:,:], H[k,:,:].conj().T)
        noisepower = np.ones(3)
        rate = 1
        linkBandwidth = 1
        p0 = 10
        m = 2
        pS = 5
        pMax = 10

        obj, solution, status = optimMinPow.optimizePCDTX(H, noisepower, rate, linkBandwidth, pMax, p0, m, pS, 0)
        answerObj = 17.000000115485285
        answerSol = np.array([ 0.33333334,  0.33333334,  0.33333334,  0.        ])
        np.testing.assert_almost_equal(obj, answerObj)
        np.testing.assert_almost_equal(solution, answerSol)

        for k in np.arange(H.shape[0]):
            ptx = optimMinPow2x2DTX.ptxOfMu(solution[k], rate, linkBandwidth, noisepower[k], H[k,:,:])
            rate_test = solution[k]*np.real(utils.ergMIMOCapacityCDITCSIR(H[k,:,:], ptx))
            np.testing.assert_almost_equal(rate_test, rate)
Пример #6
0
    def test_optimPCDTXrandomChannel(self):
        # test for simple problem with known outcome
        users = 22
        n_tx = 2
        n_rx = 2
        H = np.empty([users, n_tx, n_rx],dtype=complex) # very important to make it complex!
        for k in np.arange(users):
            H[k,:,:] = 10e-7*utils.rayleighChannel(n_tx,n_rx)
            H[k,:,:] = scipy.dot(H[k,:,:], H[k,:,:].conj().T)
        noisepower = np.ones(users) * 4e-14 
        rate = 1.2e7/users # bps
        linkBandwidth = 1e7
        p0 = 100
        m = 2.4
        pS = 50
        pMax = 40
        
        obj, solution, status = optimMinPow.optimizePCDTX(H, noisepower, rate, linkBandwidth, pMax, p0, m, pS, 0)

        # Test that all calls were correct and their order. What goes in must come out.
        for k in np.arange(users):
            ptx = optimMinPow2x2DTX.ptxOfMu(solution[k], rate, linkBandwidth, noisepower[k], H[k,:,:]) # power as a function of the MIMO link
            rate_test = solution[k]*np.real(utils.ergMIMOCapacityCDITCSIR(H[k,:,:], ptx/noisepower[k]))*linkBandwidth # bps
            np.testing.assert_almost_equal(rate_test, rate)
Пример #7
0
def raps(wrld, cell, mobiles, rate, plotting=False):
    """In the cell, allocate powers and sleep modes to mobiles."""
    # need to map algorithm indices to mobile ids (artifact from MATLAB)
    id_map = dict()
    for k, mob in enumerate(mobiles):
        id_map[k] = mob.id_
    
    # Make sure all mobiles are associated with the cell correctly
    for mob in mobiles:
        if mob.cell != cell:
            raise ValueError('Faulty passing of mobiles to RAPS')
    logger.info( '{0:50} {1:5d}'.format('Mobiles in this cell:', len(mobiles)))

    # Build SINR arrays
    users = len(mobiles) 
    N = wrld.PHY.numFreqChunks
    T = wrld.PHY.numTimeslots
    noisePower = wrld.wconf.systemNoisePower

    # EC_Optim contains one MIMO value per mobile (the center chunk effective channel)
    EC_Optim = np.empty([users, cell.antennas, wrld.mobiles[0].antennas], dtype=complex) # TODO Will we ever have mobiles with different numbers of annteas?
    # SINR_Quant contains one value for each RB and user
    SINR_Quant = np.empty([N, T, users]) 
    centerChunkIndex = np.floor(N/2)
    whichTimeslotIndex = list(cell.sleep_slot_priority).index(0)
    for idx, mob in enumerate(mobiles):
        EC_Optim[idx,:,:] = mob.OFDMA_EC[:,:,centerChunkIndex,whichTimeslotIndex] / N # scale this effective channel over all chunks
        SINR_Quant[:,:,idx] = np.mean(mob.OFDMA_effSINR,0) # SINR for RCG 

    ### Step 1 ###
    # Optimization call
    pSupplyOptim, resourceAlloc, status = optimMinPow.optimizePCDTX(EC_Optim, np.ones(EC_Optim.shape[0]), rate, wrld.PHY.systemBandwidth, cell.pMax, mobiles[0].BS.p0, mobiles[0].BS.m, mobiles[0].BS.pS)
    logger.debug( 'Resource Allocation: ' + str(resourceAlloc))
    logger.debug( 'Sleep priority: ' + str(cell.sleep_slot_priority))
    logger.info( '{0:50} {1:5.2f} W'.format('Real-valued optimization objective:', pSupplyOptim) )
    
    ## Plot ##
    if cell.cellid == 12345 and plotting: # center in tier 1
        from plotting import channelplotter
        channelplotter.bar(np.mean(np.mean(EC_Optim,1),1),'Abs mean of MIMO EC Optim', 'sinr_optim.pdf')
        channelplotter.OFDMAchannel(SINR_Quant, 'SINR Quant', 'sinr_quant.pdf')
        channelplotter.bar(resourceAlloc,'Resource Share Optim', 'rscshare.pdf')
        import pdb; pdb.set_trace()
    
    ### Step 2 ###

    # Map real valued solution to OFDMA frame
    # QUANTMAP
    resourcesPerTimeslot = quantmap.quantmap(resourceAlloc, N, T)
    outmap = np.empty([N, T])

    # Handle sleep slot alignment here. 
    resourcesPerTimeslot = resourcesPerTimeslot[cell.sleep_slot_priority]

    # RCG
    for t in np.arange(T):
        outmap[:,t],_ = rcg.rcg(SINR_Quant[:,t,:],resourcesPerTimeslot[t,:]) # outmap.shape = (N,T) tells the user index

    # Given allocation and rate target, we inverse waterfill channels for each user separately on the basis of full SINR 
    # IWF
    powerlvls = np.empty([N, T, mob.antennas])
    powerlvls[:] = np.nan
    
    for idx, obj in enumerate(mobiles): 
        # grab user SINR
        EC_usr = obj.OFDMA_EC[:,:,outmap==idx] # all effective channels assigned to this user
        noiseIfPower_usr = np.real(EC_usr[0,0,:].repeat(2) * 0 + 1) # TODO remove later  #(obj.baseStations[obj.BS].cells[obj.cell].OFDMA_interferencePower + obj.baseStations[obj.BS].cells[obj.cell].OFDMA_noisePower) * np.ones(SINR_user_all[0,0,:,:].shape)[outmap==idx].ravel().repeat(2) # one IF value per resource, so repeat once to match spatial channels
        # create list of eigVals
        eigVals = np.real([linalg.eig(EC_usr[:,:,i])[0] for i in np.arange(EC_usr.shape[2])]).ravel() # two eigvals (spatial channels) per resource
        targetLoad = rate * wrld.PHY.simulationTime 
        # inverse waterfill and fill back to OFDMA position
        powlvl, waterlvl, cap = iwf.inversewaterfill(eigVals, targetLoad, noiseIfPower_usr, wrld.PHY.systemBandwidth / N, wrld.PHY.simulationTime / T)
        powerlvls[outmap==idx,:] = powlvl.reshape(EC_usr.shape[2],obj.antennas)

    ptx = np.array([np.nansum(np.nansum(powerlvls[:,t,:],axis=0),axis=0) for t in np.arange(T)])
    logging.debug('Ptx' + str(ptx))
    if (ptx > cell.pMax).any(): 
        raise ValueError('Transmission power too high in IWF: '+str(ptx)+ ' W')
        
    # Store power levels in cell for next round
    cell.OFDMA_power[:] = np.swapaxes(np.swapaxes(powerlvls[:],1,2),0,1) 
    cell.OFDMA_power[np.isnan(cell.OFDMA_power)] = 0
    # remap to mobile ids
    outmap_ids = np.copy(outmap)
    for k,v in id_map.iteritems():
        outmap_ids[outmap==k] = v
    cell.outmap = outmap_ids
        
    psupplyPerSlot = mobiles[0].BS.p0 + mobiles[0].BS.m * ptx
        
    psupplyPerSlot[np.isnan(psupplyPerSlot)] = mobiles[0].BS.pS
    pSupplyQuant = np.mean(psupplyPerSlot)
    logger.info( '{0:50} {1:5.2f} W'.format('Integer-valued optimization objective:', pSupplyQuant))

    return pSupplyOptim, pSupplyQuant
Пример #8
0
def oneIteration(rate, CSI_Optim, SINR_Quant):
    """Perform one iteration and return the supply powers"""
### Step 1 ###
    # Optimization call
    import pdb; pdb.set_trace()
    
    pSupplyOptim, resourceAlloc, status = optimMinPow.optimizePCDTX(CSI_Optim, PnoiseIf_Optim, rate, wrld.PHY.systemBandwidth, cell.pMax, bs.p0, bs.m, bs.pS)
    print '{0:50} {1:5.2f} W'.format('Real-valued optimization objective:', pSupplyOptim)
    
    ## Plot ##
    if plotting:
        channelplotter.ChannelPlotter().bar(resourceAlloc,'Resource Share Optim', 'rscshare.pdf')
        channelplotter.ChannelPlotter().bar(PnoiseIf_Optim, 'Interference power Optim', 'ifpower.pdf')
        channelplotter.ChannelPlotter().bar(((np.abs(np.mean(np.mean(CSI_Optim,1),1)))**2)/(PnoiseIf_Optim), 'SINR Optim', 'OptimSINR.pdf')
        channelplotter.ChannelPlotter().OFDMAchannel(SINR_Quant, 'SINR Quant', 'sinrquant.pdf')
        channelplotter.ChannelPlotter().OFDMAchannel(noiseIfPQuant , 'Noise Interference Power Quant', 'noiseifquant.pdf')
        import pdb; pdb.set_trace()
        

### Step 2 ###
    # Map real valued solution to OFDMA frame
    # QUANTMAP
    resourcesPerTimeslot = quantmap.quantmap(resourceAlloc, N, T)
    outmap = np.empty([N, T])
    for t in np.arange(T):
        # RCG
        outmap[:,t],_ = rcg.rcg(SINR_Quant[:,t,:],resourcesPerTimeslot[t,:]) # outmap.shape = (N,T) tells the user index

    # Given allocation and rate target, we inverse waterfill channels for each user separately on the basis of full CSI
    # IWF
    powerlvls = np.empty([N, T, mob.antennas])
    powerlvls[:] = np.nan
    for idx, obj in enumerate(wrld.consideredMobiles): # WRONG TODO: Only all mobiles of a BS
        # grab user CSI
        CSI_usr = obj.OFDMA_SINR[:,:,outmap==idx] # all CSI assigned to this user
        noiseIfPower_usr = CSI_usr[0,0,:].repeat(2) * 0 + 1 # remove later  #(obj.baseStations[obj.BS].cells[obj.cell].OFDMA_interferencePower + obj.baseStations[obj.BS].cells[obj.cell].OFDMA_noisePower) * np.ones(CSI_user_all[0,0,:,:].shape)[outmap==idx].ravel().repeat(2) # one IF value per resource, so repeat once to match spatial channels
        # create list of eigVals
        eigVals = np.real([linalg.eig(CSI_usr[:,:,i])[0] for i in np.arange(CSI_usr.shape[2])]).ravel() # two eigvals (spatial channels) per resource
        targetLoad = rate * wrld.PHY.simulationTime 
        # inverse waterfill and fill back to OFDMA position
        powlvl, waterlvl, cap = iwf.inversewaterfill(eigVals, targetLoad, noiseIfPower_usr, wrld.PHY.systemBandwidth / N, wrld.PHY.simulationTime / T)
        powerlvls[outmap==idx,:] = powlvl.reshape(CSI_usr.shape[2],obj.antennas)
        

    ptx = np.array([np.nansum(np.nansum(powerlvls[:,t,:],axis=0),axis=0) for t in np.arange(T)])
    if ptx.any() > cell.pMax:
        raise ValueError('Transmission power too high in IWF.')
        
    psupplyPerSlot = bs.p0 + bs.m * ptx
        
    psupplyPerSlot[np.isnan(psupplyPerSlot)] = bs.pS
    pSupplyQuant = np.mean(psupplyPerSlot)
    print '{0:50} {1:5.2f} W'.format('Integer-valued optimization objective:', pSupplyQuant)
    
### SOTA comparison ###
    pSupplyBA = np.nan
    CSI_BA = np.empty([2,2,N,T, users], dtype=complex)
    CSI_BA[:] = np.nan
    noiseIfPowerPerResource = np.empty([N,T,users])
    noiseIfPowerPerResource[:] = np.nan
    for idx, obj in enumerate(wrld.consideredMobiles):
        CSI_BA[:,:,:,:,idx] = obj.baseStations[obj.BS].cells[obj.BS.cells[0]].CSI_OFDMA
        noiseIfPowerPerResource[:,:,idx] = obj.noiseIfPower * np.ones([N,T]) / N
    pTxBA = OFDMA_BA(np.ones(users)*rate*wrld.PHY.simulationTime, np.ones([N,T,users])*cell.pMax/N, wrld.PHY.systemBandwidth, wrld.PHY.simulationTime, noiseIfPowerPerResource, CSI_BA)

    pSupplyBA = scistats.nanmean(bs.p0 + bs.m * pTxBA)
    print '{0:50} {1:5.2f} W'.format('SOTA objective:', pSupplyBA)
    print ' '

    return pSupplyOptim, pSupplyQuant, pSupplyBA
Пример #9
0
def raps(wrld, cell, mobiles, rate, plotting=False):
    """In the cell, allocate powers and sleep modes to mobiles."""
    # need to map algorithm indices to mobile ids (artifact from MATLAB)
    id_map = dict()
    for k, mob in enumerate(mobiles):
        id_map[k] = mob.id_

    # Make sure all mobiles are associated with the cell correctly
    for mob in mobiles:
        if mob.cell != cell:
            raise ValueError('Faulty passing of mobiles to RAPS')
    logger.info('{0:50} {1:5d}'.format('Mobiles in this cell:', len(mobiles)))

    # Build SINR arrays
    users = len(mobiles)
    N = wrld.PHY.numFreqChunks
    T = wrld.PHY.numTimeslots
    noisePower = wrld.wconf.systemNoisePower

    # EC_Optim contains one MIMO value per mobile (the center chunk effective channel)
    EC_Optim = np.empty(
        [users, cell.antennas, wrld.mobiles[0].antennas], dtype=complex
    )  # TODO Will we ever have mobiles with different numbers of annteas?
    # SINR_Quant contains one value for each RB and user
    SINR_Quant = np.empty([N, T, users])
    centerChunkIndex = np.floor(N / 2)
    whichTimeslotIndex = list(cell.sleep_slot_priority).index(0)
    for idx, mob in enumerate(mobiles):
        EC_Optim[
            idx, :, :] = mob.OFDMA_EC[:, :, centerChunkIndex,
                                      whichTimeslotIndex] / N  # scale this effective channel over all chunks
        SINR_Quant[:, :, idx] = np.mean(mob.OFDMA_effSINR, 0)  # SINR for RCG

    ### Step 1 ###
    # Optimization call
    pSupplyOptim, resourceAlloc, status = optimMinPow.optimizePCDTX(
        EC_Optim, np.ones(EC_Optim.shape[0]), rate, wrld.PHY.systemBandwidth,
        cell.pMax, mobiles[0].BS.p0, mobiles[0].BS.m, mobiles[0].BS.pS)
    logger.debug('Resource Allocation: ' + str(resourceAlloc))
    logger.debug('Sleep priority: ' + str(cell.sleep_slot_priority))
    logger.info('{0:50} {1:5.2f} W'.format(
        'Real-valued optimization objective:', pSupplyOptim))

    ## Plot ##
    if cell.cellid == 12345 and plotting:  # center in tier 1
        from plotting import channelplotter
        channelplotter.bar(np.mean(np.mean(EC_Optim, 1), 1),
                           'Abs mean of MIMO EC Optim', 'sinr_optim.pdf')
        channelplotter.OFDMAchannel(SINR_Quant, 'SINR Quant', 'sinr_quant.pdf')
        channelplotter.bar(resourceAlloc, 'Resource Share Optim',
                           'rscshare.pdf')
        import pdb
        pdb.set_trace()

    ### Step 2 ###

    # Map real valued solution to OFDMA frame
    # QUANTMAP
    resourcesPerTimeslot = quantmap.quantmap(resourceAlloc, N, T)
    outmap = np.empty([N, T])

    # Handle sleep slot alignment here.
    resourcesPerTimeslot = resourcesPerTimeslot[cell.sleep_slot_priority]

    # RCG
    for t in np.arange(T):
        outmap[:, t], _ = rcg.rcg(SINR_Quant[:, t, :], resourcesPerTimeslot[
            t, :])  # outmap.shape = (N,T) tells the user index

    # Given allocation and rate target, we inverse waterfill channels for each user separately on the basis of full SINR
    # IWF
    powerlvls = np.empty([N, T, mob.antennas])
    powerlvls[:] = np.nan

    for idx, obj in enumerate(mobiles):
        # grab user SINR
        EC_usr = obj.OFDMA_EC[:, :, outmap ==
                              idx]  # all effective channels assigned to this user
        noiseIfPower_usr = np.real(
            EC_usr[0, 0, :].repeat(2) * 0 + 1
        )  # TODO remove later  #(obj.baseStations[obj.BS].cells[obj.cell].OFDMA_interferencePower + obj.baseStations[obj.BS].cells[obj.cell].OFDMA_noisePower) * np.ones(SINR_user_all[0,0,:,:].shape)[outmap==idx].ravel().repeat(2) # one IF value per resource, so repeat once to match spatial channels
        # create list of eigVals
        eigVals = np.real([
            linalg.eig(EC_usr[:, :, i])[0] for i in np.arange(EC_usr.shape[2])
        ]).ravel()  # two eigvals (spatial channels) per resource
        targetLoad = rate * wrld.PHY.simulationTime
        # inverse waterfill and fill back to OFDMA position
        powlvl, waterlvl, cap = iwf.inversewaterfill(
            eigVals, targetLoad, noiseIfPower_usr,
            wrld.PHY.systemBandwidth / N, wrld.PHY.simulationTime / T)
        powerlvls[outmap == idx, :] = powlvl.reshape(EC_usr.shape[2],
                                                     obj.antennas)

    ptx = np.array([
        np.nansum(np.nansum(powerlvls[:, t, :], axis=0), axis=0)
        for t in np.arange(T)
    ])
    logging.debug('Ptx' + str(ptx))
    if (ptx > cell.pMax).any():
        raise ValueError('Transmission power too high in IWF: ' + str(ptx) +
                         ' W')

    # Store power levels in cell for next round
    cell.OFDMA_power[:] = np.swapaxes(np.swapaxes(powerlvls[:], 1, 2), 0, 1)
    cell.OFDMA_power[np.isnan(cell.OFDMA_power)] = 0
    # remap to mobile ids
    outmap_ids = np.copy(outmap)
    for k, v in id_map.iteritems():
        outmap_ids[outmap == k] = v
    cell.outmap = outmap_ids

    psupplyPerSlot = mobiles[0].BS.p0 + mobiles[0].BS.m * ptx

    psupplyPerSlot[np.isnan(psupplyPerSlot)] = mobiles[0].BS.pS
    pSupplyQuant = np.mean(psupplyPerSlot)
    logger.info('{0:50} {1:5.2f} W'.format(
        'Integer-valued optimization objective:', pSupplyQuant))

    return pSupplyOptim, pSupplyQuant
Пример #10
0
def oneIteration(rate, CSI_Optim, SINR_Quant):
    """Perform one iteration and return the supply powers"""
    ### Step 1 ###
    # Optimization call
    import pdb
    pdb.set_trace()

    pSupplyOptim, resourceAlloc, status = optimMinPow.optimizePCDTX(
        CSI_Optim, PnoiseIf_Optim, rate, wrld.PHY.systemBandwidth, cell.pMax,
        bs.p0, bs.m, bs.pS)
    print '{0:50} {1:5.2f} W'.format('Real-valued optimization objective:',
                                     pSupplyOptim)

    ## Plot ##
    if plotting:
        channelplotter.ChannelPlotter().bar(resourceAlloc,
                                            'Resource Share Optim',
                                            'rscshare.pdf')
        channelplotter.ChannelPlotter().bar(PnoiseIf_Optim,
                                            'Interference power Optim',
                                            'ifpower.pdf')
        channelplotter.ChannelPlotter().bar(
            ((np.abs(np.mean(np.mean(CSI_Optim, 1), 1)))**2) /
            (PnoiseIf_Optim), 'SINR Optim', 'OptimSINR.pdf')
        channelplotter.ChannelPlotter().OFDMAchannel(SINR_Quant, 'SINR Quant',
                                                     'sinrquant.pdf')
        channelplotter.ChannelPlotter().OFDMAchannel(
            noiseIfPQuant, 'Noise Interference Power Quant',
            'noiseifquant.pdf')
        import pdb
        pdb.set_trace()

### Step 2 ###
# Map real valued solution to OFDMA frame
# QUANTMAP
    resourcesPerTimeslot = quantmap.quantmap(resourceAlloc, N, T)
    outmap = np.empty([N, T])
    for t in np.arange(T):
        # RCG
        outmap[:, t], _ = rcg.rcg(SINR_Quant[:, t, :], resourcesPerTimeslot[
            t, :])  # outmap.shape = (N,T) tells the user index

    # Given allocation and rate target, we inverse waterfill channels for each user separately on the basis of full CSI
    # IWF
    powerlvls = np.empty([N, T, mob.antennas])
    powerlvls[:] = np.nan
    for idx, obj in enumerate(
            wrld.consideredMobiles):  # WRONG TODO: Only all mobiles of a BS
        # grab user CSI
        CSI_usr = obj.OFDMA_SINR[:, :, outmap ==
                                 idx]  # all CSI assigned to this user
        noiseIfPower_usr = CSI_usr[0, 0, :].repeat(
            2
        ) * 0 + 1  # remove later  #(obj.baseStations[obj.BS].cells[obj.cell].OFDMA_interferencePower + obj.baseStations[obj.BS].cells[obj.cell].OFDMA_noisePower) * np.ones(CSI_user_all[0,0,:,:].shape)[outmap==idx].ravel().repeat(2) # one IF value per resource, so repeat once to match spatial channels
        # create list of eigVals
        eigVals = np.real([
            linalg.eig(CSI_usr[:, :, i])[0]
            for i in np.arange(CSI_usr.shape[2])
        ]).ravel()  # two eigvals (spatial channels) per resource
        targetLoad = rate * wrld.PHY.simulationTime
        # inverse waterfill and fill back to OFDMA position
        powlvl, waterlvl, cap = iwf.inversewaterfill(
            eigVals, targetLoad, noiseIfPower_usr,
            wrld.PHY.systemBandwidth / N, wrld.PHY.simulationTime / T)
        powerlvls[outmap == idx, :] = powlvl.reshape(CSI_usr.shape[2],
                                                     obj.antennas)

    ptx = np.array([
        np.nansum(np.nansum(powerlvls[:, t, :], axis=0), axis=0)
        for t in np.arange(T)
    ])
    if ptx.any() > cell.pMax:
        raise ValueError('Transmission power too high in IWF.')

    psupplyPerSlot = bs.p0 + bs.m * ptx

    psupplyPerSlot[np.isnan(psupplyPerSlot)] = bs.pS
    pSupplyQuant = np.mean(psupplyPerSlot)
    print '{0:50} {1:5.2f} W'.format('Integer-valued optimization objective:',
                                     pSupplyQuant)

    ### SOTA comparison ###
    pSupplyBA = np.nan
    CSI_BA = np.empty([2, 2, N, T, users], dtype=complex)
    CSI_BA[:] = np.nan
    noiseIfPowerPerResource = np.empty([N, T, users])
    noiseIfPowerPerResource[:] = np.nan
    for idx, obj in enumerate(wrld.consideredMobiles):
        CSI_BA[:, :, :, :,
               idx] = obj.baseStations[obj.BS].cells[obj.BS.cells[0]].CSI_OFDMA
        noiseIfPowerPerResource[:, :,
                                idx] = obj.noiseIfPower * np.ones([N, T]) / N
    pTxBA = OFDMA_BA(
        np.ones(users) * rate * wrld.PHY.simulationTime,
        np.ones([N, T, users]) * cell.pMax / N, wrld.PHY.systemBandwidth,
        wrld.PHY.simulationTime, noiseIfPowerPerResource, CSI_BA)

    pSupplyBA = scistats.nanmean(bs.p0 + bs.m * pTxBA)
    print '{0:50} {1:5.2f} W'.format('SOTA objective:', pSupplyBA)
    print ' '

    return pSupplyOptim, pSupplyQuant, pSupplyBA