Initial commit: add project materials and code

This commit is contained in:
hc
2026-02-28 16:17:42 +08:00
commit 5efb877df7
198 changed files with 17541 additions and 0 deletions
+10
View File
@@ -0,0 +1,10 @@
# Utils initialization module
from .metrics import (
jain_fairness,
rate_satisfaction,
compute_system_qoe,
compute_lambda,
compute_mixed_reward,
moving_average
)
from .visualization import Plotter
+193
View File
@@ -0,0 +1,193 @@
"""
Co-MADDPG Evaluation Metrics | Co-MADDPG 评估指标
This module provides the core performance metrics and reward calculation logic for
the cooperative-competitive multi-agent reinforcement learning (Co-MADDPG) framework
in hybrid semantic-traditional wireless resource allocation.
本模块为混合语义-传统无线资源分配中的协作-竞争多智能体强化学习(Co-MADDPG)框架
提供核心性能指标和奖励计算逻辑。
Key Metrics:
- Jain's Fairness Index / Jain 公平性指数
- Rate Satisfaction Ratio / 速率满足率
- System-level QoE / 系统级体验质量
- Dynamic Cooperation Weight (λ) / 动态协作权重 (λ)
- Mixed Reward Mechanism / 混合奖励机制
Reference:
- "Dynamic Cooperative-Competitive Multi-Agent Reinforcement Learning for
Resource Allocation in Semantic-Traditional Hybrid Wireless Networks"
"""
import numpy as np
def jain_fairness(values) -> float:
"""
Compute Jain's fairness index. | 计算 Jain 公平性指数。
Formula: J = (Σ x_i)² / (n · Σ x_i²)
公式:J = (Σ x_i)² / (n · Σ x_i²)
Returns 0.0 if all values are zero or empty. | 如果所有值均为零或为空,则返回 0.0。
Parameters
----------
values : array_like
Resource allocation or performance metrics (e.g., rates, QoE).
资源分配或性能指标(例如:速率、QoE)。
Returns
-------
float
Fairness index in range [1/n, 1.0].
[1/n, 1.0] 范围内的公平性指数。
"""
values = np.asarray(values, dtype=np.float64)
if len(values) == 0:
return 0.0
sum_sq = np.sum(values ** 2)
# Avoid division by zero | 避免除以零
if sum_sq == 0:
return 0.0
# Calculate J index | 计算 J 指数
return float(np.sum(values) ** 2 / (len(values) * sum_sq))
def rate_satisfaction(rates, r_req: float) -> float:
"""
Fraction of users meeting minimum rate requirement. | 满足最小速率要求的用户比例。
Parameters
----------
rates : array_like
Per-user achievable rates.
每个用户可达到的速率。
r_req : float
Minimum rate requirement threshold (R_req).
最小速率要求阈值 (R_req)。
Returns
-------
float
Fraction in [0, 1].
[0, 1] 范围内的比例。
"""
rates = np.asarray(rates)
if len(rates) == 0:
return 1.0
# Count how many users' rates exceed the requirement | 统计速率超过要求的用户数量
return float(np.mean(rates >= r_req))
def compute_system_qoe(qoe_list) -> float:
"""
Compute system-level QoE as mean of per-user QoE values. | 计算系统级 QoE,即用户 QoE 的平均值。
Parameters
----------
qoe_list : array_like
List of QoE values for all active users.
所有活跃用户的 QoE 值列表。
Returns
-------
float
Mean system QoE.
平均系统 QoE。
"""
if len(qoe_list) == 0:
return 0.0
# Simple arithmetic mean | 简单算术平均值
return float(np.mean(qoe_list))
def compute_lambda(qoe_sys: float, beta: float = 5.0,
q_th: float = 0.6) -> float:
"""
Compute dynamic cooperation weight λ using sigmoid function. | 使用 Sigmoid 函数计算动态协作权重 λ。
λ(t) = 1 / (1 + exp(-β · (QoE_sys - Q_th)))
Parameters
----------
qoe_sys : float
Current system-level QoE.
当前系统级 QoE。
beta : float
Steepness of the switching transition (β).
切换过渡的陡峭程度 (β)。
q_th : float
QoE threshold for cooperative behavior (Q_th).
协作行为的 QoE 阈值 (Q_th)。
Returns
-------
float
λ value in [0, 1], representing the degree of cooperation.
[0, 1] 范围内的 λ 值,代表协作程度。
"""
# Sigmoid function maps QoE difference to [0, 1] | Sigmoid 函数将 QoE 差异映射到 [0, 1]
return float(1.0 / (1.0 + np.exp(-beta * (qoe_sys - q_th))))
def compute_mixed_reward(qoe_self: float, qoe_other: float,
qoe_sys: float, lambda_val: float,
coop_w=(0.5, 0.3, 0.2),
comp_w=(0.8, 0.2)) -> float:
"""
Compute dynamically mixed cooperative-competitive reward. | 计算动态混合的协作-竞争奖励。
r = λ · r_coop + (1-λ) · r_comp
Parameters
----------
qoe_self : float
Individual QoE of the agent. | 智能体自身的 QoE。
qoe_other : float
Mean QoE of other agents in the same cell. | 同小区内其他智能体的平均 QoE。
qoe_sys : float
Overall system QoE. | 系统整体 QoE。
lambda_val : float
Dynamic cooperation weight (λ). | 动态协作权重 (λ)。
coop_w : tuple
Weights for cooperative reward (self, others, system). | 协作奖励权重(自身、他人、系统)。
comp_w : tuple
Weights for competitive reward (self, system). | 竞争奖励权重(自身、系统)。
Returns
-------
float
The final mixed reward value. | 最终混合奖励值。
"""
# Cooperative reward emphasizes global performance | 协作奖励强调全局性能
r_coop = coop_w[0] * qoe_self + coop_w[1] * qoe_other + coop_w[2] * qoe_sys
# Competitive reward focuses more on individual gain | 竞争奖励更关注个人收益
r_comp = comp_w[0] * qoe_self + comp_w[1] * qoe_sys
# Linear combination based on lambda | 基于 lambda 的线性组合
return float(lambda_val * r_coop + (1.0 - lambda_val) * r_comp)
def moving_average(values, window: int = 50) -> np.ndarray:
"""
Compute moving average of a series for visualization smoothing. | 计算序列的移动平均值,用于可视化平滑。
Parameters
----------
values : array_like
Input time series data. | 输入的时间序列数据。
window : int
Smoothing window size. | 平滑窗口大小。
Returns
-------
np.ndarray
Smoothed series. | 平滑后的序列。
"""
values = np.asarray(values, dtype=np.float64)
if len(values) < window:
return values
# Standard 1D convolution for moving average | 用于移动平均的标准一维卷积
return np.convolve(values, np.ones(window) / window, mode='valid')
+313
View File
@@ -0,0 +1,313 @@
"""
Co-MADDPG Visualization Module | Co-MADDPG 可视化模块
This module handles the generation of IEEE-standard figures for the resource
allocation performance evaluation. It maps specifically to Section VII (Experimental
Results) of the associated research paper.
本模块负责生成符合 IEEE 标准的资源分配性能评估图表。它专门对应于相关研究论文的
第七节(实验结果)。
Reference Figures (from Section VII):
- Fig 2: Training convergence curves | 训练收敛曲线
- Fig 3: System QoE vs. SNR | 系统 QoE 随 SNR 的变化
- Fig 4: Jain's Fairness Index vs. SNR | Jain 公平性指数随 SNR 的变化
- Fig 5: System QoE vs. Total Users (K) | 系统 QoE 随总用户数 (K) 的变化
- Fig 6: Rate Satisfaction Ratio vs. Total Users (K) | 速率满足率随总用户数 (K) 的变化
- Fig 7: Trajectory of λ(t) over time | λ(t) 随时间的变化轨迹
- Fig 8: Correlation scatter of λ and System QoE | λ 与系统 QoE 的相关性散点图
- Fig 9: System QoE vs. Semantic User Ratio | 系统 QoE 随语义用户比例的变化
- Fig 10: Ablation study results | 消融实验结果
- Fig 11: Sensitivity analysis of β | β 参数的敏感性分析
- Fig 12: Sensitivity analysis of Q_th | Q_th 阈值的敏感性分析
"""
import os
import numpy as np
import matplotlib
# Use non-interactive backend to avoid requiring an X server or display
# 使用非交互式后端以避免需要 X 服务器或显示器
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from utils.metrics import moving_average
# IEEE-quality plotting defaults | IEEE 质量绘图默认设置
plt.rcParams.update({
'font.family': 'serif',
'font.serif': ['Times New Roman', 'DejaVu Serif'],
'font.size': 12,
'axes.grid': True,
'figure.figsize': (8, 6),
'figure.autolayout': True, # Equivalent to tight_layout | 等同于 tight_layout
'savefig.dpi': 300,
'savefig.bbox': 'tight'
})
# Consistent algorithm styles | 一致的算法绘图风格
# Color and marker choices distinguish between proposed, baselines, and ablation variants
# 颜色和标记的选择用于区分建议算法、基准算法和消融变体
ALGO_STYLES = {
'Co-MADDPG': {'color': '#E24A33', 'marker': 'o', 'linestyle': '-'}, # Proposed (Red) | 建议算法(红色)
'Pure Cooperative': {'color': '#348ABD', 'marker': 's', 'linestyle': '--'}, # Baseline (Blue) | 基准(蓝色)
'Pure Competitive': {'color': '#988ED5', 'marker': '^', 'linestyle': '--'}, # Baseline (Purple) | 基准(紫色)
'Single-Agent DQN': {'color': '#777777', 'marker': 'D', 'linestyle': '-.'}, # Baseline (Gray) | 基准(灰色)
'IDDPG': {'color': '#FBC15E', 'marker': 'v', 'linestyle': '-.'}, # Baseline (Yellow) | 基准(黄色)
'Fixed λ=0.5': {'color': '#8EBA42', 'marker': 'p', 'linestyle': ':'}, # Ablation (Green) | 消融(绿色)
'Equal Allocation': {'color': '#FFB5B8', 'marker': '*', 'linestyle': ':'}, # Baseline (Pink) | 基准(粉色)
'Semantic-Only': {'color': '#6d904f', 'marker': 'h', 'linestyle': ':'}, # Baseline (Olive) | 基准(橄榄色)
}
class Plotter:
"""
IEEE-quality plotting module for all paper figures. | 用于所有论文图表的 IEEE 质量绘图模块。
"""
def __init__(self):
pass
def _get_style(self, algo_name):
"""
Helper to get plotting style for an algorithm or a sensible default.
获取算法的绘图风格或合理的默认值。
"""
return ALGO_STYLES.get(algo_name, {'color': 'k', 'marker': '', 'linestyle': '-'})
def _save_plot(self, save_path):
"""
Helper to save plot in both PDF and PNG formats at 300 DPI.
以 300 DPI 的分辨率将图表保存为 PDF 和 PNG 格式。
"""
os.makedirs(os.path.dirname(os.path.abspath(save_path)), exist_ok=True)
# Strip extension if the user provided one, to consistently save both .pdf and .png
# 如果用户提供了扩展名,则将其去除,以便一致地保存 .pdf 和 .png
base_path = os.path.splitext(save_path)[0]
plt.savefig(f"{base_path}.pdf", format='pdf')
plt.savefig(f"{base_path}.png", format='png', dpi=300)
plt.close()
def plot_convergence(self, data_dict, save_path):
"""
Fig 2: Episode QoE_sys curves. | 图 2:每回合系统 QoE 曲线。
Shows how the algorithm improves over training episodes.
展示算法在训练回合中如何改进。
data_dict: {algo_name: [episode_qoe_values]}
"""
plt.figure()
for algo, qoe_vals in data_dict.items():
style = self._get_style(algo)
# Remove markers for dense convergence plots to maintain clean look
# 为密集的收敛图移除标记以保持画面整洁
plot_style = style.copy()
if 'marker' in plot_style:
plot_style.pop('marker')
smoothed_qoe = moving_average(qoe_vals, window=50)
x_vals = np.arange(len(smoothed_qoe))
plt.plot(x_vals, smoothed_qoe, label=algo, **plot_style)
plt.xlabel('Episode')
plt.ylabel('System QoE')
plt.title('Training Convergence')
plt.legend()
self._save_plot(save_path)
def plot_qoe_vs_snr(self, data_dict, save_path):
"""
Fig 3: QoE vs SNR. | 图 3QoE 随 SNR 的变化。
Evaluates system robustness under different noise levels.
评估不同噪声水平下的系统鲁棒性。
data_dict: {algo_name: [qoe_per_snr_point]}
"""
plt.figure()
snr_vals = [0, 5, 10, 15, 20, 25, 30]
for algo, qoe_vals in data_dict.items():
style = self._get_style(algo)
plt.plot(snr_vals, qoe_vals, label=algo, **style)
plt.xlabel('SNR (dB)')
plt.ylabel('System QoE')
plt.title('System QoE vs. SNR')
plt.legend()
self._save_plot(save_path)
def plot_fairness_vs_snr(self, data_dict, save_path):
"""
Fig 4: Jain Fairness Index vs SNR. | 图 4Jain 公平性指数随 SNR 的变化。
Measures the balance of resource allocation across users.
衡量不同用户之间资源分配的平衡性。
data_dict: {algo_name: [fairness_per_snr_point]}
"""
plt.figure()
snr_vals = [0, 5, 10, 15, 20, 25, 30]
for algo, fairness_vals in data_dict.items():
style = self._get_style(algo)
plt.plot(snr_vals, fairness_vals, label=algo, **style)
plt.xlabel('SNR (dB)')
plt.ylabel('Jain Fairness Index')
plt.title('Fairness vs. SNR')
plt.legend()
self._save_plot(save_path)
def plot_qoe_vs_users(self, data_dict, save_path):
"""
Fig 5: QoE vs Total Users K. | 图 5QoE 随总用户数 K 的变化。
Tests system scalability as user density increases.
测试随着用户密度增加系统的可扩展性。
data_dict: {algo_name: [qoe_per_k_point]}
"""
plt.figure()
users_vals = [4, 6, 8, 10, 12]
for algo, qoe_vals in data_dict.items():
style = self._get_style(algo)
plt.plot(users_vals, qoe_vals, label=algo, **style)
plt.xlabel('Total Users (K)')
plt.ylabel('System QoE')
plt.title('System QoE vs. Total Users')
plt.legend()
self._save_plot(save_path)
def plot_rate_satisfaction_vs_users(self, data_dict, save_path):
"""
Fig 6: Rate Satisfaction Ratio vs Total Users K. | 图 6:速率满足率随总用户数 K 的变化。
Evaluates the ability to meet minimum QoS requirements.
评估满足最小 QoS 要求的能力。
data_dict: {algo_name: [rate_satisfaction_per_k_point]}
"""
plt.figure()
users_vals = [4, 6, 8, 10, 12]
for algo, sat_vals in data_dict.items():
style = self._get_style(algo)
plt.plot(users_vals, sat_vals, label=algo, **style)
plt.xlabel('Total Users (K)')
plt.ylabel('Rate Satisfaction Ratio')
plt.title('Rate Satisfaction vs. Total Users')
plt.legend()
self._save_plot(save_path)
def plot_lambda_trajectory(self, lambda_values, save_path):
"""
Fig 7: Lambda Trajectory. | 图 7Lambda 轨迹。
Visualizes the dynamic switching between cooperation and competition.
可视化协作与竞争之间的动态切换。
lambda_values: list of lambda(t) values.
"""
plt.figure()
time_steps = np.arange(len(lambda_values))
plt.plot(time_steps, lambda_values, label=r'$\lambda(t)$', color='#348ABD', linestyle='-')
# Reference line for fixed weighting | 固定权重的参考线
plt.axhline(y=0.5, color='#E24A33', linestyle='--', label=r'Reference ($\lambda=0.5$)')
plt.xlabel('Time Step')
plt.ylabel(r'$\lambda(t)$')
plt.title(r'Trajectory of Allocation Parameter $\lambda$')
plt.legend()
self._save_plot(save_path)
def plot_lambda_qoe_scatter(self, lambdas, qoes, save_path):
"""
Fig 8: Scatter of (lambda, QoE_sys). | 图 8(lambda, QoE_sys) 散点图。
Shows the correlation between the dynamic parameter and system performance.
展示动态参数与系统性能之间的相关性。
"""
plt.figure()
time_steps = np.arange(len(lambdas))
# Color points by time to show evolution | 按时间为点着色以显示演化过程
sc = plt.scatter(lambdas, qoes, c=time_steps, cmap='viridis', alpha=0.7)
cbar = plt.colorbar(sc)
cbar.set_label('Time Step')
plt.xlabel(r'$\lambda$')
plt.ylabel('System QoE')
plt.title(r'Correlation between $\lambda$ and System QoE')
self._save_plot(save_path)
def plot_qoe_vs_ratio(self, data_dict, ratios, save_path):
"""
Fig 9: QoE vs Semantic User Ratio. | 图 9QoE 随语义用户比例的变化。
Studies the impact of increasing semantic communication prevalence.
研究语义通信普及率增加的影响。
data_dict: {algo_name: [qoe_values]}
"""
plt.figure()
for algo, qoe_vals in data_dict.items():
style = self._get_style(algo)
plt.plot(ratios, qoe_vals, label=algo, **style)
plt.xlabel('Semantic User Ratio')
plt.ylabel('System QoE')
plt.title('System QoE vs. Semantic User Ratio')
plt.legend()
self._save_plot(save_path)
def plot_ablation(self, data, save_path):
"""
Fig 10: Horizontal bar chart for ablation study. | 图 10:消融研究的水平条形图。
Compares the full Co-MADDPG against its stripped-down variants.
将完整的 Co-MADDPG 与其简化变体进行比较。
data: {variant_label: qoe_value}
"""
plt.figure()
labels = list(data.keys())
values = list(data.values())
y_pos = np.arange(len(labels))
# Highlight Co-MADDPG (Full) in red if present | 如果存在,用红色高亮 Co-MADDPG (Full)
colors = ['#E24A33' if 'Co-MADDPG' in label and 'Full' in label else '#348ABD' for label in labels]
plt.barh(y_pos, values, align='center', color=colors)
plt.yticks(y_pos, labels)
plt.xlabel('System QoE')
plt.title('Ablation Study')
self._save_plot(save_path)
def plot_beta_sensitivity(self, data_dict, betas, save_path):
"""
Fig 11: QoE vs Beta values. | 图 11QoE 随 Beta 值的变化。
Analyzes sensitivity to the sigmoid steepness parameter.
分析对 Sigmoid 陡峭度参数的敏感性。
data_dict: {label: qoe_value_list}
"""
plt.figure()
for algo, qoe_vals in data_dict.items():
style = self._get_style(algo)
plt.plot(betas, qoe_vals, label=algo, **style)
plt.xlabel(r'$\beta$ Parameter')
plt.ylabel('System QoE')
plt.title(r'Sensitivity Analysis of $\beta$')
plt.legend()
self._save_plot(save_path)
def plot_qth_sensitivity(self, data_dict, qths, save_path):
"""
Fig 12: QoE vs Q_th values. | 图 12QoE 随 Q_th 值的变化。
Analyzes sensitivity to the cooperation threshold.
分析对协作阈值的敏感性。
data_dict: {label: qoe_value_list}
"""
plt.figure()
for algo, qoe_vals in data_dict.items():
style = self._get_style(algo)
plt.plot(qths, qoe_vals, label=algo, **style)
plt.xlabel(r'$Q_{th}$ Threshold')
plt.ylabel('System QoE')
plt.title(r'Sensitivity Analysis of $Q_{th}$')
plt.legend()
self._save_plot(save_path)