198 lines
7.7 KiB
Python
198 lines
7.7 KiB
Python
"""
|
||
无线资源分配信道模型 / Channel model for OFDMA wireless resource allocation.
|
||
|
||
该模块实现了 3GPP 风格的路径损耗模型和多用户 OFDMA 下行链路系统的复信道增益生成。
|
||
所有公式遵循论文中的公式 (5)-(8)。
|
||
This module implements the 3GPP-style path loss model and complex channel gain generation
|
||
for a multi-user OFDMA downlink system. All formulas follow the paper's equations (5)–(8).
|
||
|
||
作者/Author: Sisyphus-Junior
|
||
日期/Date: 2026-02-28
|
||
论文引用/Paper Reference: Co-MADDPG based Resource Allocation for Semantic Communication
|
||
依赖/Dependencies: numpy
|
||
"""
|
||
|
||
import numpy as np
|
||
|
||
|
||
class ChannelModel:
|
||
"""
|
||
多用户 OFDMA 系统的频率选择性信道模型。
|
||
Frequency-selective channel model for multi-user OFDMA systems.
|
||
|
||
生成包含距离相关路径损耗和瑞利衰落的每子载波复信道增益,并计算每子载波的信噪比 (SNR)。
|
||
Generates per-subcarrier complex channel gains incorporating distance-dependent
|
||
path loss with Rayleigh fading, and computes per-subcarrier SNR values.
|
||
|
||
Parameters
|
||
----------
|
||
config : dict
|
||
完整的配置字典(必须包含 "env" 部分,且具有 carrier_freq, noise_psd 和 subcarrier_spacing 键)。
|
||
Full configuration dictionary (must contain an "env" section with keys
|
||
"carrier_freq", "noise_psd", and "subcarrier_spacing").
|
||
"""
|
||
|
||
def __init__(self, config: dict) -> None:
|
||
# 初始化环境配置 / Initialize environment configurations
|
||
self.config = config
|
||
env = config["env"]
|
||
# 载波频率 (GHz) / Carrier frequency in GHz
|
||
self._carrier_freq_ghz: float = env["carrier_freq"]
|
||
# 噪声功率谱密度 (dBm/Hz) / Noise power spectral density in dBm/Hz
|
||
self._noise_psd_dbm: float = env["noise_psd"]
|
||
# 子载波间隔 (Hz) / Subcarrier spacing in Hz
|
||
self._subcarrier_spacing: float = env["subcarrier_spacing"]
|
||
|
||
# ------------------------------------------------------------------
|
||
# 路径损耗 / Path loss
|
||
# ------------------------------------------------------------------
|
||
|
||
def path_loss(self, distance: float) -> float:
|
||
"""
|
||
计算与距离相关的路径损耗 (dB)。
|
||
Compute distance-dependent path loss in dB.
|
||
|
||
使用 3GPP Urban Micro (UMi) NLOS 模型 (公式 5):
|
||
Uses the 3GPP Urban Micro (UMi) NLOS model (Eq. 5):
|
||
|
||
PL(d) = 36.7 * log10(d) + 22.7 + 26 * log10(fc)
|
||
|
||
其中 d 的单位为米,fc 的单位为 GHz。
|
||
where *d* is in metres and *fc* is in GHz.
|
||
|
||
Parameters
|
||
----------
|
||
distance : float or np.ndarray
|
||
收发机之间的距离,单位为米。
|
||
Transmitter–receiver distance(s) in metres.
|
||
|
||
Returns
|
||
-------
|
||
float or np.ndarray
|
||
路径损耗值,单位为 dB。
|
||
Path loss value(s) in dB.
|
||
"""
|
||
fc = self._carrier_freq_ghz
|
||
# 应用 3GPP UMi NLOS 公式 / Apply 3GPP UMi NLOS formula - Eq.(5)
|
||
return 36.7 * np.log10(distance) + 22.7 + 26.0 * np.log10(fc)
|
||
|
||
# ------------------------------------------------------------------
|
||
# 信道生成 / Channel generation
|
||
# ------------------------------------------------------------------
|
||
|
||
def generate_channel(
|
||
self, distances: np.ndarray, num_subcarriers: int
|
||
) -> np.ndarray:
|
||
"""
|
||
生成所有用户和子载波的复信道增益。
|
||
Generate complex channel gains for all users and subcarriers.
|
||
|
||
每个元素 h_{k,n} 服从复高斯分布 CN(0, 10^{-PL/10}) (公式 6)。
|
||
即:独立循环对称复高斯分布,其方差等于线性尺度的逆路径损耗。
|
||
Each element h_{k,n} is drawn from CN(0, 10^{-PL/10}) (Eq. 6), i.e.
|
||
independent circularly-symmetric complex Gaussian with variance
|
||
equal to the linear-scale inverse path loss.
|
||
|
||
Parameters
|
||
----------
|
||
distances : array_like, shape (K,)
|
||
每个用户距离基站的距离(米)。
|
||
Distance of each user from the base station (metres).
|
||
num_subcarriers : int
|
||
OFDM 子载波数量 N。
|
||
Number of OFDM subcarriers *N*.
|
||
|
||
Returns
|
||
-------
|
||
np.ndarray, shape (K, N)
|
||
复信道增益矩阵。
|
||
Complex channel gain matrix.
|
||
"""
|
||
distances = np.asarray(distances, dtype=np.float64)
|
||
K = len(distances)
|
||
N = num_subcarriers
|
||
|
||
# 每用户路径损耗 -> 线性尺度信道方差 / Per-user path loss -> linear-scale channel variance
|
||
pl_db = self.path_loss(distances) # (K,)
|
||
# 方差 = 10^(-PL/10) / Variance = 10^(-PL/10) - Eq.(6)
|
||
variance = 10.0 ** (-pl_db / 10.0) # (K,)
|
||
variance = variance.reshape(K, 1) # (K, 1) 用于广播 / for broadcasting
|
||
|
||
# 复高斯:每个分量服从 N(0, var/2) / Complex Gaussian: each component ~ N(0, var/2)
|
||
std = np.sqrt(variance / 2.0)
|
||
# 生成实部和虚部 / Generate real and imaginary parts
|
||
real_part = np.random.randn(K, N) * std
|
||
imag_part = np.random.randn(K, N) * std
|
||
|
||
# 返回复增益 / Return complex gains
|
||
return real_part + 1j * imag_part
|
||
|
||
# ------------------------------------------------------------------
|
||
# SNR 计算 / SNR computation
|
||
# ------------------------------------------------------------------
|
||
|
||
def compute_snr(
|
||
self,
|
||
channel_gains: np.ndarray,
|
||
power_alloc: np.ndarray,
|
||
noise_power: float,
|
||
) -> np.ndarray:
|
||
"""
|
||
计算每个用户的每子载波信噪比 (SNR)。
|
||
Compute per-subcarrier SNR for every user.
|
||
|
||
γ_{k,n} = p_{k,n} * |h_{k,n}|² / σ² (公式 8)
|
||
γ_{k,n} = p_{k,n} · |h_{k,n}|² / σ² (Eq. 8)
|
||
|
||
Parameters
|
||
----------
|
||
channel_gains : np.ndarray, shape (K, N)
|
||
复信道增益矩阵。
|
||
Complex channel gain matrix.
|
||
power_alloc : np.ndarray, shape (K, N)
|
||
每个用户在每个子载波上分配的功率(瓦特)。
|
||
Power allocated by each user on each subcarrier (Watts).
|
||
noise_power : float
|
||
每子载波的噪声功率 σ²(瓦特)。
|
||
Noise power σ² per subcarrier (Watts).
|
||
|
||
Returns
|
||
-------
|
||
np.ndarray, shape (K, N)
|
||
SNR 值(线性尺度)。
|
||
SNR values (linear scale).
|
||
"""
|
||
# 计算 SNR = 功率 * 增益平方 / 噪声 / Compute SNR = Power * Gain^2 / Noise - Eq.(8)
|
||
return power_alloc * (np.abs(channel_gains) ** 2) / noise_power
|
||
|
||
# ------------------------------------------------------------------
|
||
# 噪声功率属性 / Noise power property
|
||
# ------------------------------------------------------------------
|
||
|
||
@property
|
||
def noise_power(self) -> float:
|
||
"""
|
||
每子载波的热噪声功率 (瓦特)。
|
||
Thermal noise power per subcarrier (Watts).
|
||
|
||
σ² = N₀ * Δf (公式 7)
|
||
σ² = N₀ · Δf (Eq. 7)
|
||
|
||
其中 N₀ 是从 dBm/Hz 转换为线性 (W/Hz) 的噪声功率谱密度:
|
||
where N₀ is the noise PSD converted from dBm/Hz to linear (W/Hz):
|
||
|
||
N₀_linear = 10^((N₀_dBm - 30) / 10)
|
||
|
||
Returns
|
||
-------
|
||
float
|
||
噪声功率(瓦特)。
|
||
Noise power in Watts.
|
||
"""
|
||
n0_dbm = self._noise_psd_dbm
|
||
delta_f = self._subcarrier_spacing
|
||
# 转换为线性功率谱密度 / Convert to linear PSD - Eq.(7)
|
||
n0_linear = 10.0 ** ((n0_dbm - 30.0) / 10.0)
|
||
# 计算总噪声功率 / Compute total noise power
|
||
return n0_linear * delta_f
|