PolarSCLDecoder#
- class sionna.phy.fec.polar.PolarSCLDecoder(frozen_pos: numpy.ndarray, n: int, list_size: int = 8, crc_degree: str | None = None, ind_iil_inv: numpy.ndarray | None = None, return_crc_status: bool = False, *, precision: str | None = None, device: str | None = None, **kwargs)[source]#
Bases:
sionna.phy.block.BlockFast successive cancellation list (SCL) decoder for Polar and Polar-like codes [Tal_SCL] [Hashemi_SSCL]. Rate-1 nodes use a single-flip (
M=1) shortcut rather than exact list decoding; see Notes.- Parameters:
frozen_pos (numpy.ndarray) – Array of int defining the
n-kindices of the frozen positions.n (int) – Defining the codeword length.
list_size (int) – Defining the list size
Lof the decoder. Must be a power of 2.crc_degree (str | None) – Defining the CRC polynomial to be used. Can be any value from {CRC24A, CRC24B, CRC24C, CRC16, CRC11, CRC6}.
ind_iil_inv (numpy.ndarray | None) – If not None, the sequence is used as inverse input-bit interleaver before the CRC is evaluated. This only affects CRC evaluation; the output sequence is not permuted.
return_crc_status (bool) – If True, the decoder additionally returns the CRC status indicating if a codeword was (most likely) correctly recovered. This is only available if
crc_degreeis not None.precision (str | None) – Precision used for internal calculations and outputs. If None,
precisionis used.device (str | None) – Device for computation (e.g., ‘cpu’, ‘cuda:0’). If None,
deviceis used.
- Inputs:
llr_ch – […, n], torch.float. Tensor containing the channel LLR values (as logits).
- Outputs:
b_hat – […, k], torch.float. Binary tensor containing hard-decided estimations of all k information bits.
crc_status – […], torch.bool. CRC status indicating if a codeword was (most likely) correctly recovered. This is only returned if
return_crc_statusis True. Note that false positives are possible.
Notes
This block implements the successive cancellation list (SCL) decoder as described in [Tal_SCL] using LLR-domain message updates [Stimming_LLR]. At construction time, the decoder performs a single depth-first traversal of the Polar decoding tree and generates a fixed sequence of message-passing instructions (the decoder tape). The traversal also applies the fast-SCL node shortcuts of [Hashemi_SSCL], which collapse common sub-trees into single ops to avoid descending all the way to per-bit leaves.
Each tape entry is therefore one of
F(check-node update),G(variable-node update),COMBINE(upward XOR combine), a single frozen or info leaf decision, or one of the fast-SCL node shortcutsR0/REP/R1. Decoding replays this tape over shared workspace tensors, so the sequence of launched kernels does not depend on the channel input and is compatible with torch.compile and CUDA graph capture.The fast-SCL shortcuts cover three special sub-tree shapes: an all-frozen sub-tree is replaced by a single
R0op, a repetition sub-tree (all leaves frozen except the last) by a singleREPop, and a rate-1 sub-tree (no frozen leaves) by a singleR1op.R1uses the single-flip approximation (M=1), i.e., it keeps two alternatives per surviving path: the maximum-likelihood codeword and the codeword with the least-reliable bit flipped.Only the currently active region of the Polar tree is materialized per path: LLRs occupy a flat buffer of size
n - 1indexed by stage, hard decisions for stages1 .. n_stages - 1occupy2n - 4slots, and stage-0 leaf decisions live in a persistent[B, 2L, n]tensor. The per-op workspace offsets are pre-computed during tape construction so that decoding issues plain tensor slices without any per-op address arithmetic.With CRC-aided decoding, the decoder selects the surviving path with the smallest path metric after adding a large CRC-failure penalty to every path that does not check. If no path passes the CRC, the path with the smallest underlying metric is returned and its
crc_statusis False.As commonly done, we assume frozen bits are set to 0. Please note that - although its practical relevance is only little - setting frozen bits to 1 may result in affine codes instead of a linear code as the all-zero codeword is not necessarily part of the code any more.
Examples
import torch from sionna.phy.fec.polar import PolarSCLDecoder, PolarEncoder from sionna.phy.fec.polar.utils import generate_5g_ranking k, n = 100, 256 frozen_pos, _ = generate_5g_ranking(k, n) encoder = PolarEncoder(frozen_pos, n) decoder = PolarSCLDecoder(frozen_pos, n, list_size=8) bits = torch.randint(0, 2, (10, k), dtype=torch.float32) codewords = encoder(bits) llr_ch = 20.0 * (2.0 * codewords - 1) # BPSK without noise decoded = decoder(llr_ch) print(torch.equal(bits, decoded)) # True
Attributes
- property frozen_pos#
Frozen positions for Polar decoding.
- property info_pos#
Information bit positions for Polar encoding.
- property k#
Number of information bits (including any outer CRC).
- property k_crc#
Length of the outer CRC (0 if none).
- property list_size#
Decoder list size
L.
- property llr_max#
Internal LLR clipping magnitude.
- property n#
Codeword length.