A.1 Definizioni
DEFINIZIONI RELATIVE A UTENTI E SOTTOPORTANTI
simulInfo.userNumber =16; simulInfo.subCarNumber = 64;
DEFINIZIONI RELATIVE AL CANALE
simulInfo.simNum = 1;
Tipo di canale utilizzato:
0. Canale incorrelato, utenti tutti alla stessa distanza, spatial non conta; 1. Canale ETSI BRAN (non implementato);
2. Canale con Exponential Power Delay Profile e utenti posizionati a caso nella cella 3. Canale WiLan
Parametro che imposta lo stato del generatore casuale di segnali (0 deterministico, 1 casuale)
simulInfo.randSeedChannel = 1;
Frequenza della portante e banda complessiva del segnale in Hz
simulInfo.carFreq = 2e9; simulInfo.sigBandWidth = 20e6;
Variabile che determina la funzione di posizione spaziale degli utenti quando sono generati (0: no PL = 1 per tutti; 1: sì)
simulInfo.spatial = 1; simulInfo.radius = 500;
simulInfo.pathLossExponent = 4; simulInfo.rmsDelaySpread = 5e-7;
TIPO DI CALCOLO DI PRESTAZIONI CHE VOGLIO EFFETTUARE 1. Calcolo BER
2. Calcolo potenza in funzione del rate 3. Calcolo pdf
simulInfo.prest=1;
A.2 Algoritmo di allocazione dinamica delle risorse
PROGRAMMA PRINCIPALE. GENERA IL CANALE ED ALLOCA AD OGNI UTENTE IL NUMERO DI SOTTOPORTANTI RICHESTO. CALCOLA POI LE PRESTAZIONI
clear all load definiz simNumber=100; prest=simulInfo.prest; userNumber=simulInfo.userNumber; subCarNumber=simulInfo.subCarNumber; switch prest
case 1 CALCOLO IL BER DATO UN RATE DI 2 MHz/s rate=2*10^6; for sim=1:simNumber simulInfo = canale(simulInfo); simulInfo = BABS(simulInfo,rate); matrix=simulInfo.subCarMatrix; assegnazione = allocazione(simulInfo,matrix); assegnOttima=linProgImpl(simulInfo,matrix); assegnNoAll=noAll(simulInfo,matrix); vect=sum(assegnazione); vectOtt=sum(assegnOttima); vectNoAll=sum(assegnNoAll); muta = 0; for SNR = 0:2:12 SNRLin = 10^(SNR/10);
muta = muta+1; BER(sim,muta)=calcoloBER(vect,SNRLin); BEROtt(sim,muta)=calcoloBER(vectOtt,SNRLin); BERNoAll(sim,muta)=calcoloBER(vectNoAll,SNRLin); end sim end mediaBER=sum(BER)/simNumber; mediaBEROtt=sum(BEROtt)/simNumber; mediaBERNoAll=sum(BERNoAll)/simNumber; semilogy(0:2:12,mediaBER,'g') hold on semilogy(0:2:12,mediaBEROtt) hold on semilogy(0:2:12,mediaBERNoAll,'r')
case 2 CALCOLO LA POTENZA IN FUNZIONE DEL RATE for sim=1:simNumber simulInfo = canale(simulInfo); muta=0; sim for rate=(0.5:0.5:4)*10^6 simulInfo = BABS(simulInfo,rate); matrix=simulInfo.costMatrix; assegnazione = allocazione(simulInfo,matrix); assegnOttima=linProgImpl(simulInfo,matrix);
muta=muta+1; Potenza(sim,muta)=(sum(sum(assegnazione)))*simulInfo.noisePower; PotenzaOtt(sim,muta)=(sum(sum(assegnOttima)))*simulInfo.noisePower; PotenzaNoAll(sim,muta)=(sum(sum(assegnNoAll)))*simulInfo.noisePower; end end mediaPot=sum(Potenza)/simNumber; mediaPotOtt=sum(PotenzaOtt)/simNumber; mediaPotNoAll=sum(PotenzaNoAll)/simNumber; semilogy((0.5:0.5:4),mediaPot) hold on semilogy((0.5:0.5:4),mediaPotOtt,'g') hold on semilogy((0.5:0.5:4),mediaPotNoAll,'r')
case 3 CALCOLO PDF: ISTOGRAMMA CON TUTTI I VALORI DELL'ASSEGNAZIONE PER
TUTTE LE SIMULAZIONI rate=2*10^6; simNumber=3000; for sim=1:simNumber simulInfo = canale(simulInfo); simulInfo = BABS(simulInfo,rate); matrix=simulInfo.subCarMatrix; sim assegnazione = allocazione(simulInfo,matrix); assegnOttima=linProgImpl(simulInfo,matrix);
assegnNoAll=noAll(simulInfo,matrix); vect=sum(assegnazione); vectOtt=sum(assegnOttima); vectNoAll=sum(assegnNoAll); x((1:userNumber)+userNumber*(sim-1))=vect; xOtt((1:userNumber)+userNumber*(sim-1))=vectOtt; xNoAll((1:userNumber)+userNumber*(sim-1))=vectNoAll; end y = pdf1(x); hold on yOtt = pdf2(xOtt); hold on yNoAll = pdf3(xNoAll); end
A.3 Funzione per generare il canale
function simulInfo = canale(simulInfo) corrChannel = simulInfo.corrChannel; userNumber = simulInfo.userNumber; subCarNumber = simulInfo.subCarNumber; sim = simulInfo.simNum; randSeedChannel=simulInfo.randSeedChannel; if prest==2 simulInfo = calcoloperditacanale(simulInfo); else simulInfo.pathLoss=ones(1,userNumber); end
MATRICE DI GUADAGNI DI CANALE INCORRELATA
if corrChannel == 0
Inizializzazione del generatore di variabili aleatorie uniformi e Gaussiane.
if simulInfo.randSeedChannel==1
randn('state',sum(100000*clock)) Setto un nuovo valore del seme del generatore di numeri casuali else
randn('state',sim) Setto il generatore di variabili aleatorie al valore iniziale end
powerScale = 0.5.^0.5; Generazione del canale X = powerScale*randn(subCarNumber,userNumber); Y = powerScale*randn(subCarNumber,userNumber);
CANALE CON EXPONENTIAL POWER DELAY PROFILE
elseif corrChannel == 2
simulInfo = canaleprofiloesponenziale(simulInfo); Funzione per il calcolo del guadagno di canale end
MATRICE DEI GUADAGNI DI CANALE TIPO WiLAN
elseif corrChannel ==3
simulInfo=canaleWLAN(simulInfo); end
k = 1.38e-23; Costante di Bolzmann T = 293; Temperatura ambiente
sigBandWidth = simulInfo.sigBandWidth;
subCarBandWidth = sigBandWidth/subCarNumber; simulInfo.noisePower = k*T*subCarBandWidth; simulInfo.simNum = sim+1;
A.3.1 Calcolo perdita di canale
function simulInfo = calcoloperditacanale(simulInfo)
Funzione che calcola la posizione all'interno della cella per ciascun utente e la Pathloss associata.
userNumber = simulInfo.userNumber; subCarNumber = simulInfo.subCarNumber; carFreq = simulInfo.carFreq; nFFT = subCarNumber; sigBandWidth = simulInfo.sigBandWidth; lightSpeed = 3e8;
lambda = lightSpeed/carFreq; Lunghezza d'onda del segnale trasmesso spatial = simulInfo.spatial;
if spatial==0
simulInfo.pathLoss = ones(1,userNumber); elseif spatial == 1
Genero le posizioni e le attenuazioni di pathloss per ciascun utente nella cella (large scale fading) if simulInfo.randSeedChannel==1 Inizializzazione del generatore di variabili aleatorie uniformi e
Gaussiane
rand('state',sum(100*clock)) Setto un nuovo valore del seme del generatore di numeri casuali else
rand('state',1) Setto il generatore di variabili aleatorie al valore iniziale end
R = simulInfo.radius;
pLExp = simulInfo.pathLossExponent;
unifVar = rand(1,userNumber); Genero una variabile uniformemente distribuita tra 0 e 1 per ciascun
utente
Calcolo la distanza di ciascun utente dalla BS in metri: è formulata in maniera tale che non sia possibile che un utente sia più vicino di 10 m
simulInfo.userPos = userPos;
Fattore di normalizzazione della Pathloss: attenuazione di spazio libero ad un metro dalla sorgente.
pathLossNorm = (lambda/(4*pi))^2;
pathLoss = (userPos.^-pLExp)*pathLossNorm; Attenuazione dovuta alla Pathloss k = 1.38e-23; Costante di Boltzmann in J/K
T = 293; Temperature del ricevitore in K
subCarBanWidth = sigBandWidth/nFFT; Banda di una sottoportante noisePower = subCarBanWidth*k*T; Potenza del rumore
pathLossNoise = pathLoss/noisePower; Termine che riassume effetto di Pathloss e rumore simulInfo.pathLoss = pathLoss;
end
A.3.2 Canale con exponential power delay profile
function simulInfo = chanExpPowDelPro(simulInfo)
Modello di canale correlato con exponential power delay profile
userNumber = simulInfo.userNumber; subCarNumber = simulInfo.subCarNumber; nFFT = subCarNumber; carFreq = simulInfo.carFreq; sigBandWidth = simulInfo.sigBandWidth; lightSpeed = 3e8;
lambda = lightSpeed/carFreq; Lunghezza d'onda del segnale trasmesso pathLoss = simulInfo.pathLoss;
Inizializzazione del generatore di variabili aleatorie uniformi e Gaussiane
if simulInfo.randSeedChannel==1
rand('state',sum(100*clock)) Setto un nuovo valore del seme del generatore di numeri casuali randn('state',sum(100*clock))
else
rand('state',sim) Setto il generatore di variabili aleatorie al valore iniziale randn('state',sim)
end
Genero il canale frequency selective secondo un modello di propagazione exponential power delay profile
sampTime = 1/sigBandWidth; Tempo di campionamento segnale OFDM delSpread = simulInfo.rmsDelaySpread;
normDelSpread = delSpread/sampTime; Delay spread normalizzato al tempo di campionamento
Si generano un numero di repliche pari a tre volte il reciproco del delay spread normalizzato.
pathNumber = ceil(3*normDelSpread);
Fattore di normalizzazione che fa sì che il guadagno medio sia pari alla pathloss
normFactor = (1-exp(-(pathNumber)/normDelSpread))... /(1-exp(-1/normDelSpread));
for path = 1:pathNumber
pathPow(path) = (1/normFactor)*exp(-(path-1)/normDelSpread); Potenza media di ciascuna path end
pathStDv = (0.5*pathPow).^.5; Deviazione standard della potenza di ciascuna replica for user = 1:userNumber
chanGain(user,:) = pathStDv.*(randn(1,pathNumber)+i*randn(1,pathNumber)); Genero la risposta di
canale nel dominio del tempo
end
radioChanFreq(user,:) = fft(chanGain(user,:),nFFT).'; Calcolo la TdF del canale di ciascun utente end
pathLossMatrix = diag(pathLoss); Organizzo il vettore delle pathloss in una matrice
simulInfo.subCarMatrix = ... Matrice che ha gli utenti in ascissa e le sottoportanti in ordinata (pathLossMatrix*(abs(radioChanFreq).^2)).';
A.3.3 Canale WiLan
function simulInfo = canaleWLAN(simulInfo)
simulInfo.subCarNumber = 64; Aggiorno il numero di sottoportanti subCarNumber = simulInfo.subCarNumber;
userNumber=simulInfo.userNumber;
subCarMatrix = zeros(subCarNumber,userNumber); for user=1:userNumber
Inizializzazione del generatore di variabili aleatorie uniformi e Gaussiane.
rand('state',sum(100*clock)) Setto un nuovo valore del seme del generatore di numeri casuali randn('state',sum(100*clock))
subCarVector = canaleWLANsingoloUtente(simulInfo); subCarMatrix(:,user)=subCarVector*simulInfo.pathLoss(user); end
A.3.4 Canale WiLan per un singolo utente
function subCarVector = canaleWLANsingoloUtente(simulInfo) nFFT = 64;
nSubCar = simulInfo.subCarNumber;
cpLength = 16; Lunghezza del prefisso ciclico
PDP_delays = [0 1 2 3 4 5 6 7 8 9 11 14 17 20 24 29 34 39]*10e-9; Ritardi di propagazione
power_per_PDP_delays_dB = [0 -0.9 -1.7 -2.6 -3.5 -4.3 -5.2 -6.1 -6.9 -7.8 -4.7 -7.3 -9.9 -12.5 -13.7 -18 -22.4 -26.7]; Potenza in dB di ciascun percorso
power_per_PDP_delays_linear = 10.^(.1.*power_per_PDP_delays_dB); Da dB a lineare path_number = size(power_per_PDP_delays_linear,2);
Considero un canale con multipath con un filtro tx/rx
filtCoeff = filtro; coefficients = filtCoeff.coeff; offSet = filtCoeff.offSet; overSampleFactor = filtCoeff.filtOverSamp; tSamp = filtCoeff.Ts/(overSampleFactor); tempRatio = 10e-9/tSamp;
Wishart matrix of dimensions path number
X = sqrt(0.5)*randn(path_number,1); Y = sqrt(0.5)*randn(path_number,1); H = reshape(power_per_PDP_delays_linear,[],1).*(X + i*Y); Channel coefficients sampledDelays = PDP_delays/tSamp; maxDelay = max(sampledDelays); chan.cir = zeros(ceil((maxDelay+length(coefficients))/overSampleFactor),1); Channel Generator subChan = reshape(H,1,[]);
oSVector(round(sampledDelays)+1) = subChan; subChanConv = conv(oSVector,coefficients);
Channel Impulse Response (CIR)
cir = subChanConv(offSet+(1:overSampleFactor:end));
Normalizing to one the CIR power
normCoeff = sum(abs(cir).^2); cir = (cir)./sqrt(normCoeff); freq = fft(cir,nFFT);
subCarVector=(abs(freq).^2).';
A.4 Algoritmo BABS
function simulInfo = BABS(simulInfo,rate)
CALCOLO DEL NUMERO DELLE SOTTOPORTANTI PER OGNI UTENTE
subCarNumber = simulInfo.subCarNumber; userNumber = simulInfo.userNumber; matrix=simulInfo.subCarMatrix;
mediaCanale=mean(matrix); Valor medio del canale di ogni utente (media sulle sottoportanti) subCarPerUser=ones(1,userNumber); Vettore che indica quante sottoportanti vengono assegnate ad
ogni utente (inizialmente una sottoportante per ogni utente)
subCarUsed=sum(subCarPerUser); Calcolo il numero delle sottoportanti assegnate B=simulInfo.sigBandWidth; Banda complessiva a disposizione
BSubCar=B/subCarNumber; Banda di ogni sottoportante effic=rate/BSubCar;
if simulInfo.prest == 1 effic = 1;
Il vettore powerUserSubCar è formato dalla potenza necessaria all'utente (user) per trasmettere il suo flusso dati su un numero di sottoportanti pari a quelle ad esso assegnate (subCarPerUser(user)). Il vettore powerUserSubCarUno è formato dalla potenza che sarebbe necessaria ad ogni utente se potesse trasmettere su un numero di sottoportanti pari a quello ad esso assegnate + 1. Il vettore Delta Power è formato dalla differenza di potenza che ogni utente ha trasmettendo su una sottoportante in più.
for user=1:userNumber powerUserSubCar(user)=subCarPerUser(user)*(exp(effic/subCarPerUser(user))-1)/mediaCanale(user); powerUserSubCarUno(user)=(subCarPerUser(user)+1)*(exp(effic/(subCarPerUser(user)+1))-1)/mediaCanale(user); DeltaPower(user)=powerUserSubCar(user)-powerUserSubCarUno(user); end
while subCarUsed ~= subCarNumber; Ciclo fino all'assegnazione di tutte le sottoportanti [maxDeltaPower,userind]=max(DeltaPower); Userind è l'utente che ha il DeltaPower massimo
subCarPerUser(userind)=subCarPerUser(userind)+1; E a tale utente viene effettivamente assegnata una
sottoportante in più
Aggiorno il numero delle sottoportanti assegnate e aggiorno i valori delle potenze e del DeltaPower solo per l'utente che ho considerato.
subCarUsed=sum(subCarPerUser); powerUserSubCar(userind)=subCarPerUser(userind)*(exp(effic/subCarPerUser(userind))-1)/mediaCanale(userind); powerUserSubCarUno(userind)=(subCarPerUser(userind)+1)*(exp(effic/(subCarPerUser(userind)+1))-1)/mediaCanale(userind); DeltaPower(userind)=powerUserSubCar(userind)-powerUserSubCarUno(userind); end simulInfo.subCarPerUser=subCarPerUser;
Dopo aver calcolato quante sottoportanti allocare ad ogni utente, devo creare una nuova matrice dei costi; infatti, se un utente usa una sola sottoportante, essa avrà costo maggiore perchè su di essa si trasmetteranno tutti i bit e sarà necessaria molta potenza; se invece un utente trasmette su 10 sottoportanti, ciascuna sottoportante supporta solo 1/10 del flusso di bit e la potenza per trasmettere su di essa è inferiore. Nel primo caso descritto il costo sarà superiore al secondo. La matrice dei costi si ottiene considerando un termine che tiene conto del numero di sottoportanti allocate ad ogni utente e dividendo tale termine per il guadagno di canale di ogni utente su ogni sottoportante.
subCarMatrix=simulInfo.subCarMatrix; for user=1:userNumber ni(user)=effic/subCarPerUser(user); pesi(user)=2^(ni(user))-1; costMatrix(:,user)=pesi(user)./subCarMatrix(:,user); end simulInfo.costMatrix=costMatrix;
A.5 Algoritmo di allocazione dinamica delle sottoportanti
function assegnazione = allocazione(simulInfo, matrix)
ALLOCA AD OGNI UTENTE UNA O PIU' SOTTOPORTANTI
Alloca ad ogni utente il numero di sottoportanti inserito nel vettore subCarPerUser. Funziona solo se il numero di sottoportanti è maggiore o uguale al numero degli utenti
subCarNumber = simulInfo.subCarNumber; Numero di sottoportanti subCarNumberNew=subCarNumber;
userNumber = simulInfo.userNumber; Numero di utenti
prest=simulInfo.prest; Tipo di prestazioni che voglio calcolare if prest==2
matrix=-matrix; Poiché voglio minimizzare la matrice dei costi e il programma massimizza la
matrice che ha in ingresso, devo considerare i valori negativi
end
subCarPerUser=simulInfo.subCarPerUser; Vettore che indica quante sottoportanti devono essere
assegnate a ciascun utente
userRid=4; Vettore che indica quanti utenti vengono considerati nella matrice ridotta probl=0; Variabile che viene successivamente settata a 1 se si verificano problemi
Ordino le colonne in modo che la prima sia quella a valor medio minore; media è il vettore dei valor medi di ogni colonna; mediaOrd è il vettore dei valori medi ordinati; ord è il vettore che tiene conto di come sono state spostate le colonne; matrixOrd è la matrice così ordinata
media=mean(matrix); [mediaOrd,ord]=sort(media); matrixOrd=matrix(:,ord);
matrixOrdConMinimi=matrixOrd; matrixOrdOld=matrixOrd;
Si lavora su una matrice ridotta composta da tutte le righe della matrice di canale (cioè tutte le sottoportanti) ma solo 4 colonne (cioè solo 4 utenti); man mano che si assegna una colonna (cioè ad un utente vengono assegnate le sottoportanti richieste), non si considera più quella colonna e si aggiunge la successiva.
matrixRid=matrixOrd(:,(1:userRid)); subCarPerUserOrd=subCarPerUser(ord);
subCarPerUserRid=subCarPerUserOrd(1:userRid);
userPos=1:userNumber; Vettore da 1 a userNumber che mi serve per tener conto degli utenti a cui ho
già assegnato le sottoportanti richieste
subCarPos=1:subCarNumber; Vettore da 1 a subCarNumber che mi serve per tener conto delle
sottoportanti già assegnate
subCarFinitePos=subCarPos(isfinite(subCarPos)); Vettore che indica quali sono le posizioni finite di userFinitePos=userPos(isfinite(userPos)); userPos e subCarPos
userLeftNum=userNumber-userRid; E’ il numero di utenti che non considero, cioè che rimangono
assegnazione=zeros(subCarNumber,userNumber);
Matrice di assegnazione utente-sottoportante (è una matrice di 0 che vengono messi a 1 per indicare l'assegnazione)
ass=ones(subCarNumber,userNumber);
Matrice di appoggio (è una matrice di 1 che vengono messi a 0 per indicare che quell'assegnazione non viene fatta) assConMinimi=ass; assOld=ass; assRid=ones(subCarNumber,userRid); SrigheassRid=sum(assRid,2); ScolonneassRid=sum(assRid);
while subCarPerUserRid ~= 0 Cioè finché non vengono assegnate tutte le sottoportanti necessarie ad
ogni utente
1. Caso in cui il numero di utenti a cui devono ancora essere assegnate delle sottoportanti sia maggiore di 4
if numel(userFinitePos) > userRid
Cancello i valori più piccoli di canale solo nel caso in cui non vi siano delle assegnazioni obbligate;
tali assegnazioni obbligate sono dovute al fatto che in una colonna (utente) sono rimaste un numero di assegnazioni possibili pari a quelle richieste da quell'utente. E' importante prestare attenzione agli indici delle assegnazioni; per questo uso subCarFinitePos e userFinitePos
if (ScolonneassRid~=subCarPerUserRid) [minC,ind]= min(matrixRid);
[minmatrix,user] = min(minC); Trovo l'indice utente del valore minimo nella matrice di canale subCar = ind(user); Trovo l'indice sottoportante del valore minimo nella matrice di canale subCarFinitePos=subCarPos(isfinite(subCarPos)); Passo dagli indici di matrix ridotta a quelli di
matrix
userFinitePos=userPos(isfinite(userPos)); subCarReal=subCarFinitePos(subCar); userReal=userFinitePos(user);
matrixOrdConMinimi (subCarReal , userReal)=inf; matrixRid (subCar , user)=inf;
assConMinimi (subCarReal , userReal)=0; ScolonneassRid=sum(assRid);
SrigheassRid=sum(assRid,2); else
Considero il caso di una colonna (utente) in cui è necessario fare una o più assegnazioni perché è
rimasto un numero di accoppiamenti utente-sottoportante pari a quello indicato in subCarPerUser
userInd=find(ScolonneassRid==subCarPerUserRid); Trovo l'indice di colonna della matrice
ridotta
for ind=1:numel(userInd)
subCarInd=find(matrixRid(:,userInd(ind))~=inf); Trovo l'indice di riga della matrice ridotta for index=1:numel(subCarInd)
subCarReal=subCarFinitePos(subCarInd(index)); userReal=userFinitePos(userInd(ind));
assegnazione(subCarReal,userReal)=1; Assegno matrixRid(subCarInd(index),:)=inf;
subCarPos(subCarReal)=inf; Cancello la sottoportante appena assegnata
subCarPerUserOrd(userReal)=subCarPerUserOrd(userReal)-1; Decremento subCarPerUser
per indicare l'avvenuta assegnazione
end
userPos(userReal)=inf; Cancello l'utente che ho considerato end
Aggiorno matrixRid e assRid tenendo conto delle colonne cancellate (cioè messe a inf). RigheNulle=find(SrigheassRid==0);
numRigheNulle=numel(RigheNulle);
subCarFinitePos=subCarPos(isfinite(subCarPos)); userFinitePos=userPos(isfinite(userPos));
userLeftNum=numel(userFinitePos)-userRid; numUserFinitePos=numel(userFinitePos);
userLeft=userFinitePos((userRid+1):numUserFinitePos); subCarLeft=sum(subCarPerUserOrd(userLeft));
minMatrixRid=min(min(matrixRid)); Il valore più piccolo rimasto in matrixRid
Dopo aver effettuato le cancellazioni della o delle colonne assegnate, posso avere un numero di
utenti ancora da assegnare maggiore, uguale o minore a userRid=4; devo allora cambiare opportunamente la dimensione della matrice ridotta
numUserFinitePos=numel(userFinitePos); if numUserFinitePos>userRid userDim=userRid; else userDim=numUserFinitePos; end
Considero due diversi casi:
A. Nella matrice ridotta ci sono un numero di righe completamente cancellate (perchè con valori piccoli) superiore al numero di utenti rimasti (che devo ancora considerare); in questo caso non riuscirò con gli utenti restanti ad assegnare tutte le sottoportanti. Devo quindi resettare tutto e ricominciare da capo il calcolo dei minimi
if numRigheNulle>subCarLeft matrixRid=matrixOrd (subCarFinitePos,userFinitePos(1:userDim)); [subCarNumberNew,userNumberNew]=size(matrixRid); assRid=ass(subCarFinitePos,userFinitePos(1:userDim)); SrigheassRid=sum(assRid,2); ScolonneassRid=sum(assRid); subCarPerUserRid=subCarPerUserOrd(userFinitePos(1:userDim)); matrixOrdConMinimi=matrixOrd;
assConMinimi=ass;
B. La condizione sopra non è verificata quindi posso tenere la matrice ridotta con i minimi già
calcolati e scartati. Prima di aggiungere un'altra colonna, ne cancello tutti i valori più piccoli del minimo della matrice ridotta.
else
if userLeftNum>0 Se quello considerato non è l'ultimo utente da aggiungere nuovoUtente=userFinitePos(userDim);
nuovaColonna=matrixOrdConMinimi(:,nuovoUtente); maxNuovaColonna=max(nuovaColonna);
Se il massimo valore della nuova colonna è minore del minimo della vecchia matrice ridotta,
allora devo mettere a inf tutti i valori della nuova colonna minori di tale massimo, che al ciclo successivo verrà assegnato (il massimo della nuova colonna diventa il valore di confronto). Altrimenti metto a inf solo i valori della nuova colonna che sono più piccoli del minimo della vecchia matrice (che è il valore di confronto).
if maxNuovaColonna<minMatrixRid valoreDiConfronto=maxNuovaColonna; else valoreDiConfronto=minMatrixRid; end riga=find(nuovaColonna<valoreDiConfronto); for ind=1:numel(riga) matrixOrdConMinimi(riga(ind),nuovoUtente)=inf; assConMinimi(riga(ind),nuovoUtente)=0; end end matrixRid=matrixOrdConMinimi(subCarFinitePos,userFinitePos(1:userDim)); [subCarNumberNew,userNumberNew]=size(matrixRid); assRid=assConMinimi(subCarFinitePos,userFinitePos(1:userDim));
SrigheassRid=sum(assRid,2); ScolonneassRid=sum(assRid);
subCarPerUserRid=subCarPerUserOrd(userFinitePos(1:userDim)); end
end
2. Caso in cui il numero di utenti a cui devono ancora essere assegnate delle sottoportanti si è ridotto
a 4
else
Cancello i valori più piccoli di canale solo nel caso in cui non vi siano delle assegnazioni obbligate;
tali assegnazioni obbligate sono dovute al fatto che in una colonna (utente) sono rimaste un numero di assegnazioni possibili pari a quelle richiesta da quell'utente oppure al fatto che in una riga (sottoportante) è rimasta una sola possibile assegnazione utente-sottoportante. E' importante fare attenzione agli indici delle assegnazioni; per questo uso subCarFinitePos e userFinitePos
if (ScolonneassRid~=subCarPerUserRid) if (SrigheassRid~=1)
[minC,ind]= min(matrixRid);
[minmatrix,user] = min(minC); Trovo l'indice utente del valore minimo nella matrice di canale subCar = ind(user); Trovo l'indice sottoportante del valore minimo nella matrice di canale subCarFinitePos=subCarPos(isfinite(subCarPos)); Passo dagli indici di matrix ridotta a quelli
di matrix
userFinitePos=userPos(isfinite(userPos)); subCarReal=subCarFinitePos(subCar); userReal=userFinitePos(user);
matrixOrd (subCarReal , userReal)=inf; matrixRid (subCar , user)=inf;
assRid (subCar , user)=0; ass (subCarReal , userReal)=0; SrigheassRid=sum(assRid,2);
else
Considero il caso di una riga (sottoportante) in cui è necessario fare un’assegnazione perchè è rimasto solo quel possibile accoppiamento utente-sottoportante.
subCarInd=find(SrigheassRid==1); Trovo l'indice di riga della matrice ridotta for ind=1:numel(subCarInd)
ciclo fittizio nel caso vi siano più sottoportanti rimaste a 1
userInd=find(assRid(subCarInd(ind),:)==1); Trovo l'indice di colonna della matrice ridotta subCarReal=subCarFinitePos(subCarInd(ind));
userReal=userFinitePos(userInd);
assegnazione(subCarReal,userReal)= 1; Assegno
subCarPos(subCarReal)=inf; Cancello la sottoportante appena assegnata subCarPerUserOrd(userReal)=subCarPerUserOrd(userReal)-1; Decremento subCarPerUser
per indicare l'avvenuta assegnazione
Considero il caso in cui nella colonna (utente) considerata sono già assegnati tutti gli accoppiamenti utente-sottoportante richiesti.
if subCarPerUserOrd(userReal)==0
userPos(userReal)=inf; Cancello l'utente in questione end
Nel caso in cui si crei un conflitto tra le righe cancellate, rimetto i valori originari e metto
probl a 1 così tengo nota che è avvenuto qualcosa e in seguito carico la matrice senza i minimi cancellati. if subCarPerUserOrd(userReal)<0 subCarPos(subCarReal)=subCarReal; subCarPerUserOrd(userReal)=subCarPerUserOrd(userReal)+1; probl=1; end end
Aggiorno matrixRid e assRid tenendo conto delle colonne cancellate (cioè messe a inf). Non si
tiene conto dei minimi prima cancellati ma si resetta tutto, cercando nuovamente i minimi di questa nuova matrice ridotta
subCarFinitePos=subCarPos(isfinite(subCarPos)); userFinitePos=userPos(isfinite(userPos)); if probl==1 matrixRid=matrixOrdOld(subCarFinitePos,userFinitePos); assRid=assOld(subCarFinitePos,userFinitePos); else matrixRid=matrixOrd(subCarFinitePos,userFinitePos); assRid=ass(subCarFinitePos,userFinitePos); end [subCarNumberNew,userNumberNew]=size(matrixRid); SrigheassRid=sum(assRid,2); ScolonneassRid=sum(assRid); subCarPerUserRid=subCarPerUserOrd(userFinitePos); end else
Considero il caso di una colonna (utente) in cui è necessario fare una o più assegnazioni perché è rimasto un numero di accoppiamenti utente-sottoportante pari a quello indicato in subCarPerUser
userInd=find(ScolonneassRid==subCarPerUserRid); Trovo l'indice di colonna della matrice
ridotta
for ind=1:numel(userInd)
subCarInd=find(matrixRid(:,userInd(ind))~=inf); Trovo l'indice di riga della matrice ridotta for index=1:numel(subCarInd)
subCarReal=subCarFinitePos(subCarInd(index)); userReal=userFinitePos(userInd(ind));
subCarPos(subCarReal)=inf; cancello la sottoportante appena assegnata
subCarPerUserOrd(userReal)=subCarPerUserOrd(userReal)-1; Decremento subCarPerUser
per indicare l'avvenuta assegnazione
end
userPos(userReal)=inf; Cancello l'utente che ho considerato end
Aggiorno matrixRid e assRid tenendo conto delle colonne cancellate (cioè messe a inf). Se però
mi trovo con una nuova matrixRid in cui una colonna è tutta di valori inf, allora resetto tutto e ricomincio il calcolo dei minimi.
subCarFinitePos=subCarPos(isfinite(subCarPos)); userFinitePos=userPos(isfinite(userPos)); matrixRid=matrixOrd(subCarFinitePos,userFinitePos); [subCarNumberNew,userNumberNew]=size(matrixRid); assRid=ass(subCarFinitePos,userFinitePos); SrigheassRid=sum(assRid,2); ScolonneassRid=sum(assRid); subCarPerUserRid=subCarPerUserOrd(userFinitePos); if sum(ScolonneassRid==0)>0 matrixRid=matrixOrdOld(subCarFinitePos,userFinitePos); assRid=ones(subCarNumberNew,userNumberNew); SrigheassRid=sum(assRid,2); ScolonneassRid=sum(assRid); end end end end
[ordord,ordInv]=sort(ord); assegnazione=assegnazione(:,ordInv); assegnazione=assegnazione.*(matrix); if prest==2 assegnazione=-assegnazione; end
A.6 Algoritmo di Linprog
function assegnOttima=linProgImpl(simulInfo,matrix)
Implemento il linear programming per trovare la soluzione ottima da confrontare con l'algoritmo di allocazione studiato
userNumber = simulInfo.userNumber; subCarNumber = simulInfo.subCarNumber; subCarPerUser = simulInfo.subCarPerUser;
prest=simulInfo.prest; Tipo di prestazioni che voglio calcolare costVector=reshape(matrix',[],1); Vettore di costi
if prest~=2
costVector=-costVector; end
Devo poi imporre dei vincoli:
VINCOLO SULLE SOTTOPORTANTI:ogni sottoportante può essere assegnata al massimo ad un utente. Creo la matrice dei vincoli sulle sottoportanti: matrice di zeri con alcuni blocchi formati da tutti 1
matSubCar=zeros(subCarNumber,subCarNumber*userNumber); block=ones(1,userNumber);
for subCar=1:subCarNumber indPos=subCar-1;
Creo un vettore che esprime il vincolo per ciascuna sottoportante: che venga assegnata al massimo 1 volta
bConstr = ones(subCarNumber,1);
VINCOLO SUGLI UTENTI: ad ogni utente deve essere assegnato un numero di sottoportanti pari a quello indicato in subCarPerUser (calcolato col BABS).
matUser=zeros(userNumber,subCarNumber*userNumber); ident=eye(userNumber); for subCar=1:subCarNumber indPos=subCar-1; matUser(1:userNumber,indPos*userNumber+(1:userNumber))=ident; end bConstrEq=reshape(subCarPerUser,[],1); lb = zeros(subCarNumber*userNumber,1); ub = ones(subCarNumber*userNumber,1); LINPROG options = optimset('LargeScale','off','Simplex','on','Display','off'); assVector=linprog(costVector,matSubCar,bConstr,matUser,bConstrEq,lb,ub,[],options)
Ricostruisco la matrice di assegnazione
ass=reshape(assVector,userNumber,subCarNumber); assegnOttima=ass'.*matrix;
A.7 Calcolo prestazioni: probabilità d’errore
function BER = calcoloBER(vect,SNR)
Funzione che calcola il BER a partire dai guadagni di canale di tutti gli utenti e dal SNR medio. L'energia viene distribuita tra i vari utenti in modo che il BER sia uguale per tutti. Ciascun utente n viene scalato per alfa*(1/H(n)^2). Imponendo che la potenza massima da distribuire sia N (numero di utenti) => alfa = 1/(media(1/canale))
inverse = 1./vect; Reciproco dei guadagni di canale
Fattore che va a scalare Eb/N0. Se in teoria tutti i canali fossero maggiori di uno => alfa sarebbe maggiore di uno! Prestazioni migliori anche di AWGN
alfa = 1/mean(inverse);
BER = 2*Qfunc((SNR*alfa).^.5);
A.8 Calcolo prestazioni: funzione densità di probabilità
function y = pdf(x)
Funzione che calcola la pdf di una variabile aleatoria partendo dal vettore che x che raccoglie un certo numero di realizzazioni.
nBins = 100; Numero di bins della funzione hist
[freq,bins] = hist(x,nBins); Si calcola con che frequenza la v.a. assume un certo range di valori xMax = max(x);
xMin = min(x);
xDelta = (xMax-xMin)/nBins; xDim = length(x);
y = freq/(xDelta*xDim); Scalo la frequenza relativa per farla diventare una pdf plot(bins,y)