"""ex02whitevsrandomwalk.py — 第 1、3 章 白噪声 vs 随机游走 目标:用 DFA 算两条性质截然不同的序列,验证 H 的物理含义: 白噪声增量:H ≈ 0.5(无长记忆) 随机游走(累积和)profile:H → 1.0(强持久) 并画出 F(n) 双对数标度图,肉眼验证 F(n) n^H。 对应教程:tutorials/01-environment.md 1.4 节、tutorials/03-dfa-principles.md。 运行: python ex02whitevsrandomwalk.
"""ex02_white_vs_randomwalk.py — 第 1、3 章 白噪声 vs 随机游走
目标:用 DFA 算两条性质截然不同的序列,验证 H 的物理含义:
对应教程:tutorials/01-environment.md 1.4 节、tutorials/03-dfa-principles.md。
运行:
python ex02_white_vs_randomwalk.py
"""
import numpy as np
import fathon
from fathon import fathonUtils as fu
import matplotlib.pyplot as plt
def run_dfa(profile, wins, label):
"""对单条 profile 跑 DFA,返回 (n, F, H)。"""
dfa = fathon.DFA(profile)
n, F = dfa.computeFlucVec(wins, revSeg=True, polOrd=1)
H, _ = dfa.fitFlucVec(verbose=False)
print(f"{label}: H = {H:.4f}")
return n, F, H
def main():
np.random.seed(42)
N = 10000
# 序列 A:白噪声增量 white = np.random.randn(N) profile_white = fu.toAggregated(white) # 序列 B:随机游走(对增量再做一次累积和,profile 近似布朗运动) rw = np.cumsum(np.random.randn(N)) profile_rw = fu.toAggregated(rw) # 公共窗口设置:窗口上限取 N/4,保证每窗口至少 4 段(教程第 8 章经验) wins = fu.linRangeByStep(10, N // 4) n_w, F_w, H_w = run_dfa(profile_white, wins, "白噪声") n_r, F_r, H_r = run_dfa(profile_rw, wins, "随机游走") # ── 可视化 F(n) 双对数图 ── fig, ax = plt.subplots(figsize=(8, 5)) ax.loglog(n_w, F_w, 'o-', label=f'白噪声 H={H_w:.3f}', markersize=3) ax.loglog(n_r, F_r, 's-', label=f'随机游走 H={H_r:.3f}', markersize=3) # 拟合参考线:F(n) = exp(intercept) * n^H for n_arr, F_arr, H, color in [(n_w, F_w, H_w, 'C0'), (n_r, F_r, H_r, 'C1')]: ref = F_arr[0] * (n_arr / n_arr[0]) ** H ax.loglog(n_arr, ref, '--', color=color, alpha=0.4) ax.set_xlabel('窗口大小 n') ax.set_ylabel('波动函数 F(n)') ax.set_title('DFA 双对数标度图') ax.legend() ax.grid(True, which='both', alpha=0.3) plt.tight_layout() plt.show() # ── 结论解读 ── print("\n解读:") print(f" 白噪声 H={H_w:.3f} → 无长记忆(≈ 0.5)") print(f" 随机游走 H={H_r:.3f} → 强持久(→ 1.0)")
if name == "main":
main()