-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathdraft_waterfilling.py
84 lines (57 loc) · 2.08 KB
/
draft_waterfilling.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
""" # Water Filling Algorithm for ZF Beamforming
# Author : Khin Thandar Kyaw
# Reference : https://www.scicoding.com/waterfilling/
# Date : 4 Jan 2023
from NNUtils import *
import numpy as np
import tensorflow as tf
#totalUsers = totalUsersFunc()
def getGain(W, R):
W_H = tf.linalg.adjoint(W)
gain = np.squeeze(tf.math.real(tf.einsum('mqk, mkl, mlp->mqp', W_H, R, W)))
return gain
totalUser = 10
#or totalUser in totalUsers:
print(f'Calculating for {totalUser} users...')
covariance = np.load(f'test/{totalUser}users/cov_test.npy')
_, _, _, _, NoiseVarTotal, _ = dataPreparation(covariance)
beams = np.load(f'test/{totalUser}users/beamZF.npy')
#for snr in range(-5, 25, 5):
snr = -5 #dB
print(f'Calculating for the sum rate using water-filling algorithm at SNR = {snr} dB...')
sumRateAll = []
ErrorAll = []
R = covariance[10] # (totalUser, Nt, Nt)
W = beams[10] # (totalUser, Nt, 1)
noise = NoiseVarTotal[10] #(1,)
SNR = np.power(10, snr / 10)
P_total = SNR * noise # (1,,)
#print(f'P_total: {P_total}')
gain = getGain(W, R) # (totalUser, 1, 1)
print(f'gain: {gain}')
print(f'gain.shape: {gain.shape}\n')
# Bisection search for Lambda
#lowerBound = 0 # Initial lower bound
#upperBound = (P_total + np.sum(gain)) # Initial upper bound
lowerBound = 1 / (P_total + np.sum(1 / gain))
upperBound = np.max(gain)
tolerance = 1e-7
while (upperBound - lowerBound) > tolerance:
mid_point = (lowerBound + upperBound) / 2
# Calculate the power allocation
p = (1 / mid_point) - (1 / gain)
p[p < 0] = 0 # consider only positive power allocation
# Test sum-power constraints
if (np.sum(p) > P_total): # Exceeds power limit => increase the lower bound
lowerBound = mid_point
else: # less than the power limit => decrease the upper bound
upperBound = mid_point
print()
print(f'Power Allocation: {p}\n')
sumRate_m = np.sum(np.log(1 + (p * gain))/np.log(2))
print(f'sumRateWF: {sumRate_m}\n')
error_m = np.abs(P_total - np.sum(p))
print(f'Power Difference: {error_m}\n')
sumRateZF = np.load(f'Plotting/{totalUser}users/sumRateZF.npy')
print(f'sumRateZF: {sumRateZF[0]}')
"""