PADC
# The (real) AWGN channel
def AWGN_channel(x, snr, P=2):
batch_size, length = x.shape
gamma = 10 ** (snr / 10.0).to(args.device)
noise = torch.sqrt(P / gamma) * torch.randn(batch_size, length).to(args.device)
y = x + noise
return y
# Please set the symbol power if it is not a default value
def Fading_channel(x, snr, P=2):
gamma = 10 ** (snr / 10.0)
[batch_size, feature_length] = x.shape
K = feature_length // 2
h_I = torch.randn(batch_size, K).to(args.device)
h_R = torch.randn(batch_size, K).to(args.device)
h_com = torch.complex(h_I, h_R)
x_com = torch.complex(x[:, 0:feature_length:2], x[:, 1:feature_length:2])
y_com = h_com * x_com
n_I = torch.sqrt(P / gamma) * torch.randn(batch_size, K).to(args.device)
n_R = torch.sqrt(P / gamma) * torch.randn(batch_size, K).to(args.device)
noise = torch.complex(n_I, n_R)
y_add = y_com + noise
y = y_add / h_com
y_out = torch.zeros(batch_size, feature_length).to(args.device)
y_out[:, 0:feature_length:2] = y.real
y_out[:, 1:feature_length:2] = y.imag
return y_out
PAPR
def channel(self, data_x):
inputBS, len_data_x = data_x.size(0), data_x.size(1)
noise_std = 10 ** (-self.args.snr * 1.0 / 10 / 2)
# real channel
AWGN = torch.normal(0, std=noise_std, size=(inputBS, len_data_x), requires_grad=False).to(self.args.device)
if self.args.fading == 1:
# at the receiver, the equivalent noise power is reduced by self.hh**2
self.hh = np.random.rayleigh(self.args.hstd, 1) # sigma and number of samples
else:
self.hh = np.array([1])
data_r = torch.from_numpy(self.hh).type(torch.float32).to(self.args.device) * data_x + AWGN
return data_r
NTSCC
class Channel(nn.Module):
def __init__(self, config):
super(Channel, self).__init__()
self.config = config
self.chan_type = config.channel['type']
self.chan_param = config.channel['chan_param']
self.device = config.device
if config.logger:
config.logger.info('【Channel】: Built {} channel, SNR {} dB.'.format(
config.channel['type'], config.channel['chan_param']))
def gaussian_noise_layer(self, input_layer, std):
device = input_layer.get_device()
noise_real = torch.normal(mean=0.0, std=std, size=np.shape(input_layer), device=device)
noise_imag = torch.normal(mean=0.0, std=std, size=np.shape(input_layer), device=device)
noise = noise_real + 1j * noise_imag
return input_layer + noise
def forward(self, input, avg_pwr=None, power=1):
if avg_pwr is None:
avg_pwr = torch.mean(input ** 2)
channel_tx = np.sqrt(power) * input / torch.sqrt(avg_pwr * 2)
else:
channel_tx = np.sqrt(power) * input / torch.sqrt(avg_pwr * 2)
input_shape = channel_tx.shape
channel_in = channel_tx.reshape(-1)
channel_in = channel_in[::2] + channel_in[1::2] * 1j
channel_usage = channel_in.numel()
channel_output = self.channel_forward(channel_in)
channel_rx = torch.zeros_like(channel_tx.reshape(-1))
channel_rx[::2] = torch.real(channel_output)
channel_rx[1::2] = torch.imag(channel_output)
channel_rx = channel_rx.reshape(input_shape)
return channel_rx * torch.sqrt(avg_pwr * 2), channel_usage
def channel_forward(self, channel_in):
if self.chan_type == 0 or self.chan_type == 'noiseless':
return channel_in
elif self.chan_type == 1 or self.chan_type == 'awgn':
channel_tx = channel_in
sigma = np.sqrt(1.0 / (2 * 10 ** (self.chan_param / 10)))
chan_output = self.gaussian_noise_layer(channel_tx,
std=sigma)
return chan_output
TASK
snr = 10 # dB
aver_noise = aver / 10 ** (snr / 10)
noise = torch.randn(size=out.shape) * np.sqrt(aver_noise)
noise = noise.to(device)
out = out + noise