現(xiàn)指南)
簡(jiǎn)介Turbo碼EXIT圖迭代分析MATLAB資料包面向通信工程、信息論方向的研究生、科研人員及無(wú)線通信系統(tǒng)設(shè)計(jì)者聚焦Turbo碼性能預(yù)測(cè)與迭代解碼優(yōu)化。壓縮包共43個(gè)文件以m腳本、mat數(shù)據(jù)、pdf文獻(xiàn)和fig圖形為主總大小僅3.89MB其中m腳本覆蓋EXIT曲線計(jì)算、迭代軌跡追蹤、LLR軟信息生成、對(duì)數(shù)最大后驗(yàn)概率解碼、互信息直方圖測(cè)量與網(wǎng)格構(gòu)建等核心環(huán)節(jié)14個(gè)mat數(shù)據(jù)文件對(duì)應(yīng)不同生成多項(xiàng)式、信噪比與碼率下的仿真結(jié)果。10篇pdf文獻(xiàn)匯集外信息轉(zhuǎn)移經(jīng)典理論文章fig圖形直觀展示不同參數(shù)下EXIT特性與誤碼性能曲線。包內(nèi)代碼與數(shù)據(jù)構(gòu)成完整實(shí)驗(yàn)環(huán)境可復(fù)現(xiàn)Turbo碼EXIT迭代全過(guò)程幫助讀者理解交織器設(shè)計(jì)、編碼率選擇及軟判決解碼的相互作用也可用于驗(yàn)證算法收斂性并與理論曲線相互對(duì)照。已有253人學(xué)習(xí)下載適合希望結(jié)合代碼深入研究Turbo碼原理與工程設(shè)計(jì)的進(jìn)階學(xué)習(xí)者。1. Turbo碼EXIT圖用一條曲線和45度線的縫隙判斷迭代譯碼能不能收斂Turbo碼的迭代譯碼看著玄學(xué)兩個(gè)分量譯碼器來(lái)回傳軟信息迭代次數(shù)加碼到20次BER還是掉不下去。EXIT_TURBO這類工具要解決的就是把這個(gè)黑匣子攤開(kāi)——用外信息轉(zhuǎn)移圖EXIT圖可視化每次迭代到底交換了什么信息。橫軸是分量譯碼器拿到的先驗(yàn)互信息IA縱軸是它吐出來(lái)的外信息互信息IE。對(duì)稱Turbo碼看分量碼EXIT曲線與45度對(duì)角線的縫隙縫隙越寬迭代收斂越快曲線和對(duì)角線相交迭代直接卡死。適合剛接手Turbo碼鏈路、想快速定位迭代增益瓶頸的通信工程師也適合做Turbo/LDPC選型對(duì)比的算法同學(xué)。下面按“理論→實(shí)現(xiàn)→驗(yàn)證→避坑”往下推給出一份能直接照著跑的Python流程。2. 先搞懂三個(gè)量IA、IE和BCJR的外信息這是EXIT圖的地基2.1 互信息不是信噪比IA和IE到底在量什么EXIT圖里橫軸和縱軸都不是信噪比而是互信息這個(gè)統(tǒng)計(jì)量。給定一串LLR和它對(duì)應(yīng)的發(fā)送比特b互信息I(L;b)度量的是這串LLR對(duì)b的刻畫能力0表示完全沒(méi)信息1表示所有比特都能被判斷。實(shí)現(xiàn)上不需要求分布解析式直接蒙特卡洛均值就能估計(jì)。為什么要用互信息而不是直接用SNR或者LLR均值因?yàn)榉至孔g碼器做的是非線性操作LLR經(jīng)過(guò)前向/后向遞推后分布不再是高斯均值、方差都描述不了它與真實(shí)比特的相關(guān)程度互信息對(duì)分布形狀不敏感是少數(shù)能穩(wěn)定排序的指標(biāo)。這也是EXIT圖從論文走向工程實(shí)現(xiàn)的立身之本。符號(hào)上IA表示某個(gè)分量譯碼器的輸入先驗(yàn)LLR和“它對(duì)應(yīng)的信息比特”之間的互信息IE表示譯碼器輸出外信息LLR和這些比特之間的互信息。第一次迭代時(shí)所有分量譯碼器都沒(méi)有先驗(yàn)IA0如果信道條件好第一次迭代可能直接吐出IE0.3第二次這個(gè)0.3變成另一個(gè)分量譯碼器的IA0.3相當(dāng)于信息在兩個(gè)分量碼之間交替放大。新手最容易混淆的一點(diǎn)兩個(gè)譯碼器交換的不是后驗(yàn)LLR而是外信息Le也就是從“別人的先驗(yàn)”里剝掉之后剩下來(lái)的新增信息。后驗(yàn)LLR里既包含信道信息又包含先驗(yàn)直接拿它交換相當(dāng)于把別人說(shuō)過(guò)的話又原封不動(dòng)說(shuō)回去迭代會(huì)很快收斂到一個(gè)錯(cuò)誤結(jié)果。工程里還有一個(gè)常見(jiàn)誤區(qū)只盯著IA0和IA1兩個(gè)端點(diǎn)看。實(shí)際上0.9到0.99之間互信息漲得特別慢這段曲線對(duì)隨機(jī)樣本量最敏感經(jīng)常需要加大采樣次數(shù)才能把毛刺壓下去。EXIT曲線畫出來(lái)如果抖得像牙簽先別懷疑算法先看這段采樣量是不是不夠。2.2 對(duì)數(shù)域BCJR前向、后向、外信息怎么算BCJR是最常用的軟輸入軟輸出譯碼算法Turbo的分量譯碼器幾乎都用它。EXIT計(jì)算關(guān)心的不是硬判決結(jié)果而是每個(gè)信息比特的外信息Le。標(biāo)準(zhǔn)對(duì)數(shù)域BCJR分三步前向遞推計(jì)算alpha后向遞推計(jì)算beta最后合并出每個(gè)比特的后驗(yàn)LLR。給定遞歸系統(tǒng)卷積碼RSC作為分量碼每個(gè)時(shí)刻k的狀態(tài)轉(zhuǎn)移由輸入比特u_k決定。max-log域的遞推寫成alpha[k][s] max( alpha[k-1][s] gamma[k][s][s] ) beta[k][s] max( beta[k1][s] gamma[k1][s][s] )分支度量gamma只和本時(shí)刻的系統(tǒng)比特u_k、校驗(yàn)比特p_k、信道LLR以及輸入先驗(yàn)LLR有關(guān)gamma[k] L_a(u_k) L_ch_sys(u_k) L_ch_par(p_k)這里的L_a(u_k)在u_k1時(shí)取先驗(yàn)LLR的值u_k0時(shí)取0信道項(xiàng)同理。最后對(duì)u_k做max-log合并得到后驗(yàn)LLR外信息就是再扣掉信道和先驗(yàn)的貢獻(xiàn)L_e L_app - L_ch_sys - L_a這正是“外信息”名字的由來(lái)它是這個(gè)分量譯碼器本輪新拿出來(lái)的信息。寫代碼時(shí)alpha、beta、gamma全部用對(duì)數(shù)域路徑不存在用一個(gè)大負(fù)數(shù)如-1e9代替。max-log不計(jì)算logsumexp和log-MAP相比性能差零點(diǎn)幾個(gè)dB但實(shí)現(xiàn)簡(jiǎn)單得多出問(wèn)題也好排查。EXIT圖本身就是看趨勢(shì)和門限用max-log足夠。2.3 把分量譯碼器當(dāng)黑匣子EXIT掃描的“合成先驗(yàn)”思路把BCJR當(dāng)黑匣子EXIT掃描的核心思想就一句話不仿真真實(shí)接收幀而是人為構(gòu)造一批先驗(yàn)LLR讓它們的互信息恰好等于想掃描的IA然后喂給BCJR統(tǒng)計(jì)輸出外信息的互信息IE。先驗(yàn)LLR用高斯近似構(gòu)造給定標(biāo)準(zhǔn)差sigma_a讓LLR均值等于sigma_a平方的一半、符號(hào)隨發(fā)送比特翻轉(zhuǎn)即L_a (sigma_a^2/2)·(2b-1) n。這樣生成的LLR分布和真實(shí)AWGN信道下的LLR分布一致I(L_a;b)大小完全由sigma_a決定用數(shù)值方法求反函數(shù)就能得到每個(gè)IA對(duì)應(yīng)的sigma_a。對(duì)很多個(gè)IA重復(fù)一遍“構(gòu)造先驗(yàn)、跑BCJR、統(tǒng)計(jì)IE”就得到一整條EXIT曲線。這個(gè)做法把迭代譯碼的復(fù)雜行為拆成兩次獨(dú)立掃描第一次掃分量1的IE曲線第二次掃分量2的IE曲線兩條曲線之間的相對(duì)位置決定整體收斂行為。軌跡則是把兩條曲線上的點(diǎn)交替連接起來(lái)模擬真實(shí)迭代過(guò)程。我一般先掃曲線、再跑軌跡、最后才做完整誤碼率仿真因?yàn)镋XIT判斷收斂門限的成本遠(yuǎn)低于誤碼率仿真不需要跑幾十上百幀只要每點(diǎn)多取幾個(gè)隨機(jī)樣本平均就行。黑匣子思路也方便換算法以后把BCJR換成log-MAP或查表SISO其他代碼不用動(dòng)只換這個(gè)函數(shù)。如果兩個(gè)分量碼完全相同兩條EXIT曲線會(huì)重合圖退化為一條曲線和45度對(duì)角線之間的開(kāi)口。判斷標(biāo)準(zhǔn)是曲線是否始終位于對(duì)角線之上是迭代能收斂和對(duì)角線相交交點(diǎn)就是信息交換停滯點(diǎn)。分量碼不同、或?qū)ΨQTurbo做了打孔、或使用非對(duì)稱交織時(shí)兩條曲線形狀不同軌跡在兩條曲線之間走階梯隧道面積才是收斂速度的度量。這兩種情形對(duì)應(yīng)EXIT_TURBO里最常見(jiàn)的兩類圖畫法后面的實(shí)現(xiàn)同時(shí)兼容兩者。3. 自己動(dòng)手復(fù)現(xiàn)EXIT_TURBO分量碼、BCJR和掃描腳本3.1 參數(shù)表生成多項(xiàng)式、交織器、信噪比怎么定EXIT圖能不能說(shuō)明問(wèn)題一半取決于參數(shù)選得對(duì)不對(duì)。我常用的起點(diǎn)配置列在下面照著抄能省很多調(diào)試時(shí)間。參數(shù)項(xiàng)推薦值說(shuō)明分量碼RSC(2,1,3)反饋多項(xiàng)式111八進(jìn)制7、前向多項(xiàng)式101八進(jìn)制5經(jīng)典組合曲線形狀和論文可比交織長(zhǎng)度N100010000短幀看趨勢(shì)長(zhǎng)幀驗(yàn)證定量門限N太小時(shí)EXIT曲線毛刺多、軌跡偏散交織器固定種子偽隨機(jī)每幀換交織器會(huì)讓結(jié)果是平均行為固定種子便于復(fù)現(xiàn)和排錯(cuò)信道AWGN、BPSK不要在EXIT掃描里直接加衰落那是另一套統(tǒng)計(jì)先確認(rèn)AWGN下曲線再擴(kuò)展先驗(yàn)掃描點(diǎn)IA0.010.99約1015個(gè)點(diǎn)IA大于0.95的區(qū)間至少重復(fù)采樣3次取平均BCJR實(shí)現(xiàn)max-log和log-MAP差0.10.2dB曲線定量夠用實(shí)現(xiàn)簡(jiǎn)單采樣量每點(diǎn)隨機(jī)樣本20000以上互信息是統(tǒng)計(jì)量樣本少了曲線會(huì)抖選RSC(7,5)是因?yàn)樗姆答伓囗?xiàng)式讓碼字距離譜拉開(kāi)EXIT曲線在中等IA區(qū)有明顯“臺(tái)階”隧道的開(kāi)閉變化看得清楚。交織長(zhǎng)度別一上來(lái)就上十萬(wàn)先拿N1024把整個(gè)流程跑通。信道信噪比按Es/N0給BPSK實(shí)信道下Es1碼率不在這里折算。對(duì)稱Turbo碼碼率1/2時(shí)Es/N0約等于Eb/N0減3dB掃圖時(shí)直接掃Es/N0在02dB這一段基本就能看到隧道從關(guān)閉到完全打開(kāi)的全過(guò)程。3.2 RSC編碼器和max-log BCJR的最小實(shí)現(xiàn)先寫分量碼。RSC編碼器用狀態(tài)轉(zhuǎn)移表驅(qū)動(dòng)比逐位算反饋更直觀也方便后面BCJR直接復(fù)用同一張表。下面的實(shí)現(xiàn)不做尾比特收尾EXIT掃描用的是無(wú)限長(zhǎng)循環(huán)卷積近似實(shí)際仿真再加尾比特就是。import numpy as np def build_rsc_trellis(feedback_poly, forward_poly): 構(gòu)造RSC分量碼的狀態(tài)轉(zhuǎn)移表。 feedback_poly / forward_poly 是比特串左邊為最高位。 例: 111 對(duì)應(yīng)八進(jìn)制7101 對(duì)應(yīng)八進(jìn)制5。 返回 dict: 狀態(tài)數(shù), next[state][u], out[state][u]。 out 高比特系統(tǒng)位低比特校驗(yàn)位系統(tǒng)位輸入u。 m len(feedback_poly) - 1 # 寄存器長(zhǎng)度 n_states 1 m # 狀態(tài)數(shù) fb_mask int(feedback_poly[1:], 2) # 反饋抽頭去掉最高位1 ff_mask int(forward_poly[1:], 2) # 前向抽頭 next_s np.zeros((n_states, 2), dtypenp.int64) out_w np.zeros((n_states, 2), dtypenp.int64) for s in range(n_states): for u in (0, 1): # 反饋位 輸入 異或 寄存器反饋抽頭的奇偶校驗(yàn) fb u ^ (bin(s fb_mask).count(1) 1) # 新?tīng)顟B(tài)寄存器右移反饋位進(jìn)最高位 ns (s 1) | (fb (m - 1)) # 校驗(yàn)位 前向抽頭的奇偶校驗(yàn) par bin(s ff_mask).count(1) 1 next_s[s, u] ns out_w[s, u] (u 1) | par return {states: n_states, next: next_s, out: out_w} def rsc_encode(info, trellis): RSC編碼返回系統(tǒng)位和校驗(yàn)位。狀態(tài)從0出發(fā)不做尾比特收尾。 sys_bits np.zeros(len(info), dtypeint) par_bits np.zeros(len(info), dtypeint) state 0 for k, u in enumerate(info): sys_bits[k] u par_bits[k] trellis[out][state, u] 1 state trellis[next][state, u] return sys_bits, par_bits說(shuō)明build_rsc_trellis里bin(s fb_mask).count(1)取寄存器中和反饋抽頭對(duì)應(yīng)位的奇偶這就是遞歸結(jié)構(gòu)的關(guān)鍵。前向抽頭ff_mask只決定校驗(yàn)位輸出不影響狀態(tài)轉(zhuǎn)移。兩個(gè)函數(shù)合起來(lái)就是完整的分量碼編碼器。rsc_encode里sys_bits就是info本身因?yàn)橄到y(tǒng)碼的系統(tǒng)位直接透?jìng)鲗懗鰜?lái)是為了讓BCJR側(cè)理解信息比特和校驗(yàn)比特的對(duì)應(yīng)關(guān)系。接下來(lái)是核心的max-log BCJR。它吃進(jìn)去系統(tǒng)位信道LLR、校驗(yàn)位信道LLR和先驗(yàn)LLR吐出來(lái)外信息Le。符號(hào)約定在注釋里寫清楚比特1對(duì)應(yīng)發(fā)送符號(hào)-1比特0對(duì)應(yīng)1信道LLR按log(P(b1)/P(b0))定義。只要這個(gè)約定不換下面所有公式都成立。def bcjr_extrinsic(L_sys, L_par, L_prior, trellis): max-log BCJR輸出外信息 Le。 符號(hào)約定: 比特1 - 發(fā)送符號(hào) -1比特0 - 1。 信道LLR L log(P(b1)/P(b0))可由 L -2*y/sigma_n^2 得到。 L_prior 是另一個(gè)分量譯碼器給過(guò)來(lái)的先驗(yàn)LLR。 n len(L_sys) S trellis[states] nxt, out trellis[next], trellis[out] NEG -1e9 # 前向遞推 alpha[k][s] alpha np.full((n 1, S), NEG) alpha[0, 0] 0.0 for k in range(n): for s_prev in range(S): base alpha[k, s_prev] if base NEG / 2: continue for u in (0, 1): s_cur nxt[s_prev, u] # 分支度量先驗(yàn)系統(tǒng)信道校驗(yàn)信道u 和校驗(yàn)位為0時(shí)該項(xiàng)為0 gam L_prior[k] * u L_sys[k] * u L_par[k] * (out[s_prev, u] 1) v base gam if v alpha[k 1, s_cur]: alpha[k 1, s_cur] v # 后向遞推 beta[k][s] beta np.full((n 1, S), NEG) beta[n, 0] 0.0 for k in range(n - 1, -1, -1): for s_prev in range(S): for u in (0, 1): s_cur nxt[s_prev, u] gam L_prior[k] * u L_sys[k] * u L_par[k] * (out[s_prev, u] 1) v beta[k 1, s_cur] gam if v beta[k, s_prev]: beta[k, s_prev] v # 逐比特合并輸出外信息 Le np.zeros(n) for k in range(n): num, den NEG, NEG for s_prev in range(S): for u in (0, 1): s_cur nxt[s_prev, u] gam L_prior[k] * u L_sys[k] * u L_par[k] * (out[s_prev, u] 1) metric alpha[k, s_prev] gam beta[k 1, s_cur] if u 1: num metric if metric num else num else: den metric if metric den else den # 后驗(yàn)減掉系統(tǒng)信道和先驗(yàn)留下外信息 Le[k] (num - den) - L_sys[k] - L_prior[k] return Le這段代碼不是最優(yōu)的但它是這整篇文章里最值得抄的alpha和beta用同一個(gè)trellis表分支度量只依賴本時(shí)刻的LLR和輸入/輸出比特不會(huì)有表驅(qū)動(dòng)的索引錯(cuò)位。復(fù)雜度O(n·S·2)N10000、S4時(shí)一次BCJR在毫秒級(jí)。如果以后換log-MAP只需要把max替換成logsumexp函數(shù)接口和符號(hào)約定都不用動(dòng)。注意兩個(gè)容易寫錯(cuò)的地方一是前向遞推里alpha[k1]可能被多條路徑更新必須取max而不是覆蓋二是最后外信息那里減的是L_sys[k]和L_prior[k]不是減gamma因?yàn)間amma里面L_par[k]那部分是本次新增校驗(yàn)信息不能減掉。我早期實(shí)現(xiàn)就是在這里多減了一項(xiàng)結(jié)果IE曲線在高IA區(qū)整體往下塌排查了兩天才發(fā)現(xiàn)。3.3 用高斯先驗(yàn)掃描一條IE曲線互信息估計(jì)與J函數(shù)互信息的估計(jì)不需要求概率密度直接用蒙特卡洛期望。對(duì)每個(gè)樣點(diǎn)(b, L)I 1 - E[log2(1 exp(-c·L))]其中c1當(dāng)b1、c-1當(dāng)b0。數(shù)值上要寫成logaddexp直接算exp很容易溢出成inf。def estimate_mi(bits, llr): 蒙特卡洛估計(jì) I(L;b)。bits 是0/1數(shù)組。 c 2.0 * bits - 1.0 # 1-1, 0--1 return 1.0 - np.mean(np.logaddexp(0.0, -c * llr) / np.log(2.0)) def j_of_sigma(sigma, rng, n_samples20000): 給定高斯LLR的標(biāo)準(zhǔn)差sigma估計(jì)互信息。 bits rng.integers(0, 2, n_samples) L 0.5 * sigma**2 * (2 * bits - 1) sigma * rng.standard_normal(n_samples) return estimate_mi(bits, L) def sigma_from_ia(ia, rng, sigma_max20.0, n_samples20000): 二分搜索找到標(biāo)準(zhǔn)差sigma使得 J(sigma)ia。 lo, hi 1e-4, sigma_max for _ in range(40): mid 0.5 * (lo hi) if j_of_sigma(mid, rng, n_samples) ia: lo mid else: hi mid return 0.5 * (lo hi)參數(shù)說(shuō)明estimate_mi中c2·bits-1把0/1映射成-1/1和前面LLR的符號(hào)約定咬合。J函數(shù)是EXIT理論里的標(biāo)準(zhǔn)工具很多實(shí)現(xiàn)直接用多項(xiàng)式近似我這里用蒙特卡洛二分雖然慢一些但完全透明不會(huì)因?yàn)榻乒絽?shù)抄錯(cuò)而翻車。n_samples20000時(shí)J函數(shù)估計(jì)的標(biāo)準(zhǔn)差大約在千分位足以支撐曲線判斷如果掃到IA0.95把n_samples提到50000更穩(wěn)。3.4 把兩條曲線、對(duì)角線和軌跡畫到一張圖上掃描主函數(shù)一次跑出兩個(gè)分量譯碼器的IE曲線。關(guān)鍵點(diǎn)是第二分量譯碼器的系統(tǒng)LLR和先驗(yàn)LLR必須按交織器重排校驗(yàn)LLR是交織后比特流的校驗(yàn)輸出。這樣才能反映Turbo譯碼器里真實(shí)的信號(hào)路徑。def scan_exit_pair(poly1, poly2, block_len, esno_db, ia_list, seed2024): 兩個(gè)分量碼各掃一條IE曲線。 poly1/poly2 形如 (反饋多項(xiàng)式比特串, 前向多項(xiàng)式比特串)。 esno_db 是 Es/N0 的 dB 值BPSK 實(shí)信道。 tr1 build_rsc_trellis(*poly1) tr2 build_rsc_trellis(*poly2) rng np.random.default_rng(seed) info rng.integers(0, 2, block_len) interleaver rng.permutation(block_len) # 固定交織器 _, p1 rsc_encode(info, tr1) _, p2 rsc_encode(info[interleaver], tr2) esno_lin 10 ** (esno_db / 10.0) var_llr 8.0 * esno_lin # BPSK雙測(cè)噪聲下信道LLR方差 mu_llr 0.5 * var_llr # LLR均值 # 一次生成整幀信道LLR掃描多個(gè)IA時(shí)保持不變 L_sys mu_llr * (2 * info - 1) np.sqrt(var_llr) * rng.standard_normal(block_len) L_par1 mu_llr * (2 * p1 - 1) np.sqrt(var_llr) * rng.standard_normal(block_len) L_par2 mu_llr * (2 * p2 - 1) np.sqrt(var_llr) * rng.standard_normal(block_len) ies1, ies2 [], [] for ia in ia_list: sigma_a sigma_from_ia(ia, rng) L_prior 0.5 * sigma_a**2 * (2 * info - 1) sigma_a * rng.standard_normal(block_len) # 分量1 Le1 bcjr_extrinsic(L_sys, L_par1, L_prior, tr1) ies1.append(estimate_mi(info, Le1)) # 分量2系統(tǒng)LLR和先驗(yàn)都要按交織器重排 L_prior_i L_prior[interleaver] L_sys_i L_sys[interleaver] Le2 bcjr_extrinsic(L_sys_i, L_par2, L_prior_i, tr2) ies2.append(estimate_mi(info[interleaver], Le2)) return np.array(ies1), np.array(ies2)調(diào)用方式ia_list取0.01到0.99的15個(gè)點(diǎn)poly1和poly2都傳(111,101)時(shí)就是對(duì)稱Turbo碼的掃描。執(zhí)行一次大約幾秒瓶頸在sigma_from_ia的二分蒙特卡洛。嫌慢的話可以把J函數(shù)換成十Brink的多項(xiàng)式近似表曲線會(huì)平滑一些但先跑通這套再說(shuō)。繪圖用matplotlib。對(duì)稱Turbo碼時(shí)兩條IE曲線重合只畫一條曲線加對(duì)角線即可非對(duì)稱分量碼才畫兩條曲線。import matplotlib.pyplot as plt def draw_exit(ia_list, ies1, ies2, trajNone): 畫EXIT曲線。對(duì)稱分量碼時(shí)曲線重合另一分量由對(duì)角線隱含。 plt.figure(figsize(6, 6)) plt.plot(ia_list, ies1, b-o, label分量1 IE) if not np.allclose(ies1, ies2, atol0.02): plt.plot(ia_list, ies2, r-s, label分量2 IE) plt.plot([0, 1], [0, 1], k--, label對(duì)角線) if traj is not None: tx, ty zip(*traj) plt.plot(tx, ty, g.-, lw1, label迭代軌跡) plt.xlabel(I_A1 / I_E2) plt.ylabel(I_E1 / I_A2) plt.xlim(0, 1) plt.ylim(0, 1) plt.grid(True) plt.legend() plt.show()提示畫圖前先用np.allclose判斷兩條曲線是否重合。很多對(duì)稱Turbo碼因?yàn)榻豢椘骱筒蓸釉肼晝蓷l曲線會(huì)有千分位級(jí)別的差異這不代表它們不同閾值放0.02比較穩(wěn)不要看到兩條幾乎重疊的線就開(kāi)始分析“隧道寬度”。4. 從EXIT曲線到收斂門限和蒙特卡洛仿真互相印證4.1 EXIT圖告訴你的三件事門限、增益、錯(cuò)誤地板一張EXIT圖能回答三個(gè)問(wèn)題能不能收斂、收斂多快、會(huì)不會(huì)卡死。曲線與對(duì)角線全部不相交且隧道明顯打開(kāi)說(shuō)明迭代譯碼能一路把互信息推到接近1隧道在某處閉合說(shuō)明信息交換在那里停住誤碼率會(huì)掉不下去。隧道越寬完成收斂所需的迭代次數(shù)越少。第三個(gè)問(wèn)題容易被忽略有些曲線在IA接近1時(shí)和對(duì)角線靠得很近但沒(méi)有相交此時(shí)互信息推進(jìn)極慢實(shí)際表現(xiàn)就是BER曲線出現(xiàn)地板迭代次數(shù)從6次加到20次幾乎不漲。把EXIT圖和誤碼率曲線放在一起看才有工程意義。EXIT只說(shuō)“有沒(méi)有路”不說(shuō)“路上車多不多”。同一張圖里迭代4次和迭代8次的軌跡差異直接對(duì)應(yīng)仿真里迭代次數(shù)的增益。我做鏈路預(yù)算時(shí)習(xí)慣先掃4張不同信噪比的EXIT圖把隧道開(kāi)閉的Es/N0范圍定下來(lái)然后再只仿真這個(gè)范圍內(nèi)的少數(shù)幾個(gè)點(diǎn)蒙卡仿真時(shí)長(zhǎng)能省一大半。4.2 用隧道開(kāi)閉預(yù)測(cè)Er/N0門限再用仿真驗(yàn)證預(yù)測(cè)門限的操作很固定對(duì)一個(gè)Es/N0候選值掃描EXIT曲線看曲線和對(duì)角線是否還有縫隙。二分這個(gè)Es/N0就能把“理論收斂門限”卡到0.1dB內(nèi)。下面是批量判斷門限的骨架代碼。def predict_threshold(poly1, poly2, block_len, ia_list, esno_range, seed2024): 掃描一系列Es/N0返回每個(gè)點(diǎn)EXIT是否開(kāi)口。 開(kāi)口定義: 掃出的IE曲線在全部IA點(diǎn)上均不低于對(duì)角線-0.005。 results [] for esno_db in esno_range: ies1, ies2 scan_exit_pair(poly1, poly2, block_len, esno_db, ia_list, seed) # 對(duì)稱分量碼用IE曲線非對(duì)稱用兩條曲線交叉判別這里給對(duì)稱版 opened np.all(ies1 np.array(ia_list) - 0.005) results.append((esno_db, opened, float(np.min(ies1 - np.array(ia_list))))) return results說(shuō)明判斷“開(kāi)口”不能只看最后一個(gè)IA點(diǎn)要在所有掃描點(diǎn)上做比較。0.005的松弛量用來(lái)吸收蒙特卡洛估計(jì)噪聲設(shè)太小會(huì)把本來(lái)開(kāi)口的曲線誤判成閉合。跑完這個(gè)批量掃描后再把門限附近兩個(gè)Es/N0的軌跡畫出來(lái)確認(rèn)軌跡不是貼在對(duì)角線上慢慢爬——那說(shuō)明有限塊長(zhǎng)效應(yīng)已經(jīng)把實(shí)際門限推高了。我常用的配置里RSC(7,5)對(duì)稱Turbo碼、N4096、碼率1/2時(shí)EXIT預(yù)測(cè)的門限大約落在Es/N0-0.5dB到0.5dB之間把Es/N0換算成Eb/N0還要加3dB。這個(gè)值和最終蒙卡仿真BER曲線開(kāi)始明顯下降的位置能對(duì)上0.3dB左右。對(duì)不上就先別懷疑EXIT回頭查信號(hào)功率歸一化BPSK的Es是1還是0.5取決于你有沒(méi)有把碼率折算進(jìn)符號(hào)能量這一項(xiàng)最容易把門限整體平移。4.3 軌跡為什么走“Z字”有限塊長(zhǎng)和交織器的作用軌跡是實(shí)際迭代過(guò)程在EXIT圖上的投影。理想情況下軌跡交替落在兩條曲線上形成規(guī)則階梯。實(shí)際畫出來(lái)卻是一個(gè)個(gè)Z字第一輪IE到了0.3第二輪IA卻只有0.25反而退回去了。這不是算法錯(cuò)了是有限塊長(zhǎng)下互信息估計(jì)的方差在起作用。EXIT曲線是幾千幀的平均行為真實(shí)譯碼每次只迭代一幀這一幀的先驗(yàn)分布不可能正好落在平滑曲線上交織器長(zhǎng)度越短Z字越明顯軌跡甚至可能穿到曲線外面。交織器對(duì)軌跡形狀的影響比很多人以為的都大。固定交織器時(shí)軌跡只有一條換一個(gè)交織器軌跡會(huì)上下抖動(dòng)但抖動(dòng)的包絡(luò)仍然貼著EXIT曲線。用S-random交織器能減小抖動(dòng)因?yàn)樗尳豢椙昂蟮男畔⒈忍鼐嚯x拉開(kāi)外信息在幀內(nèi)更均勻。我這里給一個(gè)判斷標(biāo)準(zhǔn)軌跡的平均斜率明顯小于曲線斜率時(shí)說(shuō)明分量譯碼器沒(méi)有有效利用先驗(yàn)優(yōu)先檢查交織器是否是純隨機(jī)排列、以及是不是忘了重排系統(tǒng)LLR。純隨機(jī)交織在塊長(zhǎng)小于1000時(shí)會(huì)讓軌跡發(fā)散得很難看這也是為什么我建議一開(kāi)始就用N10000而不是N256。5. Turbo碼EXIT圖避坑指南5個(gè)常見(jiàn)翻車現(xiàn)場(chǎng)5.1 現(xiàn)象一曲線打開(kāi)隧道仿真卻不收斂現(xiàn)象EXIT圖上IE曲線明顯高于對(duì)角線按這個(gè)門限跑誤碼率仿真BER卻一直掉不下去。原因EXIT掃描用的是理想化高斯先驗(yàn)每個(gè)比特的先驗(yàn)LLR獨(dú)立同分布真實(shí)譯碼器里的先驗(yàn)來(lái)自上一輪分量譯碼器幀內(nèi)各比特質(zhì)量并不一致交織器還會(huì)讓相關(guān)性在迭代中累積。另一種可能是你把ES/N0和EB/N0搞混了對(duì)稱Turbo碼碼率1/2Es/N0要減3dB才是Eb/N0門限套錯(cuò)信號(hào)能量自然全對(duì)不上。解決先檢查信噪比定義是否一致再在EXIT圖里疊加真實(shí)軌跡而不是只看曲線。軌跡如果鉆到對(duì)角線下面說(shuō)明有限塊長(zhǎng)把實(shí)際收斂條件推高了把塊長(zhǎng)加大或者換S-random交織器重掃。5.2 現(xiàn)象二IE曲線在低IA區(qū)域掉頭向下現(xiàn)象IA從0開(kāi)始增長(zhǎng)時(shí)IE曲線先上升然后在IA大概0.1到0.2之間回落形成一個(gè)小鼓包接下來(lái)又重新上升。原因低IA區(qū)間通常出現(xiàn)在低信噪比此時(shí)信道LLR的方差很大max-log BCJR里alpha和beta的最大值接近且大量路徑metric都接近max近似損失嚴(yán)重。另一個(gè)常見(jiàn)原因是分支度量里漏了校驗(yàn)LLR項(xiàng)只加系統(tǒng)信息BCJR在高噪聲下輸出信息量反而被先驗(yàn)干擾。解決把max-log換成正則化后的log-MAPlogsumexp實(shí)現(xiàn)或者把NEG從-1e9改到-1e4以下同時(shí)檢查是否有路徑被錯(cuò)誤剪掉。如果換log-MAP后曲線正常說(shuō)明就是max近似問(wèn)題如果還掉頭回查gamma公式里L(fēng)_par[k]那項(xiàng)有沒(méi)有乘校驗(yàn)位。5.3 現(xiàn)象三軌跡和EXIT曲線對(duì)不上軌跡明顯偏低現(xiàn)象軌跡點(diǎn)和曲線差0.1以上而且每次迭代都穩(wěn)定偏低不是隨機(jī)抖動(dòng)。原因大概率是第二分量譯碼器的LLR重排錯(cuò)了。Turbo碼第一分量處理原序第二分量處理交織序。分量2的系統(tǒng)LLR要取L_sys[interleaver]先驗(yàn)要取L_prior[interleaver]校驗(yàn)位是交織后比特流編碼出來(lái)的。任何一處直接用了原序數(shù)組第二分量等于在譯另一段數(shù)據(jù)軌跡必然塌。解決打印幾個(gè)位置驗(yàn)證L_sys_i[k]對(duì)應(yīng)的真實(shí)比特是info[interleaver][k]p2[k]是info[interleaver][k]的校驗(yàn)輸出。用一個(gè)幾十比特的小幀人工核對(duì)前5個(gè)比特確認(rèn)重排關(guān)系再跑長(zhǎng)幀。5.4 現(xiàn)象四曲線整體和論文對(duì)不上形狀一樣但平移了現(xiàn)象曲線形狀完全正常整體上下平移或者左右平移半個(gè)dB。原因除了信噪比定義外最常出現(xiàn)在LLR符號(hào)約定。論文里常用比特0對(duì)應(yīng)1也有用比特0對(duì)應(yīng)-1的你按比特1對(duì)應(yīng)-1寫了代碼去對(duì)比按反約定畫的論文曲線互信息是相同的因?yàn)镮(L;b)I(-L;b)但它們內(nèi)部的信道LLR構(gòu)造不同導(dǎo)致Es/N0的換算差一個(gè)常數(shù)。此外生成多項(xiàng)式比特串的最左位是寄存器輸入還是反饋位的含義不同教材畫法也不一樣直接抄八進(jìn)制數(shù)沒(méi)核對(duì)抽頭位置曲線左右平移幾個(gè)dB不奇怪。解決先用一個(gè)已知的簡(jiǎn)單RSC(7,5)和N10000跑出曲線和論文圖肉眼對(duì)比開(kāi)關(guān)隧道的位置如果只是平移查Es/N0和Eb/N0換算如果是斜率不同查抽頭掩碼是int(poly[1:],2)還是漏了最高位如果完全錯(cuò)位把比特符號(hào)約定和多項(xiàng)式定義打印出來(lái)逐項(xiàng)核對(duì)。5.5 現(xiàn)象五EXIT圖說(shuō)明能收斂BER卻卡在錯(cuò)誤地板現(xiàn)象隧道打開(kāi)得很明顯但仿真在BER1e-4左右出現(xiàn)地板增加迭代次數(shù)也不改善。原因EXIT圖假設(shè)編碼序列無(wú)限長(zhǎng)且每個(gè)時(shí)刻等價(jià)。實(shí)際Turbo碼有網(wǎng)格收尾問(wèn)題尾比特占的比例在短幀時(shí)不可忽略另一個(gè)高頻原因是分量碼的最小距離不夠或者交織器讓低重量碼字成對(duì)出現(xiàn)錯(cuò)誤地板由碼字距離譜決定EXIT圖不直接反映這部分。還有一種情況是校驗(yàn)位被打孔后第二分量碼等效碼率升高而你掃描時(shí)沒(méi)用打孔后的校驗(yàn)序列。解決先確認(rèn)掃描和仿真用同一套打孔圖樣。再做一次不同塊長(zhǎng)的仿真塊長(zhǎng)翻倍地板下降說(shuō)明是距離譜問(wèn)題這時(shí)EXIT圖再怎么優(yōu)化也沒(méi)用得改分量碼或加CRC輔助。最后檢查尾部比特要仿真就做完整收尾要掃描就用周期卷積近似兩者不要混用。6. 進(jìn)階用EXIT圖做碼率匹配和交織器設(shè)計(jì)少走彎路EXIT圖最值錢的能力不是“事后驗(yàn)證”而是“事前選型”。我在做Turbo碼打孔設(shè)計(jì)時(shí)會(huì)先用EXIT圖掃不同打孔圖樣下的兩條曲線看它們是否仍然保持隧道開(kāi)口。常見(jiàn)做法是固定分量碼把校驗(yàn)位按2:1的周期打孔掃出來(lái)如果第二分量曲線明顯下沉、和對(duì)角線提前相交就換打孔位置或改用非對(duì)稱分量碼。這個(gè)工作放到誤碼率仿真里做每一個(gè)打孔圖樣都要跑幾十幀時(shí)間成本差一個(gè)數(shù)量級(jí)。交織器設(shè)計(jì)也可以用EXIT軌跡來(lái)挑。同一組分量碼和打孔圖樣換S-random交織器和純隨機(jī)交織器軌跡的離散程度完全不同。我一般畫軌跡云的包絡(luò)把同一幀長(zhǎng)度下多個(gè)交織器的軌跡疊加包絡(luò)窄說(shuō)明交織器對(duì)外信息的散布效果好。這個(gè)判斷比單純看交織距離譜更接近迭代譯碼的真實(shí)行為。還有一個(gè)進(jìn)階用法是給高階調(diào)制做比特度量匹配。Turbo碼配16QAM或64QAM時(shí)解映射器輸出的是比特LLR映射方式不同導(dǎo)致EXIT曲線形狀差異很大。先在BPSK下確認(rèn)分量碼本身沒(méi)問(wèn)題再換成目標(biāo)調(diào)制解調(diào)器的LLR輸入端做掃描隧道還能不能開(kāi)直接決定要不要加比特交織器。這一步能避免把時(shí)間浪費(fèi)在注定沒(méi)有迭代增益的調(diào)制方案上。這套流程走完我有兩個(gè)習(xí)慣值得保留第一任何新Turbo碼結(jié)構(gòu)先畫EXIT再上板曲線開(kāi)口是仿真的入場(chǎng)券省下的都是血淚時(shí)間第二所有掃描代碼固定隨機(jī)種子論文圖、仿真結(jié)果和回讀復(fù)現(xiàn)都對(duì)同一份隨機(jī)源出問(wèn)題時(shí)不至于懷疑是隨機(jī)數(shù)在搗亂。EXIT圖不是萬(wàn)能的它在塊長(zhǎng)短、打孔重、距離譜差的場(chǎng)景會(huì)給出偏樂(lè)觀的答案但作為第一道檢查關(guān)卡它是我調(diào)試Turbo碼鏈路時(shí)最后悔沒(méi)有早點(diǎn)用上的工具。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取