CSMA(aloha)

论文主要思路

论文地址:Toward a Coherent Theory of CSMA and Aloha

一、核心仿真模型与假设

论文的仿真模型是构建其理论分析的基础,其核心是一个离散时间的、基于时隙和微时隙的CSMA网络仿真系统

  1. 网络拓扑与节点

    • 仿真一个包含 n 个节点的网络。
    • 所有节点是同构的,具有相同的参数和行为。
  2. 时间结构

    • 时间轴被划分为时隙,每个时隙的长度等于一个完整数据包的传输时间。
    • 每个时隙进一步划分为多个微时隙 ,长度为 a(a ≪ 1)。
    • 节点只能在微时隙的边界开始传输。
  3. 流量模型

    • 每个节点都有一个无限大小的缓冲区
    • 数据包以 伯努利过程 到达每个节点,到达率为 λ
    • 总输入流量: λ ^ = n λ \hat{\lambda} = n\lambda λ^=nλ。
  4. 队列服务规则

    • 先进先出
    • 只有队首包 有资格参与信道竞争。
  5. 信道访问机制(CSMA核心)

    • 载波侦听:节点在传输前必须侦听信道。
    • p-坚持CSMA :当信道空闲时,HOL包以概率 q i q_i qi 传输,其中 i i i 是碰撞次数。
    • 截止相位 K :最大重传次数为 K K K。
    • 传输概率序列 : { q i } i = 0 , . . . , K \{q_i\}_{i=0,...,K} {qi}i=0,...,K 是单调递减序列。
  6. 碰撞检测机制

    • 碰撞检测时间 x :发生碰撞后,节点需要 x x x 个微时隙来检测碰撞并中止传输。
    • x = 0 x = 0 x=0:立即检测(有线网络)
    • x = 1 / a x = 1/a x=1/a:整个时隙后才检测(无线半双工)
  7. 关键系统参数

    • 微时隙长度 a:传播延迟与包传输时间的比值
    • 碰撞检测时间 x:碰撞检测所需的微时隙数
    • 初始传输概率 q 0 q_0 q0
    • 截止相位 K
    • 节点数 n

二、主要仿真指标

论文中明确或隐含地追踪了以下关键性能指标:

  1. 瞬态成功概率 ( p t ) ( p_t ) (pt)

    • 定义 :给定信道在 t − 1 t-1 t−1 时刻空闲的条件下,在 t t t 时刻传输成功的概率。
    • 计算方式:通过统计成功传输次数与尝试次数的比例获得。
    • 目的 :观察系统动态,验证双稳态特性 (收敛到 p L p_L pL 或 p A p_A pA)。
  2. 网络吞吐量 ( λ ^ o u t ) ( \hat{\lambda}_{out} ) (λ^out)

    • 定义:长期平均的成功传输速率。
    • 计算方式 : λ ^ o u t = 总成功传输包数 总仿真时间 \hat{\lambda}_{out} = \frac{\text{总成功传输包数}}{\text{总仿真时间}} λ^out=总仿真时间总成功传输包数
    • 目的 :验证稳定性( λ ^ o u t = λ ^ \hat{\lambda}_{out} = \hat{\lambda} λ^out=λ^)和最大吞吐量理论。
  3. 访问延迟

    • 定义:包从成为HOL到成功传输的时隙数。
    • 观测统计量
      • 一阶矩 ( E [ D 0 ] ) ( E[D_0] ) (E[D0]):平均访问延迟
      • 二阶矩 ( E [ D 0 2 ] ) ( E[D_0^2] ) (E[D02]):延迟方差
    • 目的:评估不同参数配置下的延迟性能。
  4. 稳定区域验证

    • 绝对稳定区域 S L S_L SL :保证收敛到期望稳定点 p L p_L pL 的 q 0 q_0 q0 范围
    • 准稳定区域 S A S_A SA :在非期望稳定点 p A p_A pA 仍能保持稳定的 q 0 q_0 q0 范围

三、仿真运行逻辑与参数扫描

论文的仿真进行了系统的参数扫描以验证理论:

  1. 验证双稳态特性

    • 固定 n n n, λ ^ \hat{\lambda} λ^, a a a, x x x, K K K
    • 选择不同的 q 0 q_0 q0(在稳定区域内和外部)
    • 观察 p t p_t pt 的收敛行为(对应图9
  2. 绘制稳定区域

    • 固定 n n n, λ ^ \hat{\lambda} λ^, a a a, x x x, K K K
    • 扫描 q 0 q_0 q0,测量稳态吞吐量
    • 标识满足 λ ^ o u t = λ ^ \hat{\lambda}_{out} = \hat{\lambda} λ^out=λ^ 的 q 0 q_0 q0 范围(对应图10, 12a
  3. 分析吞吐量性能

    • 变化 λ ^ \hat{\lambda} λ^,测量最大吞吐量 λ ^ max ⁡ \hat{\lambda}_{\max} λ^max
    • 研究 a a a 和 x x x 对最大吞吐量的影响(对应图4, 11
  4. 延迟性能分析

    • 在稳定区域内扫描 q 0 q_0 q0,测量 E [ D 0 ] E[D_0] E[D0] 和 E [ D 0 2 ] E[D_0^2] E[D02]
    • 找到最优 q 0 q_0 q0 以最小化延迟(对应图8, 12b
  5. 参数敏感性分析

    • 微时隙长度 a :展示 a a a 减小带来的性能增益
    • 碰撞检测时间 x :比较 x = 0 x=0 x=0 与 x = 1 / a x=1/a x=1/a 的性能差异
    • 与Aloha对比:在相同参数下比较CSMA与Aloha的性能

思考与扩展

本文构建了一个统一的CSMA理论框架,揭示了:

  1. CSMA与Aloha共享相同的双稳态特性
  2. CSMA的性能优势主要来自微时隙机制快速碰撞检测
  3. a a a 和 x x x 是决定CSMA性能上限的关键参数
  4. 退避参数的稳定区域随节点数增加而急剧缩小

对于仿真实现,建议:

  1. 先实现基础的p-坚持CSMA( K = 0 K=0 K=0)
  2. 重点验证 a a a 和 x x x 对性能的影响
  3. 通过 p t p_t pt 的轨迹观察直接验证双稳态现象
  4. 与Aloha进行对比实验,验证CSMA在 a a a 较小时的性能优势

核心的理论公式,这些公式在仿真中需要被验证:

📊 吞吐量相关公式

1. 基于泊松假设的吞吐量(公式8)

λ ^ o u t = G e − a G x + 1 − x e − a G + ( 1 / a − x ) a G e − a G \hat{\lambda}_{out} = \frac{Ge^{-aG}}{x+1-xe^{-aG}+(1/a-x)aGe^{-aG}} λ^out=x+1−xe−aG+(1/a−x)aGe−aGGe−aG

2. 最大吞吐量(公式9)

λ ^ max ⁡ = − W 0 ( − 1 e ( 1 + 1 / x ) ) x a − ( 1 − x a ) W 0 ( − 1 e ( 1 + 1 / x ) ) \hat{\lambda}{\max} = \frac{-\mathbb{W}{0}\left(-\frac{1}{e(1+1/x)}\right)}{xa-(1-xa)\mathbb{W}_{0}\left(-\frac{1}{e(1+1/x)}\right)} λ^max=xa−(1−xa)W0(−e(1+1/x)1)−W0(−e(1+1/x)1)

3. 特殊情况下的吞吐量

  • x=0时(公式10-11)

    λ ^ o u t x = 0 = G e − a G 1 + G e − a G , λ ^ max ⁡ x = 0 = 1 1 + a e \hat{\lambda}{out}^{x=0} = \frac{Ge^{-aG}}{1+Ge^{-aG}}, \quad \hat{\lambda}{\max}^{x=0} = \frac{1}{1+ae} λ^outx=0=1+Ge−aGGe−aG,λ^maxx=0=1+ae1

  • x=1/a时(公式12-13)

λ ^ o u t x = 1 / a = a G e − a G 1 + a − e − a G , λ ^ max ⁡ x = 1 / a = − W 0 ( − 1 e ( 1 + a ) ) \hat{\lambda}{out}^{x=1/a} = \frac{aGe^{-aG}}{1+a-e^{-aG}}, \quad \hat{\lambda}{\max}^{x=1/a} = -\mathbb{W}_{0}\left(\frac{-1}{e(1+a)}\right) λ^outx=1/a=1+a−e−aGaGe−aG,λ^maxx=1/a=−W0(e(1+a)−1)

🔄 双稳态点公式

4. 固定点方程(公式33)

p = exp ⁡ { x a λ ^ 1 − ( 1 − x a ) λ ^ } ⋅ exp ⁡ { − ( x + 1 ) a λ ^ 1 − ( 1 − x a ) λ ^ ⋅ 1 p } p = \exp\left\{ \frac{xa\hat{\lambda}}{1-(1-xa)\hat{\lambda}} \right\} \cdot \exp\left\{ -\frac{(x+1)a\hat{\lambda}}{1-(1-xa)\hat{\lambda}} \cdot \frac{1}{p} \right\} p=exp{1−(1−xa)λ^xaλ^}⋅exp{−1−(1−xa)λ^(x+1)aλ^⋅p1}

5. 双稳态点解(公式34-35)

p L = exp ⁡ { W 0 ( − ( x + 1 ) a λ ^ 1 − ( 1 − x a ) λ ^ ⋅ exp ⁡ { − x a λ ^ 1 − ( 1 − x a ) λ ^ } ) + x a λ ^ 1 − ( 1 − x a ) λ ^ } p_L = \exp\left\{ \mathbb{W}_0 \left( -\frac{(x+1)a\hat{\lambda}}{1-(1-xa)\hat{\lambda}} \cdot \exp\left\{ -\frac{xa\hat{\lambda}}{1-(1-xa)\hat{\lambda}} \right\} \right) + \frac{xa\hat{\lambda}}{1-(1-xa)\hat{\lambda}} \right\} pL=exp{W0(−1−(1−xa)λ^(x+1)aλ^⋅exp{−1−(1−xa)λ^xaλ^})+1−(1−xa)λ^xaλ^}

p S = exp ⁡ { W − 1 ( − ( x + 1 ) a λ ^ 1 − ( 1 − x a ) λ ^ ⋅ exp ⁡ { − x a λ ^ 1 − ( 1 − x a ) λ ^ } ) + x a λ ^ 1 − ( 1 − x a ) λ ^ } p_S = \exp\left\{ \mathbb{W}_{-1} \left( -\frac{(x+1)a\hat{\lambda}}{1-(1-xa)\hat{\lambda}} \cdot \exp\left\{ -\frac{xa\hat{\lambda}}{1-(1-xa)\hat{\lambda}} \right\} \right) + \frac{xa\hat{\lambda}}{1-(1-xa)\hat{\lambda}} \right\} pS=exp{W−1(−1−(1−xa)λ^(x+1)aλ^⋅exp{−1−(1−xa)λ^xaλ^})+1−(1−xa)λ^xaλ^}

6. 非期望稳态点(公式51)

p A = exp ⁡ { − n ∑ i = 0 K − 1 p ( 1 − p ) i q i + ( 1 − p ) K q K } p_A = \exp\left\{ -\frac{n}{\sum_{i=0}^{K-1} \frac{p(1-p)^i}{q_i} + \frac{(1-p)^K}{q_K}} \right\} pA=exp{−∑i=0K−1qip(1−p)i+qK(1−p)Kn}

🎯 稳定区域公式

7. 稳定区域边界(公式60, 62)

q l = − p L ln ⁡ p L n − λ ^ − x a λ ^ ( 1 / p L − 1 ) ( ∑ i = 0 K − 1 ( 1 − p L ) i Q ( i ) + ( 1 − p L ) K Q ( K ) p L ) q_l = \frac{-p_L \ln p_L}{n-\hat{\lambda}-xa\hat{\lambda}(1/p_L-1)}\left(\sum_{i=0}^{K-1}\frac{(1-p_L)^i}{Q(i)}+\frac{(1-p_L)^K}{Q(K)p_L}\right) ql=n−λ^−xaλ^(1/pL−1)−pLlnpL(∑i=0K−1Q(i)(1−pL)i+Q(K)pL(1−pL)K)

q u = − 1 n ln ⁡ p S q_u = -\frac{1}{n} \ln p_S qu=−n1lnpS

8. 完整稳定区域(公式65, 71)

S L = [ q l , q u ] S_L = [q_l, q_u] SL=[ql,qu]

S K = 0 = [ − 1 n ln ⁡ p L , − 1 n ln ⁡ p S ] S^{K=0} = \left[-\frac{1}{n}\ln p_L, -\frac{1}{n}\ln p_S\right] SK=0=[−n1lnpL,−n1lnpS]

9. 特殊情况稳定区域

  • x=0时(公式73)

    S K = 0 , x = 0 = [ − 1 n W 0 ( − a λ ^ 1 − λ ^ ) , − 1 n W − 1 ( − a λ ^ 1 − λ ^ ) ] S^{K=0,x=0} = \left[-\frac{1}{n}\mathbb{W}0\left(\frac{-a\hat{\lambda}}{1-\hat{\lambda}}\right), -\frac{1}{n}\mathbb{W}{-1}\left(\frac{-a\hat{\lambda}}{1-\hat{\lambda}}\right)\right] SK=0,x=0=[−n1W0(1−λ^−aλ^),−n1W−1(1−λ^−aλ^)]

  • x=1/a时(公式74)

    S K = 0 , x = 1 / a = [ − 1 n ( W 0 ( − ( 1 + a ) λ ^ e − λ ^ ) + λ ^ ) , − 1 n ( W − 1 ( − ( 1 + a ) λ ^ e − λ ^ ) + λ ^ ) ] S^{K=0,x=1/a} = \left[ -\frac{1}{n}(\mathbb{W}0(-(1+a)\hat{\lambda}e^{-\hat{\lambda}})+\hat{\lambda}), -\frac{1}{n}(\mathbb{W}{-1}(-(1+a)\hat{\lambda}e^{-\hat{\lambda}})+\hat{\lambda}) \right] SK=0,x=1/a=[−n1(W0(−(1+a)λ^e−λ^)+λ^),−n1(W−1(−(1+a)λ^e−λ^)+λ^)]

⏱️ 时延性能公式

10. 平均接入时延(公式80)

E [ D 0 ] = 1 + x a ⋅ 1 − p p + a α ( ∑ i = 0 K − 1 ( 1 − p ) i q i + ( 1 − p ) K q K p ) E[D_0] = 1 + xa \cdot \frac{1-p}{p} + \frac{a}{\alpha} \left( \sum_{i=0}^{K-1} \frac{(1-p)^i}{q_i} + \frac{(1-p)^K}{q_K p} \right) E[D0]=1+xa⋅p1−p+αa(∑i=0K−1qi(1−p)i+qKp(1−p)K)

11. K=0时的时延矩(公式84-85)

E [ D 0 ] = 1 + x a ( 1 − p ) p + a α p q 0 E[D_0] = 1 + \frac{xa(1-p)}{p} + \frac{a}{\alpha p q_0} E[D0]=1+pxa(1−p)+αpq0a
E [ D 0 2 ] = 1 + x a ( 1 − p ) p ⋅ ( 2 + x a ( 2 − p ) p ) + a α p q 0 ⋅ ( 2 − a + 4 x a ( 1 − p ) p ) + 2 a 2 α 2 p 2 q 0 2 E[D_0^2] = 1 + \frac{xa(1-p)}{p} \cdot \left( 2 + \frac{xa(2-p)}{p} \right) + \frac{a}{\alpha p q_0} \cdot \left( 2 - a + \frac{4xa(1-p)}{p} \right) + \frac{2a^2}{\alpha^2 p^2 q_0^2} E[D02]=1+pxa(1−p)⋅(2+pxa(2−p))+αpq0a⋅(2−a+p4xa(1−p))+α2p2q022a2

12. 最小时延(公式86-87)

min ⁡ q 0 E [ D 0 ] = 1 + x a ( 1 − p L ) p L + n ln ⁡ p L λ ln ⁡ p S \min_{q_0} E[D_0] = 1 + \frac{xa(1-p_L)}{p_L} + \frac{n \ln p_L}{\lambda \ln p_S} minq0E[D0]=1+pLxa(1−pL)+λlnpSnlnpL

min ⁡ q 0 E [ D 0 2 ] = 1 + x a ( 1 − p L ) p L ( 2 + x a ( 2 − p L ) p L ) + n ln ⁡ p L λ ln ⁡ p S ( 2 − a + 4 x a ( 1 − p L ) p L ) + 2 n 2 ( ln ⁡ p L ) 2 λ 2 ( ln ⁡ p S ) 2 \min_{q_0} E[D_0^2] = 1 + \frac{xa(1-p_L)}{p_L} \left( 2 + \frac{xa(2-p_L)}{p_L} \right) + \frac{n \ln p_L}{\lambda \ln p_S} \left( 2 - a + \frac{4xa(1-p_L)}{p_L} \right) + \frac{2n^2 (\ln p_L)^2}{\lambda^2 (\ln p_S)^2} minq0E[D02]=1+pLxa(1−pL)(2+pLxa(2−pL))+λlnpSnlnpL(2−a+pL4xa(1−pL))+λ2(lnpS)22n2(lnpL)2

🔧 辅助公式

13. 信道空闲概率(公式32)

a l p h a = 1 x + 1 − x p − ( 1 / a − x ) p ln ⁡ p alpha = \frac{1}{x+1-xp-(1/a-x)p\ln p} alpha=x+1−xp−(1/a−x)plnp1

14. HOL包服务率(公式23)

t i l d e π T = 1 1 + x a ⋅ 1 − p p + a α ( ∑ i = 0 K − 1 ( 1 − p ) i q i + ( 1 − p ) K q K p ) tilde{\pi}T = \frac{1}{1+xa\cdot\frac{1-p}{p}+\frac{a}{\alpha}\left(\sum{i=0}^{K-1}\frac{(1-p)^i}{q_i}+\frac{(1-p)^K}{q_K p}\right)} tildeπT=1+xa⋅p1−p+αa(∑i=0K−1qi(1−p)i+qKp(1−p)K)1

🎯 理论对比的关键点

在仿真验证时,主要对比:

  1. 公式8 vs 仿真吞吐量:验证泊松假设下的吞吐量模型
  2. 公式34-35 vs 仿真稳态点:验证双稳态点的计算
  3. 公式71/73/74 vs 仿真稳定区域:验证稳定边界的准确性
  4. 公式80/84 vs 仿真时延:验证时延性能预测
  5. 公式9 vs 仿真最大吞吐量:验证极限性能分析

我的仿真

由于我们需要评价各协议的具体指标并于其它协议对比,所以为了统一性我们并不会完全按照论文中的仿真来做,而是按照论文思路,做吞吐量,公平性和时延性指标

吞吐量

有 退避

一、核心模型与假设
  1. 网络模型

    • 节点数量n_nodes 个同构节点。
    • 流量模型 :每个节点在每个正常时隙有独立且相同的概率 lambda_per_slot 产生一个新包。这是一个伯努利到达过程 ,总到达率为 lambda_hat = n_nodes * lambda_per_slot
    • 队列模型 :每个节点维护一个队列 (代码中用 node_queues 表示队列长度)。这是一个缓冲式CSMA 模型。
  2. 协议机制

    • 时间结构 :时间被划分为正常时隙 ,每个正常时隙进一步划分为多个微时隙 (迷你时隙)。微时隙长度为 a(相对于正常时隙的比例),每个正常时隙包含 minislots_per_slot = round(1/a) 个微时隙。
    • 载波侦听多路访问(CSMA):节点在传输前必须侦听信道。只有在信道空闲时,节点才能尝试传输。
    • 传输决策
      • 只有队列非空的节点才可能传输。
      • 每个这样的节点,在信道空闲的微时隙,独立地以固定概率 q0 决定是否传输 (注意:本仿真中采用了固定的传输概率,即 K=0 的 p-坚持CSMA)。
    • 碰撞检测
      • 如果在一个空闲微时隙内,有且仅有一个节点传输,则传输成功,该节点在当前正常时隙的剩余时间内占用信道。
      • 如果传输节点数大于1,则发生碰撞。碰撞会持续 x 个微时隙(如果 x=0,则碰撞立即被检测,信道立即空闲;否则,信道在 x 个微时隙内为忙状态)。
  3. 关键系统参数

    • 微时隙长度 a:决定信道侦听的时间粒度
    • 碰撞检测时间 x:决定碰撞后信道的占用时间
    • 初始传输概率 q0:节点在信道空闲时的传输概率
二、仿真流程与逻辑(逐微时隙)

仿真核心是一个嵌套循环:外层循环遍历不同的 q0 值,内层循环对每个 q0 进行 total_normal_slots 个正常时隙的模拟,每个正常时隙内又分为多个微时隙。

对于每个正常时隙 normal_slot,执行以下步骤:

  1. 包到达

    • 在每个正常时隙的第一个微时隙,为所有节点生成随机数,判断本正常时隙是否有新包到达。
    • 将到达的包加入对应节点的队列。node_queues(i) = node_queues(i) + 1;
  2. 微时隙内的处理

    • 对于每个微时隙 ms(全局微时隙索引 mini_global):
      • 更新信道状态 :如果当前微时隙超过了信道的忙状态结束时间(busy_until_global),则设置信道为空闲。
      • 退避计数器更新:如果信道空闲,所有节点的退避计数器减1(如果大于0)。
      • 传输决策 :如果信道空闲,且节点队列非空,且退避计数器为0,则节点以概率 q0 尝试传输。记录所有尝试传输的节点。
      • 冲突检测与成功处理
        • 如果尝试传输的节点数恰好为1,则成功传输。
          • 该节点的队列减1。
          • 信道状态设置为成功,并设置信道忙直到当前正常时隙结束(即占用整个正常时隙)。
          • 跳出当前正常时隙的微时隙循环(因为成功传输后,信道在该正常时隙剩余时间内都是忙的)。
        • 如果尝试传输的节点数大于1,则发生碰撞。
          • 信道状态设置为碰撞,并设置信道忙状态持续 x 个微时隙(如果 x=0,则忙状态只持续当前微时隙;否则,持续 x 个微时隙)。
          • 注意:代码中注释掉了碰撞后节点的退避计数器增加(指数退避)部分,因此本仿真中节点在碰撞后不会增加退避窗口,而是继续以概率 q0 尝试。
  3. 性能统计

    • 在每个微时隙,记录传输尝试次数(total_attempts 在每次尝试时加1)。
    • 成功传输时,记录成功次数(total_success 加1)。
三、关键性能指标
  1. 吞吐量 throughput

    • 定义:平均每个正常时隙成功传输的包数量。
    • 计算total_success / total_normal_slots
    • 目的 :这是最核心的性能指标 ,用于绘制"吞吐量 vs. 传输概率 q0"曲线,找到使吞吐量最大化的最优 q0
  2. 尝试率 attempt_rate

    • 定义:平均每个正常时隙发生的传输尝试次数(包括成功的和冲突的)。
    • 计算total_attempts / total_normal_slots
    • 目的:衡量信道竞争的激烈程度和协议效率。过高的尝试率意味着大量冲突。
  3. 理论验证指标

    • 理论最大吞吐量 :基于论文公式计算不同 ax 下的理论性能上限
    • 稳定区域 :计算保证系统稳定的 q0 取值范围
四、仿真策略与特点
  1. 参数扫描

    • 通过外层循环遍历 q0_values 数组(即不同的 q0 值),系统地研究传输概率对系统性能的影响。
  2. 多次独立仿真

    • 对每个 q0 值,进行 num_simulations 次独立仿真,计算吞吐量和尝试率的均值和标准差,以减小随机性影响。
  3. 理论对比

    • 根据论文中的理论公式,计算理论吞吐量曲线和稳定区域,与仿真结果进行对比。
  4. 性能评估

    • 仿真的最终目标是得到两条曲线:
      • throughputq0 变化的曲线。
      • attempt_rateq0 变化的曲线。
    • 通过分析这些曲线,可以确定系统的最佳工作点,并验证理论分析。
  5. 优化技巧

    • 使用了向量化操作,对所有节点的到达进行批量随机数生成和逻辑判断。
    • 采用微时粒度的仿真,精确模拟CSMA的载波侦听和碰撞检测过程。

与论文仿真思路的对比

方面 本仿真思路 论文中的仿真思路
核心协议 p-坚持CSMA (K=0) ,固定传输概率 q0 K-指数退避框架,传输概率随碰撞次数变化
关键观测变量 (但可以扩展记录瞬态成功概率) 瞬态成功概率 ( p t ) ( p_t ) (pt)
性能指标 吞吐量尝试率 吞吐量平均延迟延迟二阶矩
分析重点 寻找最优固定 q0,以最大化吞吐量 分析双稳态稳定区域延迟抖动K 的关系
节点状态 队列长度、退避计数器(但未用于退避) 队列长度 + 相位 (0 to K)
动态行为 无记忆性,每次尝试概率相同 有记忆性,碰撞后退避,传输概率降低
时间结构 微时隙+正常时隙双层结构 统一的微时隙时间轴

代码:CSMA_corrected.m

matlab 复制代码
clear all; close all; clc;

%% CSMA协议仿真与分析 - 修正版本(区分迷你时隙和正常时隙)
% 基于论文《Toward a Coherent Theory of CSMA and Aloha》的理论框架
% 主要修正:正确区分迷你时隙(用于信道监听)和正常时隙(用于数据传输)
fprintf('CSMA协议仿真与分析 - 修正版本\n');
fprintf('====================================\n');

% === 系统参数设置 ===
n_nodes = 50;           % 网络中的节点数量
a = 0.01;               % 迷你时隙长度(相对于正常时隙的比例)
x = 0;                  % 碰撞检测时间(迷你时隙数),x=0表示瞬时检测
lambda_per_slot = 0.03; % 每个正常时隙每个节点的数据包到达率
q0_values = 0:0.05:1;   % 初始传输概率的测试范围
num_simulations = 5;    % 每个q0值的独立仿真次数

fprintf('系统参数:\n');
fprintf('  节点数 n = %d\n', n_nodes);
fprintf('  迷你时隙长度 a = %.3f\n', a);
fprintf('  碰撞检测时间 x = %d 个迷你时隙\n', x);
fprintf('  单节点到达率 λ = %.3f 包/时隙\n', lambda_per_slot);
fprintf('  传输概率范围 q0 = %.2f ~ %.2f\n', q0_values(1), q0_values(end));
fprintf('  每个q0值的仿真次数 = %d\n\n', num_simulations);

% === 时间轴参数计算 ===
% 关键修正:正确计算迷你时隙和正常时隙的关系
total_normal_slots = 5000;              % 总的正常时隙数量(用于性能统计)
minislots_per_slot = round(1 / a);      % 每个正常时隙包含的迷你时隙数
total_minislots = total_normal_slots * minislots_per_slot;  % 总的迷你时隙数

fprintf('时间轴参数:\n');
fprintf('  仿真时长: %d 个正常时隙\n', total_normal_slots);
fprintf('  每个正常时隙包含 %d 个迷你时隙\n', minislots_per_slot);
fprintf('  总迷你时隙数: %d\n\n', total_minislots);

% === 初始化结果存储结构 ===
results = [];  % 存储所有仿真结果

%% 主仿真循环:遍历不同的传输概率q0
for q_idx = 1:length(q0_values)
    q0 = q0_values(q_idx);  % 当前测试的传输概率
    
    fprintf('正在测试 q0 = %.2f (%d/%d)...\n', q0, q_idx, length(q0_values));
    
    % 为当前q0值存储多次仿真的结果
    throughputs = zeros(1, num_simulations);    % 吞吐量结果
    attempt_rates = zeros(1, num_simulations);  % 尝试率结果
    
    %% 多次独立仿真(减少随机性影响)
    for sim_idx = 1:num_simulations
        % === 节点状态初始化 ===
        node_queues = zeros(n_nodes, 1);    % 各节点的数据包队列长度
        node_backoff = zeros(n_nodes, 1);   % 各节点的退避计数器(迷你时隙)
        
        % === 性能统计初始化 ===
        total_success = 0;      % 成功传输的数据包总数
        total_attempts = 0;     % 总的传输尝试次数 (aggregate attempts over whole sim)
        
        % === 信道状态初始化 ===
        channel_state = 'idle';     % 信道状态:'idle', 'success', 'collision'
        busy_until_global = 0;      % 全局忙状态持续到哪个迷你时隙(全局计数)
        current_transmitter = -1;   % 当前正在传输的节点编号(-1表示无)
        
        %% 采用"正常时隙外层 + 迷你时隙内层"的双层循环(与之前一致)
        for normal_slot = 1:total_normal_slots
            base_mini = (normal_slot - 1) * minislots_per_slot;
            for ms = 1:minislots_per_slot
                mini_global = base_mini + ms;
                % 到达在每个正常时隙的第一个迷你时隙
                if ms == 1
                    for i = 1:n_nodes
                        if rand() < lambda_per_slot
                            node_queues(i) = node_queues(i) + 1;
                        end
                    end
                end
                
                if mini_global > busy_until_global
                    channel_state = 'idle';
                    current_transmitter = -1;
                else
                    channel_state = 'collision';
                end
                
                if strcmp(channel_state,'idle')
                    node_backoff = max(0, node_backoff - 1);
                end
                
                if strcmp(channel_state,'idle')
                    attempting_nodes = [];
                    for i = 1:n_nodes
                        if node_queues(i) > 0 && node_backoff(i) == 0
                            if rand() < q0
                                attempting_nodes = [attempting_nodes, i];
                                total_attempts = total_attempts + 1;
                            end
                        end
                    end
                    
                    if ~isempty(attempting_nodes)
                        if length(attempting_nodes) == 1
                            transmitter = attempting_nodes(1);
                            node_queues(transmitter) = node_queues(transmitter) - 1;
                            total_success = total_success + 1;
                            channel_state = 'success';
                            current_transmitter = transmitter;
                            busy_until_global = base_mini + minislots_per_slot; 
                            break;
                        else
                            channel_state = 'collision';
                            if x <= 0
                                busy_until_global = mini_global;
                            else
                                busy_until_global = mini_global + x - 1;
                            end
                            % === 关键修正建议(若要与论文一致,注释掉下面BE退避) ===
                            % 下面的BE退避会导致高 q0 区域陷入冻结;若要仿真论文的 p-persistent 模型,请注释掉以下退避设置
                            % for ii = attempting_nodes
                            %     backoff_window = min(16, 2^(node_backoff(ii) + 1));
                            %     node_backoff(ii) = randi(backoff_window);
                            % end
                        end
                    end
                end
            end % ms
        end % normal_slot
        
        throughputs(sim_idx) = total_success / total_normal_slots;
        attempt_rates(sim_idx) = total_attempts / total_normal_slots;
        
        fprintf('  仿真 %d/%d: 吞吐量 = %.4f, 尝试率 = %.4f (成功=%d, 尝试=%d)\n', ...
                sim_idx, num_simulations, throughputs(sim_idx), attempt_rates(sim_idx), total_success, total_attempts);
    end % sim
    
    mean_throughput = mean(throughputs);
    std_throughput = std(throughputs);
    mean_attempt_rate = mean(attempt_rates);
    std_attempt_rate = std(attempt_rates);
    
    results(q_idx).q0 = q0;
    results(q_idx).throughput_mean = mean_throughput;
    results(q_idx).throughput_std = std_throughput;
    results(q_idx).attempt_rate_mean = mean_attempt_rate;
    results(q_idx).attempt_rate_std = std_attempt_rate;
    results(q_idx).throughputs_all = throughputs;
    results(q_idx).attempt_rates_all = attempt_rates;
    
    fprintf('q0 = %.2f 结果: 平均吞吐量 = %.4f ± %.4f, 平均尝试率 = %.4f ± %.4f\n\n', ...
            q0, mean_throughput, std_throughput, mean_attempt_rate, std_attempt_rate);
end % q loop

%% ==== 这里开始:严格修正的"理论性能分析"部分(直接替换你的原有部分) ====
fprintf('=== 理论性能分析 ===\n');

% 计算聚合输入速率
lambda_hat = n_nodes * lambda_per_slot;
fprintf('聚合输入速率: λ_hat = n × λ = %.3f\n', lambda_hat);

% 计算CSMA网络的理论吞吐量曲线
% G 的单位:attempts per NORMAL SLOT(与仿真口径一致)

G_range = 0:0.01:5;                    % 尝试率G的取值范围
lambda_theo = zeros(size(G_range));    % 存储理论吞吐量
lambda_max = 0;                        % 最大理论吞吐量
G_optimal = 0;                         % 达到最大吞吐量的最优尝试率

% ---------- 严格区分 x==0 与 x>0 的数学表达 ----------
if x == 0
    % 瞬时碰撞检测:论文中对 x=0 的退化形式(数值稳定且与文献一致)
    % S(G) = (G * exp(-aG)) / (1 + a*G)
    lambda_theo = (G_range .* exp(-a .* G_range)) ./ (1 + a .* G_range);
else
    % 通用情况(x>0),按照论文通式向量化计算
    % numerator = G * exp(-a * G)
    % denominator = x + 1 - x * exp(-a * G) + (1/a - x) * a * G * exp(-a * G)
    numerator = G_range .* exp(-a .* G_range);
    denominator = x + 1 - x .* exp(-a .* G_range) + (1./a - x) .* a .* G_range .* exp(-a .* G_range);
    lambda_theo = numerator ./ denominator;
end

% ---------- 容错处理:若存在 NaN/Inf(数值异常),置为 0(防止绘图中断) ----------
lambda_theo(~isfinite(lambda_theo)) = 0;

% ---------- 记录最大值与对应 G ----------
[lambda_max, idx_max] = max(lambda_theo);
if ~isempty(idx_max)
    G_optimal = G_range(idx_max);
else
    G_optimal = 0;
end

fprintf('理论最大吞吐量: %.4f (在 G = %.2f 时达到)\n', lambda_max, G_optimal);

% 计算稳定区域(基于论文第IV节,保留你原有实现)
if lambda_hat <= lambda_max
    if x == 0
        argument = -a * lambda_hat / (1 - lambda_hat);
        p_L = exp(lambertw(0, argument));  % 期望稳定点
        p_S = exp(lambertw(-1, argument)); % 临界点
    else
        argument = -(1 + a) * lambda_hat * exp(-lambda_hat);
        p_L = exp(lambertw(0, argument) + lambda_hat);
        p_S = exp(lambertw(-1, argument) + lambda_hat);
    end
    q_lower = -log(p_L) / n_nodes;
    q_upper = -log(p_S) / n_nodes;
else
    q_lower = 0; q_upper = 0;
end

%% ==== 后续绘图部分(保持你原来的 8 图 + Fig.4) ====
fprintf('\n=== 生成性能分析图表 ===\n');

q0_list = [results.q0];
throughput_mean = [results.throughput_mean];
throughput_std = [results.throughput_std];
attempt_mean = [results.attempt_rate_mean];
attempt_std = [results.attempt_rate_std];
[max_throughput, max_idx] = max(throughput_mean);
optimal_q0 = q0_list(max_idx);

figure('Position', [100, 100, 1400, 1000], 'Name', 'CSMA协议性能分析');

% 1. 吞吐量 vs 传输概率(带误差棒)
subplot(2, 4, 1);
errorbar(q0_list, throughput_mean, throughput_std, 'bo-', ...
         'LineWidth', 2, 'MarkerSize', 6, 'CapSize', 5, ...
         'DisplayName', '仿真结果');
hold on;
% 标记理论稳定区域
if q_lower > 0 && q_upper > q_lower
    y_lim = ylim;
    fill_area = fill([q_lower, q_lower, q_upper, q_upper], ...
                    [y_lim(1), y_lim(2), y_lim(2), y_lim(1)], ...
                    [0.8, 1, 0.8], 'EdgeColor', 'none');
    set(fill_area, 'FaceAlpha', 0.3, 'DisplayName', '理论稳定区域');
end
plot(optimal_q0, max_throughput, 'ro', 'MarkerSize', 10, ...
     'LineWidth', 3, 'DisplayName', '最优工作点');
xlabel('传输概率 q_0');
ylabel('网络吞吐量 \lambda');
title('吞吐量与传输概率的关系');
legend('show', 'Location', 'best');
grid on;

% 2. 尝试率 vs 传输概率(带误差棒)
subplot(2, 4, 2);
errorbar(q0_list, attempt_mean, attempt_std, 'ro-', ...
         'LineWidth', 2, 'MarkerSize', 6, 'CapSize', 5);
xlabel('传输概率 q_0');
ylabel('尝试率 G (attempts / normal slot)');
title('尝试率与传输概率的关系');
grid on;

% 3. 理论曲线 vs 仿真结果对比
subplot(2, 4, 3);
plot(G_range, lambda_theo, 'r-', 'LineWidth', 3, ...
     'DisplayName', '理论吞吐量曲线 (论文 (8))');
hold on;
% 绘制所有仿真数据点(显示随机性分布)
for q_idx = 1:length(results)
    scatter(results(q_idx).attempt_rates_all, results(q_idx).throughputs_all, ...
            20, 'b', 'filled', 'MarkerFaceAlpha', 0.3, ...
            'HandleVisibility', 'off');
end
% 绘制平均值点
scatter(attempt_mean, throughput_mean, 50, 'bo', 'filled', ...
        'DisplayName', '仿真平均值');
xlabel('尝试率 G (attempts / normal slot)');
ylabel('吞吐量 \lambda');
title('理论 vs 仿真 对比 (所有数据点)');
legend('show', 'Location', 'best');
grid on;

% 4. CSMA vs Aloha 性能对比
subplot(2, 4, 4);
lambda_aloha = G_range .* exp(-G_range);
plot(G_range, lambda_theo, 'b-', 'LineWidth', 2, 'DisplayName', 'CSMA理论');
hold on;
plot(G_range, lambda_aloha, 'r-', 'LineWidth', 2, 'DisplayName', 'Aloha理论');
xlabel('尝试率 G');
ylabel('吞吐量 \lambda');
title('CSMA vs Aloha 性能对比');
legend('show', 'Location', 'best');
grid on;

% 5. 吞吐量波动性分析
subplot(2, 4, 5);
coefficient_of_variation = throughput_std ./ throughput_mean;
plot(q0_list, coefficient_of_variation * 100, 'mo-', ...
     'LineWidth', 2, 'MarkerSize', 6);
xlabel('传输概率 q_0');
ylabel('变异系数 (%)');
title('吞吐量波动性分析');
grid on;

% 6. 传输效率分析(吞吐量/尝试率)
subplot(2, 4, 6);
efficiency_mean = throughput_mean ./ (attempt_mean + eps);  % 避免除零
efficiency_std = sqrt((throughput_std ./ (throughput_mean + eps)).^2 + ...
                      (attempt_std ./ (attempt_mean + eps)).^2) .* efficiency_mean;
errorbar(q0_list, efficiency_mean, efficiency_std, 'ko-', ...
         'LineWidth', 2, 'MarkerSize', 6, 'CapSize', 5);
xlabel('传输概率 q_0');
ylabel('传输效率 (\lambda/G)');
title('传输效率 vs 传输概率');
grid on;

% 7. 吞吐量分布箱线图
subplot(2, 4, 7);
throughput_data = [];
q0_labels = {};
for q_idx = 1:length(results)
    throughput_data = [throughput_data, results(q_idx).throughputs_all'];
    q0_labels{q_idx} = sprintf('%.2f', results(q_idx).q0);
end
boxplot(throughput_data, 'Labels', q0_labels);
xlabel('传输概率 q_0');
ylabel('吞吐量 \lambda');
title('各q0值的吞吐量分布');
grid on; xtickangle(45);

% 8. 性能总结对比图
subplot(2, 4, 8);
bar_values = [lambda_max, max_throughput, exp(-1)];
bar_labels = {'CSMA理论最大', 'CSMA仿真最优', 'Aloha理论最大'};
bar(bar_values); set(gca,'XTickLabel',bar_labels);
ylabel('吞吐量 \lambda'); title('性能总结对比'); grid on;

%% === 额外:验证论文 Fig.4(最大吞吐量随 a 变化) ===
a_values = [1, 0.1, 0.01, 0.001, 0.0001];
lambda_max_vs_a = zeros(size(a_values));
for ia = 1:length(a_values)
    aa = a_values(ia);
    if x == 0
        % 这是用于示意/验证的近似表达(论文有解析形式)
        lambda_max_vs_a(ia) = max((G_range .* exp(-aa .* G_range)) ./ (1 + aa .* G_range));
    else
        numerator = G_range .* exp(-aa .* G_range);
        denominator = x + 1 - x .* exp(-aa .* G_range) + (1./aa - x) .* aa .* G_range .* exp(-aa .* G_range);
        temp = numerator ./ denominator;
        temp(~isfinite(temp)) = 0;
        lambda_max_vs_a(ia) = max(temp);
    end
end
figure('Name','Fig4-like: 最大吞吐量随 a 的变化 (理论)');
plot(a_values, lambda_max_vs_a, 'bo-','LineWidth',2);
set(gca,'XScale','log');
xlabel('迷你时隙长度 a (log scale)');
ylabel('理论最大吞吐量 \lambda_{max}');
title('理论:最大吞吐量 vs a (类 Fig.4)');
grid on;

%% 详细性能分析报告(保留)
fprintf('\n=== 详细性能分析报告 ===\n');
fprintf('最优工作点分析:\n');
fprintf('  最优传输概率: q0* = %.3f\n', optimal_q0);
fprintf('  最大平均吞吐量: λ_max = %.4f ± %.4f\n', max_throughput, throughput_std(max_idx));
fprintf('  对应的平均尝试率: G = %.4f ± %.4f\n', attempt_mean(max_idx), attempt_std(max_idx));
fprintf('  吞吐量变异系数: %.2f%%\n', coefficient_of_variation(max_idx) * 100);

% 与Aloha协议对比与其它分析(保持原文)
fprintf('\n仿真完成!所有图表已生成。\n');

%% Lambert W函数实现(保留)
function w = lambertw(k, x)
    if k == 0
        try
            w = builtin('lambertw', 0, x);
        catch
            if x >= -1/exp(1)
                w = log(1 + x);
                for it = 1:10
                    ew = exp(w);
                    w = w - (w*ew - x) / ((w+1)*ew - (w+2)*(w*ew - x)/(2*w+2));
                end
            else
                w = -1;
            end
        end
    else
        try
            w = builtin('lambertw', -1, x);
        catch
            w = log(-x) - log(-log(-x));
        end
    end
end

结果与结论


可以看出,仿真趋势线与论文中的图类似,基本没问题。但问题在于仿真实际上认为mini_slot太小,已经忽略了(实际上并不可以忽略),不过本仿真也只是看大概趋势,实际上大概趋势差不多,不过明显观察到a=0.01的曲线还是有一段区间很不一样,这其实是因为退避方法在 q 0 > 0.5 q_0>0.5 q0>0.5时监听过程中会多次碰撞,不断退避,导致很难继续发送数据包,导致吞吐量减小,所以为了更符合论文的曲线,我们接下来做无退避的

本仿真代码实现了一个基础的缓冲式时隙CSMA模型 ,旨在通过蒙特卡洛仿真验证CSMA协议的基本特性:

  • 在轻负载下,低 q0 可能导致信道利用率不足。
  • 在重负载下,高 q0 会导致过多冲突,吞吐量下降。
  • 存在一个最优的 q0,使得吞吐量达到最大值。
  • 通过改变微时隙长度 a 和碰撞检测时间 x,可以研究它们对性能的影响。

此外,本仿真还通过与理论结果的对比,验证了理论分析的正确性,并展示了CSMA相对于Aloha的性能优势。

无 退避(非饱和)

代码仿真思路描述

一、核心模型与假设

  1. 网络模型

    • 节点数量n_nodes = 50 个同构节点
    • 流量模型 :每个节点在每个正常时隙有独立概率 lambda_per_slot = 0.001 产生新包,形成轻负载非饱和条件
    • 队列模型 :每个节点维护队列 node_queues,构成缓冲式CSMA 模型
  2. 协议机制

    • 时间结构 :采用微时隙+正常时隙 双层结构,微时隙长度 a = 0.01
    • CSMA核心机制
      • 节点在传输前必须侦听信道,只有信道空闲才能尝试
      • 采用p-坚持CSMA (K=0) ,固定传输概率 q0
      • 碰撞检测时间 x = 0(瞬时检测)
  3. 关键诊断特性

    • 非饱和条件 :聚合到达率 lambda_hat = 0.05 远低于信道容量
    • 热身期处理:丢弃前10%数据以减少瞬态影响

二、仿真流程与逻辑

主循环结构

matlab 复制代码
for q_idx = 1:length(q0_values)     % 遍历传输概率
    for sim_idx = 1:num_simulations % 多次独立仿真
        while mini_slot <= total_minislots  % 微时隙级仿真
            % 核心状态机逻辑
        end
    end
end

每个微时隙的状态处理

  1. 包到达检测

    • 仅在每个正常时隙的第一个微时隙检查新包到达
    • node_queues = node_queues + (rand(n_nodes,1) < lambda_per_slot)
  2. 信道状态管理

    • 检查 mini_slot < channel_busy_until 判断信道忙闲
    • 忙状态直接跳过当前微时隙
  3. 传输决策与冲突处理

    • 空闲时,队列非空节点以概率 q0 尝试传输
    • 成功传输:占用整个正常时隙,队列减1
    • 碰撞 :信道忙 x 个微时隙

三、关键性能指标与诊断设计

  1. 双口径尝试率统计

    • G_normal_slot:每正常时隙的尝试次数
    • G_per_minislot:每微时隙的尝试次数
    • 诊断目的:验证理论公式中G的口径一致性
  2. 非饱和约束分析

    • 理论吞吐量受限于 min(理论值, lambda_hat)
    • 诊断目的:区分理论极限与实际可达吞吐量
  3. 统计鲁棒性增强

    • 热身期数据丢弃 (warmup_ratio = 0.1)
    • 多次独立仿真求均值
    • 计算变异系数评估波动性

四、仿真验证策略

  1. 参数扫描验证

    • 系统扫描 q0 = 0:0.05:1
    • 识别最优工作点和稳定区域
  2. 理论-实验对比

    • 绘制理论吞吐量曲线(原始和受限版本)
    • 散点图展示仿真数据分布
  3. 多维度诊断分析

    • 吞吐量稳定性:通过变异系数分析
    • 传输效率λ/G 反映协议效率
    • 参数敏感性 :分析 a 对性能的影响

五、创新性诊断特性

  1. 非饱和条件专门优化

    • 极低到达率 lambda_per_slot = 0.001 确保非饱和
    • 明确标注 lambda_hat 上界线
  2. 双口径G统计

    matlab 复制代码
    attempt_rates_normal = total_attempts_eff / total_normal_slots;      % 正常时隙口径
    attempt_rates_mini   = total_attempts_eff / (total_normal_slots * minislots_per_slot); % 微时隙口径

    诊断价值:澄清理论公式中G的定义歧义

  3. 受限性能分析

    • 区分理论极限 lambda_theo_raw 和实际可达 lambda_theo_feasible
    • 反映真实系统中输入率限制的影响

六、与标准仿真的关键差异

方面 本诊断版仿真 标准CSMA仿真
负载条件 刻意非饱和 (λ=0.001) 通常饱和或可变负载
性能关注 输入率限制下的实际性能 理论最大吞吐量
统计口径 双G口径对比分析 单一G统计
诊断重点 协议效率、稳定性 吞吐量最大化
理论对比 受限理论 vs 原始理论 标准理论公式验证
matlab 复制代码
clear all; close all; clc;
fprintf('CSMA协议仿真与分析 - 非饱和诊断版\n');
fprintf('==================================================\n');

%% === 系统参数 ===
n_nodes = 50;           
a = 0.01;               
x = 0;                  
lambda_per_slot = 0.001;    % 非饱和条件关键参数
q0_values = 0:0.05:1;      
num_simulations = 5;       
warmup_ratio = 0.1;         % 热身期比例

lambda_hat = n_nodes * lambda_per_slot; % 聚合到达率上限
fprintf('系统参数:\n');
fprintf('  节点数 n = %d\n  a = %.3f, x = %d\n  单节点到达率 λ_in = %.4f\n  聚合到达率 λ_hat = %.4f\n\n',...
    n_nodes,a,x,lambda_per_slot,lambda_hat);

%% === 仿真主循环 ===
total_normal_slots = 10000;
minislots_per_slot = round(1 / a);
total_minislots = total_normal_slots * minislots_per_slot;

results = [];

for q_idx = 1:length(q0_values)
    q0 = q0_values(q_idx);
    fprintf('正在仿真 q0 = %.2f (%d/%d)...\n', q0, q_idx, length(q0_values));

    throughputs = zeros(1, num_simulations);
    attempt_rates_normal = zeros(1, num_simulations);
    attempt_rates_mini = zeros(1, num_simulations);

    for sim_idx = 1:num_simulations
        node_queues = zeros(n_nodes,1);
        total_success = 0;
        total_attempts = 0;
        channel_busy_until = 0;
        mini_slot = 1;

        while mini_slot <= total_minislots
            % === 新包到达 ===
            if mod(mini_slot, minislots_per_slot) == 1
                arrivals = rand(n_nodes,1) < lambda_per_slot;
                node_queues = node_queues + arrivals;
            end

            % === 信道忙检查 ===
            if mini_slot < channel_busy_until
                mini_slot = mini_slot + 1;
                continue;
            end

            % === 尝试发送 ===
            attempting_nodes = find(node_queues > 0 & rand(n_nodes,1) < q0);
            total_attempts = total_attempts + length(attempting_nodes);

            if isempty(attempting_nodes)
                mini_slot = mini_slot + 1;
            elseif length(attempting_nodes) == 1
                % 成功发送
                tx = attempting_nodes(1);
                node_queues(tx) = node_queues(tx) - 1;
                total_success = total_success + 1;
                channel_busy_until = mini_slot + minislots_per_slot - 1;
                mini_slot = channel_busy_until + 1;
            else
                % 碰撞
                channel_busy_until = mini_slot + x;
                mini_slot = mini_slot + 1;
            end
        end

        % === 丢弃热身期的前10% ===
        valid_slots = total_normal_slots * (1 - warmup_ratio);
        total_success_eff = total_success * (valid_slots / total_normal_slots);
        total_attempts_eff = total_attempts * (valid_slots / total_normal_slots);

        % === 两种G口径统计 ===
        throughputs(sim_idx) = total_success_eff / total_normal_slots;
        attempt_rates_normal(sim_idx) = total_attempts_eff / total_normal_slots;
        attempt_rates_mini(sim_idx)   = total_attempts_eff / (total_normal_slots * minislots_per_slot);
    end

    % === 结果汇总 ===
    results(q_idx).q0 = q0;
    results(q_idx).lambda_mean = mean(throughputs);
    results(q_idx).lambda_std = std(throughputs);
    results(q_idx).G_mean_normal = mean(attempt_rates_normal);
    results(q_idx).G_std_normal = std(attempt_rates_normal);
    results(q_idx).G_mean_mini = mean(attempt_rates_mini);
end

%% === 理论分析 ===
G_range = 0:0.01:5;
lambda_theo_raw = (G_range .* exp(-a .* G_range)) ./ (1 + a .* G_range);
lambda_theo_feasible = min(lambda_theo_raw, lambda_hat);  % 加上非饱和约束
lambda_max = max(lambda_theo_feasible);
G_opt = G_range(lambda_theo_feasible == lambda_max);

fprintf('\n理论最大吞吐量(受限): %.4f (G=%.2f)\n', lambda_max, G_opt);

%% === 输出统计表格 ===
q0_list = [results.q0];
lambda_mean = [results.lambda_mean];
lambda_std = [results.lambda_std];
G_mean_normal = [results.G_mean_normal];
G_mean_mini = [results.G_mean_mini];

disp('--- 仿真统计检查(非饱和诊断) ---');
T = table(q0_list',lambda_mean',G_mean_normal',G_mean_mini',...
    'VariableNames',{'q0','lambda','G_normal_slot','G_per_minislot'});
disp(T);

%% === 绘图 ===
figure('Name','CSMA 非饱和仿真诊断','Position',[100 100 1400 900]);

% 1. 吞吐量 vs q0
subplot(2,3,1);
errorbar(q0_list,lambda_mean,lambda_std,'bo-','LineWidth',2);
yline(lambda_hat,'r--','LineWidth',1.5,'DisplayName','λ̂ 上界');
xlabel('传输概率 q_0'); ylabel('吞吐量 λ');
title('吞吐量与传输概率 (非饱和)');
legend('仿真','λ̂ 上界'); grid on;

% 2. G vs q0
subplot(2,3,2);
plot(q0_list,G_mean_normal,'ko-','LineWidth',2,'DisplayName','每正常时隙 G');
hold on;
plot(q0_list,G_mean_mini,'r--','LineWidth',1.5,'DisplayName','每迷你时隙 G');
xlabel('传输概率 q_0'); ylabel('G');
legend('Location','best'); grid on; title('尝试率双口径比较');

% 3. 理论 vs 仿真 (λ-G)
subplot(2,3,3);
plot(G_range,lambda_theo_raw,'g-','LineWidth',2,'DisplayName','理论 raw');
hold on;
plot(G_range,lambda_theo_feasible,'r--','LineWidth',2,'DisplayName','理论 (受 λ̂ 限制)');
scatter(G_mean_normal,lambda_mean,60,'bo','filled','DisplayName','仿真');
xlabel('G (每正常时隙尝试率)'); ylabel('λ (吞吐量)');
legend('Location','best'); grid on;
title('理论 vs 仿真 (含 λ̂ 约束)');

% 4. 吞吐量波动性
subplot(2,3,4);
cv = lambda_std ./ (lambda_mean + eps);
plot(q0_list,cv*100,'mo-','LineWidth',2);
xlabel('q_0'); ylabel('变异系数 (%)'); title('吞吐波动性'); grid on;

% 5. 传输效率
subplot(2,3,5);
eff = lambda_mean ./ (G_mean_normal + eps);
plot(q0_list,eff,'b^-','LineWidth',2);
xlabel('q_0'); ylabel('效率 λ/G'); title('传输效率 (非饱和)'); grid on;

% 6. 直方图 (仅 q0=1)
subplot(2,3,6);
if any(q0_list==1)
    idx1 = find(q0_list==1);
    bar(1,lambda_mean(idx1),'b'); hold on;
    bar(2,G_mean_normal(idx1),'r');
    set(gca,'XTick',[1 2],'XTickLabel',{'λ','G'});
    title('q0=1 诊断(吞吐量 vs 尝试率)');
    ylabel('值');
end
sgtitle('CSMA 非饱和诊断版结果');

%% === λ vs a 曲线 (理论 + 仿真受限)
fprintf('\n=== 生成 λ vs a (受 λ̂ 限制) ===\n');
a_values = [0.0005 0.001 0.005 0.01 0.02 0.05 0.1];
lambda_max_theo = zeros(size(a_values));
lambda_max_sim = zeros(size(a_values));

for ia = 1:length(a_values)
    aa = a_values(ia);
    G_tmp = 0:0.01:5;
    lambda_vec = (G_tmp .* exp(-aa .* G_tmp)) ./ (1 + aa .* G_tmp);
    lambda_vec_feasible = min(lambda_vec, lambda_hat);
    lambda_max_theo(ia) = max(lambda_vec_feasible);
    lambda_max_sim(ia) = mean(lambda_mean); % 仿真受限基本恒定 ≈ λ̂
    fprintf('  a=%.4f: λ_theo_feasible=%.4f, λ_sim=%.4f\n',...
        aa,lambda_max_theo(ia),lambda_max_sim(ia));
end

figure('Name','λ vs a (受限理论+仿真)','Position',[200 200 900 600]);
plot(a_values,lambda_max_theo,'r-o','LineWidth',2,'DisplayName','理论受限 λ_{max}');
hold on;
plot(a_values,lambda_max_sim,'b-s','LineWidth',2,'DisplayName','仿真 λ_{max}');
yline(lambda_hat,'k--','LineWidth',1.2,'DisplayName','λ̂ 上界');
set(gca,'XScale','log');
xlabel('迷你时隙长度 a (log scale)');
ylabel('最大吞吐量 λ_{max}');
title('λ_{max} 随 a 的变化 (含 λ̂ 上界)');
legend('Location','best'); grid on;

结果与结论

λ 与 G 的总体一致性分析

结论 解释
λ ≈ 0.04 ~ 0.046 与理论非饱和输入速率 λ_hat = 0.05 接近,说明网络确实处于非饱和状态(未积压、队列稳定)。
G_normal_slot ≈ λ 尝试率 G 与吞吐率 λ 接近,意味着大部分尝试是成功的(冲突概率低)。
G_per_minislot ≈ 0.0004--0.0005 因为每个正常时隙包含 1/a = 100 个迷你时隙,这个数量级是合理的: G_per_minislot ≈ a·G_normal。
q0 增大后 λ 几乎不变 因为系统被到达率限制了(非饱和),再增加发送概率也不会提升吞吐量。

异常点分析(q0 = 1)

指标 说明
λ(1) = 0.0019 几乎归零,说明发生了严重拥塞。
G_normal = 3881 极高的尝试率,意味着几乎所有节点一直争夺信道,但持续碰撞。
结果解释 典型"过度激进"行为:所有节点几乎同时发送,造成持续碰撞,吞吐量反而急剧下降。

这与 ALOHA/CSMA 理论完全一致:在非退避系统中,当 q → 1 时,系统进入碰撞饱和区,吞吐量迅速下降。


📊 三、λ vs a 的结果解释

a 理论 λ_feasible 仿真 λ_sim 说明
所有 a ≈ 0.05 ≈ 0.0399 仿真几乎恒定,略低于理论上界。

解释:

  • λ f e a s i b l e = m i n ( 理论值 , λ ^ ) = 0.05 ,因为 λ ^ = n ⋅ λ i n = 50 × 0.001 λ_feasible = min(理论值, λ̂) = 0.05,因为 λ̂= n·λ_in = 50×0.001 λfeasible=min(理论值,λ^)=0.05,因为λ^=n⋅λin=50×0.001;

  • 仿真 λ ≈ 0.04,低 20% 左右,是合理的:

    • 因为有部分时隙空闲(无节点发送);
    • 加上 a=0.01 → 迷你时隙占比高,信道效率略受影响;
    • 再加上 warmup 截断(10%)与有限采样误差。

所以图像上 λ_sim 是略低的平线,而 λ_theo_feasible 是 λ̂=0.05 的水平线。

这恰好验证了非饱和条件下吞吐量受到输入速率约束的特性,而不是退避或 a 值主导。


与论文 (饱和模型)差异总结

项目 论文 当前仿真
模型类型 饱和(所有节点随时都有包) 非饱和(到达率有限)
主变量 λ vs G,不同 p(q0) 曲线 λ vs q0,在固定 λ_in 下平缓
特征 λ 随 G 上升到峰值后下降(经典凸曲线) λ ≈ 常数(受 λ_in 限制),仅高 q0 区域崩溃
含义 验证 CSMA 理论极限 验证非饱和系统的稳定性与公平性

总结

仿真表明:在无退避的非饱和 CSMA 系统中,当每节点到达率低(λ_in = 0.001, λ̂ = 0.05)时,系统吞吐量受限于输入速率,与 a、q0 基本无关;只有当 q0→1 时,由于冲突激增,吞吐量迅速坍塌。


无退避饱和

matlab 复制代码
%% === 修正CSMA仿真(解决吞吐量偏低问题)===
% 重点修复:信道状态管理、吞吐量统计、参数优化
clear all; close all; clc;

fprintf('=== 修正CSMA仿真(优化吞吐量)===\n');

% 参数设置
n_nodes = 20;
a_values = [0.001, 0.01, 0.05, 0.1];
x = 0;  % 即时碰撞检测
num_simulations = 3;
total_normal_slots = 10000;

all_results = [];

for a_idx = 1:length(a_values)
    a = a_values(a_idx);
    minislots_per_slot = round(1 / a);
    
    fprintf('\n分析 a = %.3f, minislots_per_slot = %d\n', a, minislots_per_slot);
    
    % === 动态调整q0搜索范围 ===
    % 理论最优q0 ≈ 1/(n * sqrt(a)),因为G_optimal ≈ 1/a
    q0_estimated = 1 / (n_nodes * sqrt(a));
    q0_range = max(0.001, q0_estimated * 0.1):(q0_estimated * 0.2):min(0.2, q0_estimated * 3);
    
    if isempty(q0_range)
        q0_range = 0.01:0.01:0.1;
    end
    
    throughputs_by_q0 = zeros(length(q0_range), num_simulations);
    attempt_rates_by_q0 = zeros(length(q0_range), num_simulations);
    
    for q_idx = 1:length(q0_range)
        q0 = q0_range(q_idx);
        
        for sim_idx = 1:num_simulations
            % === 修正的信道状态管理 ===
            total_success = 0;
            total_attempts = 0;
            total_idle_minislots = 0;
            
            % 信道状态
            channel_busy_until = 0;  % 信道忙碌直到的全局迷你时隙
            current_global_minislot = 0;
            
            % 节点状态(饱和:每个节点总有包)
            % 使用简单的退避机制
            node_backoff = zeros(n_nodes, 1);
            
            % === 按迷你时隙循环 ===
            for normal_slot = 1:total_normal_slots
                for mini_in_slot = 1:minislots_per_slot
                    current_global_minislot = current_global_minislot + 1;
                    
                    % 检查信道状态
                    if current_global_minislot <= channel_busy_until
                        % 信道忙碌,跳过
                        continue;
                    end
                    
                    % 信道空闲
                    total_idle_minislots = total_idle_minislots + 1;
                    
                    % 节点尝试传输
                    attempting_nodes = [];
                    for node = 1:n_nodes
                        if node_backoff(node) <= 0
                            if rand() < q0
                                attempting_nodes = [attempting_nodes, node];
                            end
                        else
                            node_backoff(node) = node_backoff(node) - 1;
                        end
                    end
                    
                    num_attempts = length(attempting_nodes);
                    total_attempts = total_attempts + num_attempts;
                    
                    if num_attempts == 1
                        % 成功传输
                        total_success = total_success + 1;
                        channel_busy_until = current_global_minislot + minislots_per_slot - 1;
                        % 成功节点重置
                        node_backoff(attempting_nodes) = 0;
                        
                    elseif num_attempts > 1
                        % 碰撞
                        collision_duration = max(1, x); % 至少1个迷你时隙
                        channel_busy_until = current_global_minislot + collision_duration - 1;
                        
                        % 碰撞节点随机退避
                        for node = attempting_nodes
                            node_backoff(node) = randi([1, round(10/a)]); % 退避时间与a相关
                        end
                    end
                    % num_attempts == 0: 保持空闲
                end
            end
            
            % 统计
            throughputs_by_q0(q_idx, sim_idx) = total_success / total_normal_slots;
            if total_idle_minislots > 0
                attempt_rates_by_q0(q_idx, sim_idx) = total_attempts / total_idle_minislots;
            else
                attempt_rates_by_q0(q_idx, sim_idx) = 0;
            end
        end
        
        fprintf('  q0=%.4f: λ=%.4f ± %.4f, G=%.4f ± %.4f\n', ...
                q0, mean(throughputs_by_q0(q_idx, :)), std(throughputs_by_q0(q_idx, :)), ...
                mean(attempt_rates_by_q0(q_idx, :)), std(attempt_rates_by_q0(q_idx, :)));
    end
    
    % 存储结果
    [best_throughput, best_idx] = max(mean(throughputs_by_q0, 2));
    best_q0 = q0_range(best_idx);
    best_G = mean(attempt_rates_by_q0(best_idx, :));
    
    all_results(a_idx).a = a;
    all_results(a_idx).q0_range = q0_range;
    all_results(a_idx).throughputs = throughputs_by_q0;
    all_results(a_idx).attempt_rates = attempt_rates_by_q0;
    all_results(a_idx).best_q0 = best_q0;
    all_results(a_idx).best_throughput = best_throughput;
    all_results(a_idx).best_G = best_G;
    
    % 计算稳定区域(吞吐量 > 95% 最优)
    throughput_means = mean(throughputs_by_q0, 2);
    threshold = best_throughput * 0.95;
    stable_indices = find(throughput_means >= threshold);
    if ~isempty(stable_indices)
        all_results(a_idx).stable_min = q0_range(min(stable_indices));
        all_results(a_idx).stable_max = q0_range(max(stable_indices));
        all_results(a_idx).stable_range = all_results(a_idx).stable_max - all_results(a_idx).stable_min;
    else
        all_results(a_idx).stable_min = NaN;
        all_results(a_idx).stable_max = NaN;
        all_results(a_idx).stable_range = 0;
    end
end

%% === 理论计算 ===
fprintf('\n=== 理论计算 ===\n');
fprintf('Aloha理论最大吞吐量: %.4f\n', exp(-1));

% 论文公式计算
for a_idx = 1:length(a_values)
    a = a_values(a_idx);
    
    % 对于x=0的情况,使用公式(10)
    G_range = 0:0.1:10;
    lambda_theo = (G_range .* exp(-a .* G_range)) ./ (1 + G_range .* exp(-a .* G_range));
    
    [lambda_max_theo, max_idx] = max(lambda_theo);
    G_optimal_theo = G_range(max_idx);
    
    all_results(a_idx).lambda_max_theo = lambda_max_theo;
    all_results(a_idx).G_optimal_theo = G_optimal_theo;
    
    fprintf('a=%.3f: 理论λ_max=%.4f (G=%.4f)\n', a, lambda_max_theo, G_optimal_theo);
end

%% === 性能报告 ===
fprintf('\n=== 详细性能报告 ===\n');
fprintf('系统参数: n=%d\n', n_nodes);
fprintf('Aloha理论最大吞吐量: %.4f\n\n', exp(-1));

fprintf('a值\t最优q0\t吞吐量λ\t尝试率G\t理论λ_max\t匹配度\t改进Aloha\n');
for a_idx = 1:length(a_values)
    result = all_results(a_idx);
    improvement = (result.best_throughput / exp(-1) - 1) * 100;
    match_percentage = (result.best_throughput / result.lambda_max_theo) * 100;
    
    fprintf('%.3f\t%.3f\t%.4f\t\t%.3f\t\t%.4f\t\t%.1f%%\t\t+%.1f%%\n', ...
            result.a, result.best_q0, result.best_throughput, result.best_G, ...
            result.lambda_max_theo, match_percentage, improvement);
end

%% === 修正的参数推荐表 ===
fprintf('\n=== 参数推荐表 ===\n');
fprintf('基于n=%d节点的CSMA参数优化建议:\n', n_nodes);
fprintf('a值范围\t推荐q0\t预期吞吐量\t备注\n');

for a_idx = 1:length(a_values)
    a_val = a_values(a_idx);
    result = all_results(a_idx);
    
    % 基于理论的经验公式
    recommended_q0 = 1 / (n_nodes * sqrt(a_val));
    
    % 根据仿真结果调整预期吞吐量
    if a_val <= 0.01
        expected_throughput = min(0.95, result.lambda_max_theo * 0.9); % 高性能场景
        remark = '高性能';
    elseif a_val <= 0.05
        expected_throughput = result.lambda_max_theo * 0.8;
        remark = '平衡性能';
    else
        expected_throughput = result.lambda_max_theo * 0.7;
        remark = '适用高延迟';
    end
    
    fprintf('%.3f\t%.3f\t%.4f\t\t%s\n', a_val, recommended_q0, expected_throughput, remark);
end

%% === 稳定性分析 ===
fprintf('\n=== 稳定性分析 ===\n');
fprintf('参数敏感性评估:\n');

for a_idx = 1:length(a_values)
    result = all_results(a_idx);
    if ~isnan(result.stable_min)
        fprintf('a=%.3f: 稳定区域 q0∈[%.3f, %.3f] (范围=%.3f)\n', ...
                result.a, result.stable_min, result.stable_max, result.stable_range);
    else
        fprintf('a=%.3f: 无稳定区域\n', result.a);
    end
end

%% === 可视化结果 ===
figure('Position', [100, 100, 1200, 800]);

% 1. 吞吐量对比
subplot(2,2,1);
colors = ['r', 'g', 'b', 'm'];
markers = ['o', 's', '^', 'd'];
for a_idx = 1:length(a_values)
    result = all_results(a_idx);
    throughput_means = mean(result.throughputs, 2);
    throughput_stds = std(result.throughputs, 0, 2);
    
    errorbar(result.q0_range, throughput_means, throughput_stds, ...
             [colors(a_idx) markers(a_idx) '-'], 'LineWidth', 1.5, ...
             'DisplayName', sprintf('a=%.3f', result.a));
    hold on;
end
xlabel('传输概率 q0');
ylabel('吞吐量 λ');
title('不同a值的吞吐量对比');
legend('show', 'Location', 'best');
grid on;

% 2. 与理论对比
subplot(2,2,2);
aloha_throughput = exp(-1) * ones(1, length(a_values));
sim_throughputs = [all_results.best_throughput];
theo_throughputs = [all_results.lambda_max_theo];

bar_data = [aloha_throughput; sim_throughputs; theo_throughputs]';
bar(bar_data);
set(gca, 'XTickLabel', arrayfun(@(x) sprintf('a=%.3f', x), a_values, 'UniformOutput', false));
ylabel('吞吐量');
title('Aloha vs CSMA仿真 vs CSMA理论');
legend('Aloha理论', 'CSMA仿真', 'CSMA理论', 'Location', 'best');
grid on;

% 3. 参数敏感性
subplot(2,2,3);
for a_idx = 1:length(a_values)
    result = all_results(a_idx);
    throughput_means = mean(result.throughputs, 2);
    throughput_ratio = throughput_means / result.best_throughput * 100;
    
    plot(result.q0_range, throughput_ratio, [colors(a_idx) '-'], 'LineWidth', 1.5, ...
         'DisplayName', sprintf('a=%.3f', result.a));
    hold on;
end
yline(95, 'k--', 'LineWidth', 1, 'Label', '95% 阈值');
xlabel('传输概率 q0');
ylabel('相对吞吐量 (%)');
title('参数敏感性分析');
legend('show', 'Location', 'best');
grid on;

% 4. 尝试率分析
subplot(2,2,4);
for a_idx = 1:length(a_values)
    result = all_results(a_idx);
    attempt_means = mean(result.attempt_rates, 2);
    plot(result.q0_range, attempt_means, [colors(a_idx) markers(a_idx) '-'], ...
         'LineWidth', 1.5, 'DisplayName', sprintf('a=%.3f', result.a));
    hold on;
end
xlabel('传输概率 q0');
ylabel('尝试率 G');
title('尝试率分析');
legend('show', 'Location', 'best');
grid on;

%% === 性能优化建议 ===
fprintf('\n=== 性能优化建议 ===\n');
for a_idx = 1:length(a_values)
    result = all_results(a_idx);
    
    fprintf('a=%.3f:\n', result.a);
    fprintf('  当前最优: q0=%.4f, λ=%.4f\n', result.best_q0, result.best_throughput);
    fprintf('  理论极限: λ=%.4f (G=%.4f)\n', result.lambda_max_theo, result.G_optimal_theo);
    
    if result.best_throughput < result.lambda_max_theo * 0.8
        fprintf('  ❌ 性能偏低,建议:\n');
        fprintf('     - 增加仿真时长: total_normal_slots = 20000\n');
        fprintf('     - 优化退避机制: 使用指数退避\n');
        fprintf('     - 检查信道状态管理逻辑\n');
    elseif result.best_throughput < result.lambda_max_theo * 0.9
        fprintf('  ⚠️  性能良好,可优化:\n');
        fprintf('     - 微调q0搜索范围\n');
        fprintf('     - 增加仿真次数\n');
    else
        fprintf('  ✅ 性能优秀\n');
    end
    fprintf('  推荐q0范围: %.4f - %.4f\n\n', result.stable_min, result.stable_max);
end

fprintf('=== 分析完成 ===\n');
相关推荐
机器学习之心2 小时前
基于双向时序卷积网络(BiTCN)与支持向量机(SVM)混合模型的时间序列预测代码Matlab源码
网络·支持向量机·matlab
MATLAB代码顾问4 小时前
MATLAB实现决策树数值预测
开发语言·决策树·matlab
民乐团扒谱机17 小时前
深入浅出理解克尔效应(Kerr Effect)及 MATLAB 仿真实现
开发语言·matlab·光学·非线性光学·克尔效应·kerr effect
leo__52019 小时前
MATLAB实现高光谱分类算法
支持向量机·matlab·分类
民乐团扒谱机1 天前
脉冲在克尔效应下的频谱展宽仿真:原理与 MATLAB 实现
开发语言·matlab·光电·非线性光学·克尔效应
yuan199971 天前
基于扩展卡尔曼滤波的电池荷电状态估算的MATLAB实现
开发语言·matlab
chao1898441 天前
多光谱图像融合:IHS、PCA与小波变换的MATLAB实现
图像处理·计算机视觉·matlab
我爱C编程1 天前
基于无六环H校验矩阵和归一化偏移minsum算法的LDPC编译码matlab性能仿真
matlab·矩阵·ldpc·无六环·归一化偏移·minsum
bubiyoushang8881 天前
使用MATLAB计算梁单元的刚度矩阵和质量矩阵
开发语言·matlab·矩阵