5信息论基础(第2版)

信道容量

通信的理论极限

信道互信息信道容量香农定理

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第5章 信道容量(Channel Capacity)

一、导读

5.1 本章学习目标

通过本章的学习,你将能够:

理解通信信道的数学模型:掌握离散无记忆信道(DMC)的定义和表示方法

掌握互信息与信道传输的关系:理解为什么互信息度量了信道传递的信息量

掌握信道容量的定义:理解 $C = \max_{p(x)} I(X;Y)$ 的含义和计算方法

掌握几种典型信道的容量:能够计算二元对称信道、二元擦除信道、高斯信道的容量

理解信道编码定理的意义:理解为什么只要传输速率小于容量,就可以实现任意小的错误概率

掌握水填充算法的思想:理解如何在并行高斯信道间分配功率以最大化总容量

能够分析实际通信系统的性能极限:理解香农公式在无线通信中的应用

理解反馈对信道容量的影响:掌握反馈是否能增加信道容量这一经典问题的答案

5.2 为什么本章如此重要

信道容量是信息论中最深刻的概念之一。它给出了可靠通信的绝对极限:无论采用多么复杂的编码方案,传输速率都不能超过信道容量。这个结果看似简单,却蕴含着深刻的物理洞察。

理论重要性:

信道编码定理(香农第二定理)与信源编码定理一起构成了信息论的两大支柱。如果说信源编码定理告诉我们数据可以被压缩到什么程度,信道编码定理则告诉我们数据可以以多快的速度可靠传输。这两个定理共同定义了通信系统的基本极限。

实践重要性:

从2G到5G移动通信,从WiFi到卫星通信,所有现代通信系统的设计都受到信道容量的制约。香农公式 $C = B \log_2(1 + SNR)$ 是通信工程师最常用的公式之一,它指导了频谱资源的分配和调制方案的选择。

方法论重要性:

信道容量的计算方法(优化互信息)是信息论优化的典型范例。随机码本构造和联合典型性译码的证明技巧在网络信息论中反复出现。理解这些方法对于学习更高级的主题至关重要。

5.3 核心问题引导

在学习本章之前,请思考以下问题:

什么是"信道"? 噪声如何影响信息的传输?为什么有些信道比其他信道"更好"?

为什么互信息 $I(X;Y)$ 能度量信道传递的信息量? 它与信道的噪声水平有什么关系?

信道容量为什么要对输入分布求最大值? 不同的输入分布如何影响传输的信息量?

二元对称信道的容量是多少? 当交叉概率 $p=0.5$ 时,容量为0意味着什么?

香农公式 $C = B \log_2(1 + SNR)$ 的物理意义是什么? 带宽和信噪比哪个更重要?

如果传输速率超过信道容量会发生什么? 为什么不可能实现可靠通信?

反馈能提高信道容量吗? 直觉上,知道接收端的情况应该能帮助发送端调整策略,但事实如何?

无线信道的衰落如何影响容量? 为什么分集技术可以提高有效容量?


二、核心概念详解

5.1 信道模型

5.1.1 离散无记忆信道(DMC)

定义:一个离散无记忆信道由以下要素定义:

  • 输入字母表 $\mathcal{X}$
  • 输出字母表 $\mathcal{Y}$
  • 转移概率 $p(y|x)$,表示给定输入 $x$ 时输出 $y$ 的条件概率

无记忆性:每个输出只依赖于对应的输入,不依赖于之前的输入或输出:

$$p(y^n|x^n) = \prod_{i=1}^n p(y_i|x_i)$$

矩阵表示:对于有限字母表,信道可以用转移概率矩阵表示:

$$P = \begin{pmatrix} p(y_1|x_1) & p(y_2|x_1) & \cdots \\ p(y_1|x_2) & p(y_2|x_2) & \cdots \\ \vdots & \vdots & \ddots \end{pmatrix}$$

每行之和为1(概率归一化)。

5.1.2 典型信道示例

二元对称信道(BSC, Binary Symmetric Channel):

  • 输入/输出:$\mathcal{X} = \mathcal{Y} = \{0, 1\}$
  • 转移概率:$p(y=x) = 1-p$,$p(y \neq x) = p$
  • 参数:交叉概率 $p \in [0, 0.5]$

转移矩阵:

$$P = \begin{pmatrix} 1-p & p \\ p & 1-p \end{pmatrix}$$

直观理解:每个比特以概率 $p$ 翻转,以概率 $1-p$ 正确传输。当 $p=0$ 时无噪声,当 $p=0.5$ 时输出与输入独立(完全噪声)。

二元擦除信道(BEC, Binary Erasure Channel):

  • 输入:$\mathcal{X} = \{0, 1\}$
  • 输出:$\mathcal{Y} = \{0, 1, e\}$($e$ 表示擦除)
  • 转移概率:$p(y=x) = 1-\epsilon$,$p(y=e) = \epsilon$

直观理解:每个比特以概率 $\epsilon$ 被擦除(接收端知道出错了),以概率 $1-\epsilon$ 正确传输。与BSC不同,BEC的接收端知道哪些比特出错了。

Z信道:

  • 输入/输出:$\{0, 1\}$
  • 转移概率:只有 $0 \to 1$ 会出错,$1 \to 0$ 不会出错
  • 不对称噪声模型

代码示例5-1:信道可视化

python
import numpy as np
import matplotlib.pyplot as plt

def plot_channel(channel_name, transfer_matrix, input_labels=None, output_labels=None):
    """可视化信道转移概率"""
    
    if input_labels is None:
        input_labels = [f'x{i}' for i in range(transfer_matrix.shape[0])]
    if output_labels is None:
        output_labels = [f'y{j}' for j in range(transfer_matrix.shape[1])]
    
    fig, ax = plt.subplots(figsize=(8, 6))
    
    # 绘制热力图
    im = ax.imshow(transfer_matrix, cmap='Blues', aspect='auto')
    
    # 添加数值标签
    for i in range(transfer_matrix.shape[0]):
        for j in range(transfer_matrix.shape[1]):
            ax.text(j, i, f'{transfer_matrix[i, j]:.2f}', 
                   ha='center', va='center', fontsize=12)
    
    ax.set_xticks(range(len(output_labels)))
    ax.set_yticks(range(len(input_labels)))
    ax.set_xticklabels(output_labels, fontsize=11)
    ax.set_yticklabels(input_labels, fontsize=11)
    ax.set_xlabel('输出 Y', fontsize=12)
    ax.set_ylabel('输入 X', fontsize=12)
    ax.set_title(f'{channel_name} 转移概率', fontsize=14)
    
    plt.colorbar(im)
    plt.tight_layout()
    plt.savefig(f'{channel_name.replace(" ", "_")}.png', dpi=150)
    plt.show()

# 二元对称信道 (p=0.1)
bsc_matrix = np.array([[0.9, 0.1], [0.1, 0.9]])
plot_channel("Binary Symmetric Channel (p=0.1)", bsc_matrix, 
             ['0', '1'], ['0', '1'])

# 二元擦除信道 (ε=0.2)
bec_matrix = np.array([[0.8, 0, 0.2], [0, 0.8, 0.2]])
plot_channel("Binary Erasure Channel (ε=0.2)", bec_matrix,
             ['0', '1'], ['0', '1', 'e'])

5.2 互信息与信道

5.2.1 互信息的重新审视

对于信道,我们关心的是:给定输入分布 $p(x)$,通过信道传输后,输出 $Y$ 包含多少关于输入 $X$ 的信息?

这正是互信息的定义:

$$I(X;Y) = H(Y) - H(Y|X) = H(X) - H(X|Y)$$

解释:

  • $H(Y)$:输出的总不确定性
  • $H(Y|X)$:已知输入后输出的剩余不确定性(由噪声引起)
  • $I(X;Y)$:输出中与输入相关的部分,即成功传输的信息量

5.2.2 互信息的性质

对称性:$I(X;Y) = I(Y;X)$

非负性:$I(X;Y) \geq 0$,等号成立当且仅当 $X$ 和 $Y$ 独立

链式法则:$I(X_1, X_2; Y) = I(X_1; Y) + I(X_2; Y | X_1)$

数据处理不等式:如果 $X \to Y \to Z$,则 $I(X;Y) \geq I(X;Z)$

凸性/凹性:

  • 固定 $p(y|x)$,$I(X;Y)$ 是 $p(x)$ 的凹函数
  • 固定 $p(x)$ 和 $p(y|x)$,$I(X;Y)$ 是 $p(y|x)$ 的凸函数

凹性的证明对于信道容量的计算至关重要,因为它保证了最大值存在且可以通过凸优化找到。

5.2.3 互信息的计算

例子:BSC信道的互信息

设输入 $X \sim \text{Bernoulli}(q)$,即 $P(X=0)=q$,$P(X=1)=1-q$。

输出分布:

$$P(Y=0) = q(1-p) + (1-q)p = q(1-2p) + p$$

$$P(Y=1) = 1 - P(Y=0)$$

条件熵:

$$H(Y|X) = q H_b(p) + (1-q) H_b(p) = H_b(p)$$

其中 $H_b(p) = -p\log_2 p - (1-p)\log_2(1-p)$ 是二元熵函数。

输出熵:

$$H(Y) = H_b(q(1-2p) + p)$$

互信息:

$$I(X;Y) = H_b(q(1-2p) + p) - H_b(p)$$

代码示例5-2:互信息计算

python
import numpy as np

def binary_entropy(p):
    """二元熵函数"""
    if p == 0 or p == 1:
        return 0
    return -p * np.log2(p) - (1-p) * np.log2(1-p)

def mutual_information_bsc(q, p):
    """
    BSC信道的互信息
    
    参数:
        q: P(X=0)
        p: 交叉概率
    
    返回:
        I(X;Y) in bits
    """
    # H(Y|X)
    h_y_given_x = binary_entropy(p)
    
    # P(Y=0)
    p_y0 = q * (1-p) + (1-q) * p
    
    # H(Y)
    h_y = binary_entropy(p_y0)
    
    # I(X;Y) = H(Y) - H(Y|X)
    return h_y - h_y_given_x

# 测试
p = 0.1  # 交叉概率
q_values = np.linspace(0.01, 0.99, 50)
mi_values = [mutual_information_bsc(q, p) for q in q_values]

print(f"BSC信道 (p={p}) 的互信息")
print("=" * 50)
print(f"最大互信息: {max(mi_values):.4f} bits")
print(f"达到最大的 q: {q_values[np.argmax(mi_values)]:.4f}")

# 可视化
import matplotlib.pyplot as plt

plt.figure(figsize=(10, 6))
plt.plot(q_values, mi_values, 'b-', linewidth=2.5)
plt.xlabel('q = P(X=0)', fontsize=12)
plt.ylabel('I(X;Y) (bits)', fontsize=12)
plt.title(f'BSC信道互信息 vs 输入分布 (p={p})', fontsize=14)
plt.grid(True, alpha=0.3)
plt.axvline(x=0.5, color='r', linestyle='--', alpha=0.5, label='q=0.5')
plt.legend()
plt.tight_layout()
plt.savefig('bsc_mutual_info.png', dpi=150)
plt.show()

5.3 信道容量

5.3.1 定义

定义:离散无记忆信道的容量定义为:

$$C = \max_{p(x)} I(X;Y)$$

即对所有可能的输入分布 $p(x)$,互信息的最大值。

单位:比特/信道使用(bits per channel use)

物理意义:信道容量是信道能够可靠传输的最大信息速率。如果传输速率 $R < C$,存在编码方案使得错误概率任意小;如果 $R > C$,任何编码方案的错误概率都有正的下界。

5.3.2 BSC信道容量

对于BSC($p$),由于对称性,最优输入分布是均匀的($q=0.5$)。

$$\begin{align*}

C &= \max_q I(X;Y) \\

&= I(X;Y)|_{q=0.5} \\

&= H_b(0.5) - H_b(p) \\

&= 1 - H_b(p)

\end{align*}$$

分析:

  • 当 $p=0$(无噪声):$C = 1 - 0 = 1$ bit/use
  • 当 $p=0.5$(完全噪声):$C = 1 - 1 = 0$ bits/use
  • 当 $p=0.1$:$C = 1 - H_b(0.1) \approx 1 - 0.469 = 0.531$ bits/use

代码示例5-3:BSC容量曲线

python
import numpy as np
import matplotlib.pyplot as plt

def bsc_capacity(p):
    """BSC信道容量"""
    return 1 - binary_entropy(p)

# 计算不同p值下的容量
p_values = np.linspace(0, 0.5, 100)
capacity_values = [bsc_capacity(p) for p in p_values]

plt.figure(figsize=(10, 6))
plt.plot(p_values, capacity_values, 'b-', linewidth=2.5)
plt.xlabel('交叉概率 p', fontsize=12)
plt.ylabel('容量 C (bits/use)', fontsize=12)
plt.title('二元对称信道容量', fontsize=14)
plt.grid(True, alpha=0.3)
plt.axhline(y=0, color='k', linestyle='-', linewidth=0.5)
plt.axvline(x=0.5, color='r', linestyle='--', alpha=0.5, label='p=0.5 (C=0)')
plt.legend()
plt.tight_layout()
plt.savefig('bsc_capacity.png', dpi=150)
plt.show()

# 打印一些关键点
print("BSC信道容量")
print("=" * 40)
for p in [0, 0.01, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5]:
    print(f"p={p:.2f}: C={bsc_capacity(p):.4f} bits/use")

输出:

BSC信道容量
========================================
p=0.00: C=1.0000 bits/use
p=0.01: C=0.9192 bits/use
p=0.05: C=0.7219 bits/use
p=0.10: C=0.5310 bits/use
p=0.20: C=0.2781 bits/use
p=0.30: C=0.1187 bits/use
p=0.40: C=0.0290 bits/use
p=0.50: C=0.0000 bits/use

5.3.3 BEC信道容量

对于BEC($\epsilon$),最优输入分布也是均匀的。

$$\begin{align*}

H(Y|X) &= \epsilon H_b(1) + (1-\epsilon) \cdot 0 = 0 \quad (\text{因为擦除时Y确定})\\

\text{实际上: } H(Y|X) &= \epsilon \cdot 0 + (1-\epsilon) \cdot 0 = 0 \quad (\text{错误!})

\end{align*}$$

让我重新计算:

$$H(Y|X) = \sum_x p(x) H(Y|X=x)$$

当 $X=0$ 时,$Y \in \{0, e\}$,分布为 $(1-\epsilon, \epsilon)$,熵为 $H_b(\epsilon)$。

当 $X=1$ 时,同样。

所以 $H(Y|X) = H_b(\epsilon)$。

输出分布(均匀输入):

$$P(Y=0) = P(Y=1) = \frac{1-\epsilon}{2}, \quad P(Y=e) = \epsilon$$

$$H(Y) = -2 \cdot \frac{1-\epsilon}{2} \log_2 \frac{1-\epsilon}{2} - \epsilon \log_2 \epsilon$$

$$= (1-\epsilon) \log_2 \frac{2}{1-\epsilon} - \epsilon \log_2 \epsilon$$

$$= (1-\epsilon) + H_b(\epsilon)$$

因此:

$$I(X;Y) = H(Y) - H(Y|X) = (1-\epsilon) + H_b(\epsilon) - H_b(\epsilon) = 1 - \epsilon$$

BEC容量:$C = 1 - \epsilon$ bits/use

对比BSC和BEC:

  • BSC($p=0.1$):$C \approx 0.531$ bits/use
  • BEC($\epsilon=0.1$):$C = 0.9$ bits/use

BEC的容量更高,因为接收端知道哪些比特被擦除了,可以利用这些信息。

5.3.4 一般DMC容量的计算

对于一般信道,容量计算是一个凸优化问题:

$$C = \max_{p(x)} I(X;Y) = \max_{p(x)} \sum_{x,y} p(x) p(y|x) \log_2 \frac{p(y|x)}{\sum_{x'} p(x') p(y|x')}$$

Blahut-Arimoto算法:一种迭代算法,用于数值计算信道容量。

算法步骤:

初始化输入分布 $p^{(0)}(x)$(如均匀分布)

迭代更新:

$$q^{(t)}(y|x) = \frac{p(y|x)^{s}}{\sum_{x'} p(y|x')^{s} p^{(t)}(x')}$$

$$p^{(t+1)}(x) \propto p^{(t)}(x) \exp\left(\sum_y p(y|x) \log \frac{p(y|x)}{\sum_{x'} p^{(t)}(x') p(y|x')}\right)$$

收敛时,$I(X;Y)$ 即为容量

代码示例5-4:Blahut-Arimoto算法实现

python
import numpy as np

def blahut_arimoto(transfer_matrix, max_iter=1000, tol=1e-8):
    """
    Blahut-Arimoto算法计算信道容量
    
    参数:
        transfer_matrix: 转移概率矩阵 P(y|x)
        max_iter: 最大迭代次数
        tol: 收敛容差
    
    返回:
        容量 (bits), 最优输入分布
    """
    n_in, n_out = transfer_matrix.shape
    
    # 初始化均匀分布
    px = np.ones(n_in) / n_in
    
    for iteration in range(max_iter):
        # 计算输出分布
        py = transfer_matrix.T @ px
        
        # 避免log(0)
        py = np.maximum(py, 1e-30)
        
        # 计算互信息的梯度
        # I(X;Y) = sum_x p(x) sum_y p(y|x) log(p(y|x) / p(y))
        mutual_info = 0
        for i in range(n_in):
            for j in range(n_out):
                if transfer_matrix[i, j] > 0:
                    mutual_info += px[i] * transfer_matrix[i, j] * \
                                   np.log2(transfer_matrix[i, j] / py[j])
        
        # 更新输入分布
        new_px = np.zeros(n_in)
        for i in range(n_in):
            for j in range(n_out):
                if transfer_matrix[i, j] > 0 and py[j] > 0:
                    new_px[i] += transfer_matrix[i, j] * np.log2(transfer_matrix[i, j] / py[j])
        
        # 指数并归一化
        new_px = np.exp2(new_px)
        new_px = new_px / new_px.sum()
        
        # 检查收敛
        if np.max(np.abs(new_px - px)) < tol:
            px = new_px
            break
        
        px = new_px
    
    # 最终计算容量
    py = transfer_matrix.T @ px
    capacity = 0
    for i in range(n_in):
        for j in range(n_out):
            if transfer_matrix[i, j] > 0 and py[j] > 0:
                capacity += px[i] * transfer_matrix[i, j] * \
                            np.log2(transfer_matrix[i, j] / py[j])
    
    return capacity, px

# 测试:BSC信道
p = 0.1
bsc_matrix = np.array([[1-p, p], [p, 1-p]])
capacity, opt_px = blahut_arimoto(bsc_matrix)

print("Blahut-Arimoto算法测试")
print("=" * 50)
print(f"BSC(p={p}) 信道:")
print(f"  计算容量: {capacity:.6f} bits/use")
print(f"  理论容量: {1 - binary_entropy(p):.6f} bits/use")
print(f"  最优输入分布: {opt_px}")
print()

# 测试:Z信道
z_channel = np.array([[1, 0], [0.5, 0.5]])
capacity, opt_px = blahut_arimoto(z_channel)

print("Z信道:")
print(f"  容量: {capacity:.6f} bits/use")
print(f"  最优输入分布: {opt_px}")

5.4 连续信道与高斯信道

5.4.1 微分熵回顾

对于连续随机变量 $X$ 具有概率密度函数 $f(x)$,微分熵定义为:

$$h(X) = -\int f(x) \log_2 f(x) dx$$

注意:微分熵可以是负的,且不等于离散熵的极限。

高斯分布的微分熵:

如果 $X \sim \mathcal{N}(\mu, \sigma^2)$,则:

$$h(X) = \frac{1}{2} \log_2(2\pi e \sigma^2)$$

5.4.2 AWGN信道

加性白高斯噪声(AWGN)信道模型:

$$Y = X + Z$$

其中 $Z \sim \mathcal{N}(0, N_0/2)$ 是高斯噪声,$X$ 受功率约束 $\mathbb{E}[X^2] \leq P$。

互信息:

$$I(X;Y) = h(Y) - h(Y|X) = h(Y) - h(Z)$$

由于 $Y = X + Z$,且 $Z$ 是高斯的,当 $X$ 也是高斯分布时,$Y$ 的熵最大。

最优输入分布:$X \sim \mathcal{N}(0, P)$

此时 $Y \sim \mathcal{N}(0, P + N_0/2)$。

$$\begin{align*}

h(Y) &= \frac{1}{2} \log_2(2\pi e (P + N_0/2)) \\

h(Z) &= \frac{1}{2} \log_2(2\pi e N_0/2) \\

I(X;Y) &= \frac{1}{2} \log_2\left(1 + \frac{P}{N_0/2}\right)

\end{align*}$$

通常定义信噪比 $SNR = P/N$,其中 $N$ 是噪声功率。

单符号AWGN信道容量:

$$C = \frac{1}{2} \log_2(1 + SNR) \text{ bits/use}$$

5.4.3 带限高斯信道与香农公式

对于带宽为 $B$ Hz的带限信道,根据奈奎斯特采样定理,每秒可以有 $2B$ 个独立样本。

如果信号功率为 $P$,噪声功率谱密度为 $N_0$ W/Hz,则噪声功率为 $N = N_0 B$。

香农公式:

$$C = B \log_2\left(1 + \frac{P}{N_0 B}\right) \text{ bits/second}$$

分析:

  • 功率受限区域(低SNR):$C \approx \frac{P}{N_0} \log_2 e$,容量与功率成正比
  • 带宽受限区域(高SNR):$C \approx B \log_2(SNR)$,容量与带宽成正比
  • 无限带宽极限:当 $B \to \infty$,$C \to \frac{P}{N_0} \log_2 e \approx 1.44 \frac{P}{N_0}$

代码示例5-5:香农公式可视化

python
import numpy as np
import matplotlib.pyplot as plt

def shannon_capacity_bandwidth(B, P, N0):
    """
    香农公式:容量 vs 带宽
    
    参数:
        B: 带宽 (Hz)
        P: 信号功率 (W)
        N0: 噪声功率谱密度 (W/Hz)
    
    返回:
        容量 (bits/s)
    """
    return B * np.log2(1 + P / (N0 * B))

def shannon_capacity_snr(SNR_dB):
    """
    归一化容量 (B=1Hz)
    
    参数:
        SNR_dB: 信噪比 (dB)
    
    返回:
        容量 (bits/s/Hz)
    """
    SNR = 10**(SNR_dB / 10)
    return np.log2(1 + SNR)

# 图1:容量 vs 带宽
P = 1  # 1W
N0 = 1e-9  # 噪声谱密度

B_values = np.logspace(1, 9, 100)  # 10Hz 到 1GHz
C_values = [shannon_capacity_bandwidth(B, P, N0) for B in B_values]

plt.figure(figsize=(10, 6))
plt.loglog(B_values, C_values, 'b-', linewidth=2.5)
plt.xlabel('带宽 B (Hz)', fontsize=12)
plt.ylabel('容量 C (bits/s)', fontsize=12)
plt.title(f'香农公式: 容量 vs 带宽 (P={P}W, N₀={N0}W/Hz)', fontsize=14)
plt.grid(True, alpha=0.3, which='both')

# 标注渐近线
C_inf = P / N0 * np.log2(np.e)
plt.axhline(y=C_inf, color='r', linestyle='--', alpha=0.5, 
            label=f'无限带宽极限: {C_inf/1e9:.2f} Gbits/s')
plt.legend()
plt.tight_layout()
plt.savefig('shannon_capacity_bandwidth.png', dpi=150)
plt.show()

# 图2:容量 vs SNR
SNR_dB_values = np.linspace(-20, 30, 100)
C_norm_values = [shannon_capacity_snr(snr) for snr in SNR_dB_values]

plt.figure(figsize=(10, 6))
plt.plot(SNR_dB_values, C_norm_values, 'b-', linewidth=2.5)
plt.xlabel('SNR (dB)', fontsize=12)
plt.ylabel('归一化容量 (bits/s/Hz)', fontsize=12)
plt.title('香农公式: 归一化容量 vs SNR', fontsize=14)
plt.grid(True, alpha=0.3)
plt.axhline(y=1, color='r', linestyle='--', alpha=0.5, label='1 bit/s/Hz')
plt.legend()
plt.tight_layout()
plt.savefig('shannon_capacity_snr.png', dpi=150)
plt.show()

print("香农公式分析")
print("=" * 60)
print(f"无限带宽极限容量: {C_inf/1e9:.2f} Gbits/s")
print()
print("不同SNR下的归一化容量:")
for snr_db in [-10, 0, 10, 20, 30]:
    c = shannon_capacity_snr(snr_db)
    print(f"  SNR={snr_db:3d}dB: {c:.4f} bits/s/Hz")

5.5 并行高斯信道与水填充

5.5.1 问题设定

考虑 $n$ 个并行的独立高斯信道,第 $i$ 个信道的噪声方差为 $N_i$。总功率约束为 $\sum_{i=1}^n P_i \leq P$。

总容量为各信道容量之和:

$$C = \sum_{i=1}^n \frac{1}{2} \log_2\left(1 + \frac{P_i}{N_i}\right)$$

优化问题:在 $\sum P_i \leq P$ 约束下最大化 $C$。

5.5.2 水填充解

使用拉格朗日乘子法,最优功率分配满足:

$$\frac{1}{2} \cdot \frac{1}{\ln 2} \cdot \frac{1}{P_i + N_i} = \lambda$$

即:

$$P_i + N_i = \text{常数}$$

但由于 $P_i \geq 0$,实际解为:

$$P_i = \max(0, \mu - N_i)$$

其中 $\mu$ 由总功率约束确定。

直观解释:想象噪声水平 $N_i$ 是地面高度,总功率是水。水会先填满低洼处,直到水位达到 $\mu$。这就是"水填充"名称的由来。

代码示例5-6:水填充算法

python
import numpy as np
import matplotlib.pyplot as plt

def water_filling(noise_levels, total_power):
    """
    水填充算法
    
    参数:
        noise_levels: 各信道的噪声水平列表
        total_power: 总功率约束
    
    返回:
        功率分配列表,水位
    """
    n = len(noise_levels)
    noise = np.array(noise_levels)
    
    # 排序噪声水平
    sorted_indices = np.argsort(noise)
    sorted_noise = noise[sorted_indices]
    
    # 逐步增加水位
    water_level = 0
    remaining_power = total_power
    
    for i in range(n):
        if i < n - 1:
            # 计算填满当前层所需的功率
            delta_h = sorted_noise[i+1] - sorted_noise[i]
            power_needed = delta_h * (i + 1)
            
            if power_needed <= remaining_power:
                remaining_power -= power_needed
                water_level = sorted_noise[i+1]
            else:
                break
        else:
            # 最后一层
            water_level = sorted_noise[i] + remaining_power / (i + 1)
            remaining_power = 0
    
    # 计算功率分配
    power_alloc = np.zeros(n)
    for i in range(n):
        power_alloc[i] = max(0, water_level - noise[i])
    
    return power_alloc, water_level

# 示例
noise_levels = [1, 2, 3, 4, 5]
total_power = 10

power_alloc, water_level = water_filling(noise_levels, total_power)

print("水填充算法")
print("=" * 60)
print(f"噪声水平: {noise_levels}")
print(f"总功率: {total_power}")
print(f"水位: {water_level:.4f}")
print(f"功率分配: {power_alloc.round(4)}")
print(f"总分配功率: {power_alloc.sum():.4f}")

# 计算总容量
capacity = sum(0.5 * np.log2(1 + p/n) for p, n in zip(power_alloc, noise_levels) if p > 0)
print(f"总容量: {capacity:.4f} bits/use")

# 可视化
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))

# 图1:水填充示意
channels = np.arange(len(noise_levels))
ax1.bar(channels, noise_levels, color='brown', alpha=0.5, label='噪声水平')
ax1.bar(channels, power_alloc, bottom=noise_levels, color='blue', alpha=0.7, label='功率分配')
ax1.axhline(y=water_level, color='r', linestyle='--', linewidth=2, label=f'水位={water_level:.2f}')
ax1.set_xlabel('信道索引', fontsize=12)
ax1.set_ylabel('功率/噪声', fontsize=12)
ax1.set_title('水填充功率分配', fontsize=14)
ax1.legend()
ax1.grid(True, alpha=0.3)

# 图2:容量 vs 总功率
power_values = np.linspace(1, 20, 50)
capacities = []
for P in power_values:
    pa, _ = water_filling(noise_levels, P)
    cap = sum(0.5 * np.log2(1 + p/n) for p, n in zip(pa, noise_levels) if p > 0)
    capacities.append(cap)

ax2.plot(power_values, capacities, 'b-', linewidth=2.5)
ax2.set_xlabel('总功率', fontsize=12)
ax2.set_ylabel('总容量 (bits/use)', fontsize=12)
ax2.set_title('容量 vs 总功率', fontsize=14)
ax2.grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('water_filling.png', dpi=150)
plt.show()

5.6 信道编码定理

5.6.1 定理陈述

定理(香农信道编码定理):对于离散无记忆信道,容量为 $C$。

正面(Achievability):对于任意 $R < C$ 和 $\epsilon > 0$,存在码长为 $n$、速率为 $R$ 的编码方案,使得错误概率 $P_e < \epsilon$(当 $n$ 足够大时)。

反面(Converse):对于任何码长为 $n$、速率为 $R > C$ 的编码方案,错误概率有正的下界(不能任意小)。

直观理解:

  • 容量是可靠通信的绝对极限
  • 低于容量,可以通过复杂编码实现任意小的错误
  • 高于容量,无论如何编码都会有显著错误

5.6.2 证明思路(正面)

随机码本构造:

生成 $2^{nR}$ 个长度为 $n$ 的随机序列,每个符号独立服从最优输入分布 $p^*(x)$

这些序列作为码字,对应不同的消息

编码:要发送消息 $m$,发送对应的码字 $x^n(m)$。

译码(联合典型性译码):

收到 $y^n$

寻找唯一的 $m$,使得 $(x^n(m), y^n)$ 是联合典型的

如果找到,输出 $m$;否则报错

错误分析:

  • 错误事件1:正确码字与接收序列不联合典型。由AEP,概率趋于0。
  • 错误事件2:某个错误码字与接收序列联合典型。对于每个错误消息,概率约 $2^{-nI(X;Y)}$。共有 $2^{nR}-1$ 个错误消息,由union bound,总错误概率 $\leq 2^{nR} \cdot 2^{-nI(X;Y)} = 2^{-n(I(X;Y)-R)}$。

当 $R < I(X;Y) \leq C$ 时,错误概率指数级趋于0。

5.6.3 实际意义

虽然随机码本在实际中不可行(存储和搜索复杂度太高),但这个证明表明:好的编码方案存在。后续的研究致力于找到接近容量的实用编码方案,如Turbo码、LDPC码、Polar码等。


三、程序员的视角

5.1 在实际通信系统中的应用

调制方案选择:

  • BPSK:1 bit/symbol,适用于低SNR
  • QPSK:2 bits/symbol
  • 16-QAM:4 bits/symbol
  • 64-QAM:6 bits/symbol
  • ...

高阶调制可以在相同带宽下传输更多数据,但需要更高的SNR。

自适应调制编码(AMC):

根据信道条件动态调整调制阶数和编码率,以接近信道容量。

MIMO系统:

多输入多输出系统利用空间维度增加容量。对于 $N_t$ 发射天线和 $N_r$ 接收天线,容量可以线性增长。

5.2 常见陷阱

混淆比特率和符号率:符号率受带宽限制,比特率还取决于调制阶数。

忽略实现损耗:实际系统与香农极限有几dB的差距。

假设理想信道:实际信道有衰落、干扰、非线性等效应。

功率与带宽的权衡:在某些场景下,增加带宽比增加功率更有效。

5.3 与其他层级的联系

  • 与物理层:调制、编码、均衡等技术直接影响有效SNR
  • 与链路层:ARQ、HARQ等重传机制处理残余错误
  • 与网络层:路由和调度需要考虑链路容量

四、代码实战

5.1 完整的信道容量计算器

python
import numpy as np
from scipy.optimize import minimize_scalar

class ChannelCapacityCalculator:
    """信道容量计算器"""
    
    @staticmethod
    def bsc_capacity(p):
        """BSC信道容量"""
        return 1 - (-p*np.log2(p+1e-30) - (1-p)*np.log2(1-p+1e-30))
    
    @staticmethod
    def bec_capacity(epsilon):
        """BEC信道容量"""
        return 1 - epsilon
    
    @staticmethod
    def awgn_capacity(SNR):
        """AWGN信道容量(归一化)"""
        return 0.5 * np.log2(1 + SNR)
    
    @staticmethod
    def shannon_formula(B, P, N0):
        """香农公式"""
        return B * np.log2(1 + P / (N0 * B))
    
    @staticmethod
    def dmc_capacity_blahut_arimoto(transfer_matrix, max_iter=1000):
        """DMC信道容量(Blahut-Arimoto算法)"""
        n_in, n_out = transfer_matrix.shape
        px = np.ones(n_in) / n_in
        
        for _ in range(max_iter):
            py = transfer_matrix.T @ px
            py = np.maximum(py, 1e-30)
            
            new_px = np.zeros(n_in)
            for i in range(n_in):
                for j in range(n_out):
                    if transfer_matrix[i, j] > 0 and py[j] > 0:
                        new_px[i] += transfer_matrix[i, j] * np.log2(transfer_matrix[i, j] / py[j])
            
            new_px = np.exp2(new_px)
            new_px /= new_px.sum()
            
            if np.max(np.abs(new_px - px)) < 1e-8:
                px = new_px
                break
            px = new_px
        
        py = transfer_matrix.T @ px
        capacity = 0
        for i in range(n_in):
            for j in range(n_out):
                if transfer_matrix[i, j] > 0 and py[j] > 0:
                    capacity += px[i] * transfer_matrix[i, j] * np.log2(transfer_matrix[i, j] / py[j])
        
        return capacity, px


# 使用示例
if __name__ == "__main__":
    calc = ChannelCapacityCalculator()
    
    print("信道容量计算器")
    print("=" * 60)
    
    # BSC
    p = 0.1
    print(f"BSC(p={p}): C = {calc.bsc_capacity(p):.4f} bits/use")
    
    # BEC
    eps = 0.2
    print(f"BEC(ε={eps}): C = {calc.bec_capacity(eps):.4f} bits/use")
    
    # AWGN
    SNR = 10  # 线性值
    print(f"AWGN(SNR={SNR}={10*np.log10(SNR):.1f}dB): C = {calc.awgn_capacity(SNR):.4f} bits/use")
    
    # 香农公式
    B = 1e6  # 1MHz
    P = 1  # 1W
    N0 = 1e-9  # W/Hz
    print(f"香农公式(B={B/1e6:.0f}MHz, P={P}W): C = {calc.shannon_formula(B, P, N0)/1e6:.2f} Mbits/s")
    
    # 一般DMC
    z_channel = np.array([[1, 0], [0.5, 0.5]])
    cap, px = calc.dmc_capacity_blahut_arimoto(z_channel)
    print(f"Z信道: C = {cap:.4f} bits/use, 最优输入: {px.round(4)}")

5.2 蒙特卡洛仿真验证信道编码定理

python
import numpy as np

def simulate_bsc_communication(n_bits, p, code_rate, n_trials=1000):
    """
    模拟BSC信道上的通信
    
    参数:
        n_bits: 每块比特数
        p: BSC交叉概率
        code_rate: 编码率 (k/n)
        n_trials: 试验次数
    
    返回:
        错误率估计
    """
    errors = 0
    
    for _ in range(n_trials):
        # 生成随机消息
        message = np.random.randint(0, 2, int(n_bits * code_rate))
        
        # 简单重复码(用于演示)
        # 每个比特重复 1/code_rate 次
        repeat_factor = int(1 / code_rate)
        codeword = np.repeat(message, repeat_factor)
        
        # 通过BSC
        noise = np.random.rand(len(codeword)) < p
        received = codeword ^ noise
        
        # 多数表决译码
        decoded = np.zeros_like(message)
        for i in range(len(message)):
            block = received[i*repeat_factor:(i+1)*repeat_factor]
            decoded[i] = np.round(np.mean(block))
        
        # 检查错误
        if not np.array_equal(message, decoded):
            errors += 1
    
    return errors / n_trials

# 测试
p = 0.1
C = 1 - (-p*np.log2(p) - (1-p)*np.log2(1-p))

print("BSC信道通信仿真")
print("=" * 60)
print(f"BSC(p={p}), 容量 C = {C:.4f} bits/use")
print()

for rate in [0.3, 0.5, 0.7, 0.9]:
    error_rate = simulate_bsc_communication(100, p, rate, n_trials=500)
    status = "✓ 可靠" if rate < C else "✗ 不可靠"
    print(f"速率 R={rate}: 错误率 = {error_rate:.4f} {status}")

五、深入思考

5.1 历史背景

香农在1948年的论文中首次提出了信道容量的概念,并证明了信道编码定理。这个结果在当时是革命性的,因为它表明通过适当的编码,可以在有噪声的信道上实现几乎无错误的通信。

早期的研究者认为这是一个理论结果,实际中无法实现。但随着Turbo码(1993)、LDPC码(重新发现于1990年代末)和Polar码(2009)的发明,人们已经能够非常接近香农极限。

5.2 前沿方向

大规模MIMO:利用大量天线实现空间复用,显著提高频谱效率。

毫米波通信:利用高频段的大带宽,但面临传播损耗挑战。

智能反射面:通过可编程表面控制无线环境,改善信道条件。

语义通信:超越比特级的可靠传输,关注信息的语义保真度。

5.3 延伸阅读

Cover & Thomas《信息论基础》第9章

Tse & Viswanath《Fundamentals of Wireless Communication》

Richardson & Urbanke《Modern Coding Theory》


六、实验笔记

实验1:不同信道的容量比较

目标:比较BSC、BEC和Z信道在相同"噪声水平"下的容量差异。

步骤:

设置BSC的 $p=0.1$,BEC的 $\epsilon=0.1$,Z信道的相应参数

计算各信道的容量

分析为什么BEC容量高于BSC

绘制容量随噪声参数变化的曲线

预期结果:BEC > BSC,因为擦除比翻转更容易处理。

实验2:水填充算法验证

目标:验证水填充算法的最优性。

步骤:

设置5个并行高斯信道,噪声水平不同

使用水填充算法分配功率

尝试其他功率分配方案(如均匀分配)

比较总容量

思考题:

  • 水填充在什么情况下退化为均匀分配?
  • 如果某些信道噪声极大,会发生什么?

七、本章小结

本章介绍了信道容量的概念和计算方法。

信道模型:离散无记忆信道(DMC)是最基本的模型,用转移概率矩阵描述。二元对称信道(BSC)和二元擦除信道(BEC)是两个重要的特例。

互信息:$I(X;Y)$ 度量了通过信道传输的信息量。它是输入分布的凹函数,这保证了容量计算中的最大值存在。

信道容量:$C = \max_{p(x)} I(X;Y)$ 是可靠通信的极限。BSC的容量为 $1-H_b(p)$,BEC的容量为 $1-\epsilon$。

高斯信道:AWGN信道的容量由香农公式给出:$C = B \log_2(1+SNR)$。这个公式是现代通信系统设计的基石。

水填充:在并行高斯信道中,最优功率分配遵循水填充原则,将更多功率分配给噪声较低的信道。

信道编码定理:只要传输速率小于容量,就存在编码方案实现任意小的错误概率。随机码本论证证明了这一点,虽然实际中需要使用结构化编码。

从程序员的角度看,理解信道容量有助于设计高效的通信协议、选择合适的调制编码方案,以及评估系统性能的理论上界。


八、习题

习题5.1(BSC容量):计算BSC($p=0.05$)的容量。如果要求传输速率为0.8 bits/use,是否可行?

习题5.2(BEC容量):BEC的擦除概率为多少时,容量等于BSC($p=0.1$)的容量?

习题5.3(Z信道):Z信道的转移矩阵为 $\begin{pmatrix} 1 & 0 \\ 0.5 & 0.5 \end{pmatrix}$。计算其容量和最优输入分布。

习题5.4(香农公式):一个无线信道的带宽为20MHz,信噪比为20dB。计算信道容量。如果带宽加倍,容量变为多少?

习题5.5(水填充):三个并行高斯信道的噪声方差分别为 $N_1=1, N_2=2, N_3=4$。总功率约束为 $P=6$。使用水填充算法计算最优功率分配和总容量。

习题5.6(编程题):实现Blahut-Arimoto算法,计算任意DMC信道的容量。测试你的实现在不同信道上的表现。

习题5.7(挑战题):证明对于对称信道(每行是其他行的排列,每列也是),最优输入分布是均匀分布。

习题5.8(应用题):设计一个5G基站的下行链路,带宽100MHz,覆盖半径500米。假设路径损耗模型和终端接收功率,估算小区边缘用户的最大可达速率。

习题5.9(分析题):比较有反馈和无反馈的BSC信道容量。反馈是否能增加容量?为什么?

习题5.10(开放性问题):研究大规模MIMO系统的容量特性,撰写一篇500字左右的分析报告,讨论天线数量、信道状态信息精度对容量的影响。

5/9信道容量
0%