Turbo编译码Matlab仿真解读 (2)-- WuYufei_matlab

3.3 前向度量计算

前向度量 α 计算由双循环组成:

内循环:以所有状态为循环:state = 1 : 2^m

外循环:以所有信息数量为循环:k = 2 : L_total + 1

                                      

图5 前向度量算法示意图

即  \alpha _{l+1}^*(s)  状态 为上一时刻状态的总和:  

\alpha _{l+1}(s) = \sum_{s'\in \sigma _l}^{} \gamma _l(s'\, ,\, s)\alpha _l(s')                                                              (1)

先计算输入 d_k = 0时:

% Log_MAP算法计算

gamma( last_state(state2,1) ) = ( -rec_s(2*k-3) + rec_s(2*k-2) * last_out(state2,2) )
                                                   - log(1+exp(L_a(k-1)));

再计算输入 d_k = 1时: 

 gamma(last_state(state2,2)) = (rec_s(2*k-3) + rec_s(2*k-2) * last_out(state2,4))
                                                   + L_a(k-1) - log(1+exp(L_a(k-1))); 

log_map算法目前用的不多,由于计算量较大,主流均采用 max-log-map计算,这里只给出计算公式,详细算法不再推导。



分支度量计算: 

\gamma _k(s) = P(s_k^E(s),Y_k\, |\, s_k^S(s))=\sum_{u_k\in U}^{} P(s_k^E(s)\, |\, s_k^S(s))\, P(X_k|e)\, P(Y_k|X_k)

其中,X_k 和 Y_k分别是 k 时刻的发送符号和接收符号。

(1) P(s_k^E(s)\, |\, s_k^S(s)) 为边的状态转移概率:

P(s_k^E(s)\, |\, s_k^S(s))=\left\{\begin{matrix} P(u_k=1)=\frac{exp(\Lambda _a(u_k))}{1+exp(\Lambda _a(u_k))}\\ P(u_k=0)=\frac{1}{1+exp(\Lambda _a(u_k))} \end{matrix}\right.                                        (2)

(2) P(X_k|e) 取决于 X_k是否与 边e 有关。有关时取1,无关时取0.

(3)第三项与信道模型有关:

\Lambda(u_k)=log \left (\frac{P(u_k=1\, | Y_1^N }{P(u_k=0\, | Y_1^N} \right) =log\left ( \frac{\sum _{u(e)=1}\,\, \alpha_{k-1}(s_k^S(e))\,\, \gamma _k(e)\, \, \beta_{k}(s_k^E(e))} {\sum _{u(e)=0}\,\, \alpha_{k-1}(s_k^S(e))\,\, \gamma _k(e)\, \, \beta_{k}(s_k^E(e))} \right )           (3)

用对数表示为:

               M_k(e)=ln(\gamma _k(s))=ln\,\, p(s_k^E(e)\, |\, s_k^S(e))+ln\, p(X_k|e)+ln\, p(Y_k|X_k)              (4)

              ln\,\, p(s_k^E(e)\, |\, s_k^S(e))=\left\{\begin{matrix} \Lambda _a(u_k)-ln\, (1+exp(\Lambda _a(u_k)))\: ,u_k=1\\ -ln\, (1+exp(\Lambda _a(u_k))\: ,u_k=0 \end{matrix}\right.



再回到 前向度量计算:

                            \alpha_k(s)=p(s_k^S(e)=s,Y_1^{k-1})=\sum \alpha_{k-1}(s_k^S(e))\, \gamma _k(e)                            (5)

                           A_k(s)=ln\, \alpha _k(s)

因此,

Alpha(k,state2) = log( sum( exp( gamma+Alpha(k-1,:) ) ) );  

 3.4 后向度量计算

与前向度量类似,后向度量也由双循环组成:

内循环:以所有状态为循环:state = 1 : 2^m

外循环:以所有信息数量为循环:k = L_total-1 : -1: 1 

                                                           图6  后向度量算法示意图 

后向度量 \beta _k(s) 用公式表示为: 

                               \beta _k(s)=p(Y_{k+1}^N\, |\, s_k^E(e))=\sum_{s_{k+1}^S(e)}^{} \beta _{k+1}(s_{k+1}^E(e))\gamma _{k+1}(e)                     (6) 

先计算输入 d_k = 0时:

  gamma(next_state(state1,1)) = (-rec_s(2*k+1) + rec_s(2*k+2) * next_out(state1,2))
           -log(1+exp(L_a(k+1)));                 

先计算输入 d_k = 1时: 

gamma(next_state(state1,2)) = (rec_s(2*k+1) + rec_s(2*k+2) * next_out(state1,4))
           + L_a(k+1) - log(1+exp(L_a(k+1)));

因此,

Beta(k,state1) = log(sum(exp(gamma+Beta(k+1,:)))) 

  3.5 LLR输出

在进行前向度量时,已经计算过  \gamma _k(e)  

gamma0 =  -rec_s(2*k-1) + rec_s(2*k) * last_out(state2,2) ) - log(1+exp(L_a(k)) ;

gamma1 = rec_s(2*k-1) + rec_s(2*k) * last_out(state2,4)) + L_a(k) -

                   log(1+exp(L_a(k)); 

这个与之前计算前向度量时计算得到的  \gamma _k(e) 一致。最终得到,

% 将四个状态的度量值分别计算,得到当前状态下p(d_k=1)与p(d_k=0)的后验概率

for state2 = 1:nstates

    temp0(state2) = exp(gamma0 + Alpha(k,last_state(state2,1)) + Beta(k,state2));

    temp1(state2) = exp(gamma1 + Alpha(k,last_state(state2,2)) + Beta(k,state2));

end

L_all(k) = log(sum(temp1)) - log(sum(temp0));

L_e = L_all - 2 * rec_s(1,1:2:2*L_total) - L_a;



按照上述梳理的思路,类似地,对于rec_s(2,:)同样也分三步走:

1)L_a = L_e(alpha)  

将码1得到的L_e再次进行交织,作为码块2的先验概率;

2) L_all = logmapo(rec_s(2,:), g, L_a, 2); 

对码块2进行迭代译码;

3) L_e = L_all - 2 * rec_s(2,1:2:2*L_total) - L_a;

 最终可得到:

  xhat(alpha) = (sign(L_all)+1)/2;

结尾: 

 历史是何等的有意思,当 Claude Elwood Shannon 提出香农定理的时候,却并没有给出解决方案。也许这就是他对“信息”最好的诠释:

    We may have knowledge of the past but can't control it , we may control the future but have no knowledge of it. 

    过去可知不可控,未来可控不可知。

 

    经过几代人不断地探索和追求,当Turbo编码横空出世的时候,举世震惊:

                                     左: Claude Berrou  右: Alain Glavieux

历史是何等的相似,又似乎命中注定。

                                                                                                                        Turbo 编译码完结#

                                                   

  • 6
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
以下是WuYufeiTurbo码和译码的C语言实现: Turbo码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define N 1024 #define K 512 #define M 4 #define PUNCTURE 3 int main() { int i, j, k; int input[N]; int output[K]; int state1, state2, state3; int out1, out2, out3; int temp1, temp2, temp3; int *ptr; int puncture[PUNCTURE] = {1, 2, 3}; //输入比特流 printf("Input bit stream:\n"); for(i = 0; i < N; i++) scanf("%d", &input[i]); //初始化状态 state1 = 0; state2 = 0; state3 = 0; //Turbo码 for(i = 0; i < K; i += 2) { //第一个卷积码器 temp1 = (state1 << 1) | input[i]; temp2 = (state2 << 1) | input[i + 1]; out1 = (temp1 ^ temp2) & 1; state1 = (temp1 >> 1) & 7; state2 = (temp2 >> 1) & 7; //第二个卷积码器 temp1 = (state2 << 1) | input[i]; temp2 = (state3 << 1) | input[i + 1]; out2 = (temp1 ^ temp2) & 1; state2 = (temp1 >> 1) & 7; state3 = (temp2 >> 1) & 7; //交织器 ptr = output + i; *ptr = out1; *(ptr + 1) = out2; //打孔 for(j = 0; j < PUNCTURE; j++) { if(i + puncture[j] < K) *(ptr + puncture[j]) = -1; } } //输出码比特流 printf("Output code bit stream:\n"); for(i = 0; i < K; i++) { if(output[i] == -1) printf("-"); else printf("%d", output[i]); } printf("\n"); return 0; } ``` Turbo译码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define N 1024 #define K 512 #define M 4 #define PUNCTURE 3 #define SOFT_DECISION 1 int main() { int i, j, k; int input[K]; int output[N]; int state1, state2, state3; int out1, out2, out3; int temp1, temp2, temp3; int *ptr; int puncture[PUNCTURE] = {1, 2, 3}; //输入码比特流 printf("Input code bit stream:\n"); for(i = 0; i < K; i++) { char c = getchar(); while(c == '\n' || c == '\r' || c == ' ') c = getchar(); if(c == '-') input[i] = -1; else input[i] = c - '0'; } //初始化状态 state1 = 0; state2 = 0; state3 = 0; //Turbo译码 for(i = 0; i < N; i++) { //第一个卷积码器 temp1 = (state1 << 1) | input[2 * (i % K)]; temp2 = (state2 << 1) | input[2 * (i % K) + 1]; out1 = (temp1 ^ temp2) & 1; state1 = (temp1 >> 1) & 7; state2 = (temp2 >> 1) & 7; //第二个卷积码器 temp1 = (state2 << 1) | input[2 * (i % K)]; temp2 = (state3 << 1) | input[2 * (i % K) + 1]; out2 = (temp1 ^ temp2) & 1; state2 = (temp1 >> 1) & 7; state3 = (temp2 >> 1) & 7; //交织器 ptr = output + i; *ptr = out1; *(ptr + M) = out2; //打孔 for(j = 0; j < PUNCTURE; j++) { if(i % M == puncture[j]) *(ptr - M + puncture[j]) = -1; } } //输出译码比特流 printf("Output decoded bit stream:\n"); for(i = 0; i < N; i++) { if(output[i] == -1) printf("-"); else printf("%d", output[i]); } printf("\n"); return 0; } ``` 其中,Turbo码和Turbo译码的区别在于输入的数据不同,Turbo码输入原始比特流,Turbo译码输入码比特流。同时,在Turbo译码中,还需要对输入的码比特流进行去打孔和交织处理,以还原出原始比特流。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值