SCS译码的算法原理如下图展示:
相比于SCL,SCS的优点就是每次都去寻找最优的待选路径,而SCL每个信息比特进行扩展,即使PM足够大的候选路径也会扩展(最不可能的路径),计算就出现了冗余。
但SCS译码的难点在于构造一个数据栈来存候选路径的各个信息,在仿真中,这是容易做到的,但是在硬件中,维护一个大的数据栈是难以实现的(这也是SCS的缺点)。我在matlab仿真时构造了如下的数据结构:
PM_and_path是一个结构体,其成员有PM(存储候选路径的度量值)、path(存储路径的比特、P(存储候选路径的计算LLRs数组)、C(存储候选路径的计算比特数组)。
PM为一个double型变量;
path为一个N*1的数组,其中取值为(0,1);
P为一个(N-1) *1的double型数组;
C为一个(2N-1)*2的数组,取值为(0,1);
![](https://img-blog.csdnimg.cn/20210731115344830.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMTI0MDEw,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20210731115625365.png)
依靠上述的结构体,就可以构造出一个堆栈,相比于C语言,matlab构造一个栈比较简单,我们只需构造一个结构体数组,将第一个结构体作为栈底,最后一个结构体作为栈顶,依靠栈大小D和数组大小进行判断是否满栈,这里就不再赘述,详细可以查看代码。
![](https://img-blog.csdnimg.cn/20210731122832751.png)
入栈和出栈的代码如下所示:
function PM_and_path=push_stack(PM_and_path,PM,path,first_flag,D,P,C)
%push stack%
%PM_and_path(1) is the bottom of stack and PM_and_path(D) is the top of stack
%PM_and_path is the structure block;The smaller the PM, the higher the accuracy
%PM is the PM num;
%path is the path num eg.[0 0 1 1]
% P is internal LLRs of active path
% C is internal bit values of active path
if length(PM_and_path)==D
sprintf('%s ','Full Stack,Failed to push stack!')
else
if first_flag==1
PM_and_path(1).PM=PM;
PM_and_path(1).path=path;
PM_and_path(1).P=P;
PM_and_path(1).C=C;
else
PM_and_path(end+1).PM=PM;
PM_and_path(end).path=path;
PM_and_path(end).P=P;
PM_and_path(end).C=C;
end
[~,index]=sort([PM_and_path.PM],'descend');
PM_and_path=PM_and_path(index);
end
end
function [PM_and_path,P,C]= pop_stack(PM_and_path)
%pop stack%
if isempty(PM_and_path)
sprintf('%s ','Empty Stack,Failed to pop stack!')
else
P=PM_and_path(end).P;
C=PM_and_path(end).C;
PM_and_path(end)=[];
end
end
在构造完数据结构后,只需调用之前的SC译码函数就可以进行译码,译码的具体算法和本文开头的算法一样,下面我使用了极化码讲义中的一个例子来说明SCS的译码过程。
![](https://img-blog.csdnimg.cn/20210802073328301.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMTI0MDEw,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20210802073702317.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMTI0MDEw,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20210802074532525.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMTI0MDEw,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20210802074818360.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMTI0MDEw,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/2021080207504767.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMTI0MDEw,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20210802075633499.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMTI0MDEw,size_16,color_FFFFFF,t_70)
由此,整个SCS的内容已经全部阐述完毕,依据上述的内容,我现在的理解如下:
(1)P、C数组的存储和维护。
如果我们选择使用将P、C数组入栈的方法,这将在硬件上对栈的存储空间提出挑战,尤其是在栈的大小D很大时,N也很大时,这个数据栈的大小将十分大(但这对仿真几乎没有特别大的影响)。对此,我结合SCL的译码特点,给出的一个解决方案就维护一个P数组、和C数组,这两个数组不进行出入栈,其中P的大小为(N-1)*D,C的大小为(2N-1)*2D,且排列顺序与栈的相对应,即栈中的第i条路径在P中为(:)*i,在C中为:(:)*2i-1,(:)*2i。出栈时激活对应列即可。
(2)Lazy Copy的不适用。
因为栈中的候选路径的长度不再相同,这带来每条译码路径都是相对独立的,即P、C数组的生成都是独立的,因此就没有必要使用Lazy Copy。
(3)原算法中的判断存在问题。
计数器,记录了堆栈中长度为i的路径数量,但依据上述过程并不能记录栈内的长度为i的路径数量,因此我认为可以在第(5)步时在统计数量即可。
(4)D、L的选择问题。
当,我们可以知道,这将遍历全部的译码情况,实现最准确的译码,但这是不切实际的,因此我们必须要合理的选择D和L的大小。在参考CA-SCL后,可以使用自适应的栈大小,即CA-SCS,将栈的大小从小向大进行译码,当译码成功时即可停止译码。
当我们将D=1时,SCS译码会退回为SC译码。相应的,在SCS算法原理,入栈时我们将栈内的排序的标准设置为PM的大小,若我们将排序标准设置为候选路径已译码的长度时,SCS将退化为SCL。
SCS的具体代码,我完成时将开源在GitHub和CSDN,为其他学习极化码的朋友提供方便。