Utility Functions
This module provides utility functions for the FEC package. It also provides serval functions to simplify EXIT analysis of iterative receivers.
(Binary) Linear Codes
Several functions are provided to convert parity-check matrices into generator matrices and vice versa. Please note that currently only binary codes are supported.
# load example parity-check matrixpcm,k,n,coderate=load_parity_check_examples(pcm_id=3)
Note that many research projects provide their parity-check matrices in thealist format[MacKay] (e.g., see[UniKL]). The follwing code snippet provides an example of how to import an external LDPC parity-check matrix from analist file and how to set-up an encoder/decoder.
# load external example parity-check matrix in alist formatal=load_alist(path=filename)pcm,k,n,coderate=alist2mat(al)# the linear encoder can be directly initialized with a parity-check matrixencoder=LinearEncoder(pcm,is_pcm=True)# initalize BP decoder for the given parity-check matrixdecoder=LDPCBPDecoder(pcm,num_iter=20)# and run simulation with random information bitsno=1.batch_size=10num_bits_per_symbol=2source=BinarySource()mapper=Mapper("qam",num_bits_per_symbol)channel=AWGN()demapper=Demapper("app","qam",num_bits_per_symbol)u=source([batch_size,k])c=encoder(u)x=mapper(c)y=channel(x,no)llr=demapper(y,no)c_hat=decoder(llr)
- sionna.phy.fec.utils.load_parity_check_examples(pcm_id,verbose=False)[source]
Loads parity-check matrices of built-in example codes.
This utility function loads predefined example codes, including Hamming,BCH, and LDPC codes. The following codes are available:
pcm_id=0 :(7,4) Hamming code withk=4 information bits andn=7 codeword length.pcm_id=1 :(63,45) BCH code withk=45 information bits andn=63 codeword length.pcm_id=2 :(127,106) BCH code withk=106 information bits andn=127 codeword length.pcm_id=3 : Random LDPC code with variable node degree 3 and check node degree 6, withk=50 information bits andn=100 codeword length.pcm_id=4 : 802.11n LDPC code withk=324 information bits andn=648 codeword length.
- Parameters:
pcm_id (int) – An integer identifying the code matrix to load.
verbose (bool, (defaultFalse)) – IfTrue, prints the code parameters.
- Returns:
pcm (numpy.ndarray) – Array containing the parity-check matrix (values are0 and1).
k (int) – Number of information bits.
n (int) – Number of codeword bits.
coderate (float) – Code rate, assuming full rank of the parity-check matrix.
- sionna.phy.fec.utils.alist2mat(alist,verbose=True)[source]
Converts analist[MacKay] code definition to a NumPy parity-check matrix.
This function converts analist format representation of a code’sparity-check matrix to a NumPy array. Many example codes inalistformat can be found in[UniKL].
About thealist format (see[MacKay] for details):
Row 1: Defines the parity-check matrix dimensionsm x n.
Row 2: Contains two integers,max_CN_degree andmax_VN_degree.
Row 3: Lists the degrees of alln variable nodes (columns).
Row 4: Lists the degrees of allm check nodes (rows).
Nextn rows: Non-zero entries of each column, zero-padded as needed.
Followingm rows: Non-zero entries of each row, zero-padded as needed.
- Parameters:
alist (list) – Nested list inalist format[MacKay] representing the parity-check matrix.
verbose (bool, (defaultTrue)) – IfTrue, prints the code parameters.
- Returns:
pcm (numpy.ndarray) – NumPy array of shape[n - k, n] representing the parity-checkmatrix.
k (int) – Number of information bits.
n (int) – Number of codeword bits.
coderate (float) – Code rate of the code.
Notes
Use
load_alistto import analist from a textfile.Example
The following code snippet imports analist from a file called
filename:al=load_alist(path=filename)pcm,k,n,coderate=alist2mat(al)
- sionna.phy.fec.utils.load_alist(path)[source]
Reads analist file and returns a nested list describing a code’sparity-check matrix.
This function reads a file inalist format[MacKay] and returns a nestedlist representing the parity-check matrix. Numerous example codes inalist format are available in[UniKL].
- Parameters:
path (str) – Path to thealist file to be loaded.
- Returns:
A nested list containing the importedalist data representing theparity-check matrix.
- Return type:
list
- sionna.phy.fec.utils.generate_reg_ldpc(v,c,n,allow_flex_len=True,verbose=True)[source]
Generates a random regular (v, c) LDPC code.
This function generates a random Low-Density Parity-Check (LDPC)parity-check matrix of length
nwhere each variable node (VN) hasdegreevand each check node (CN) has degreec. Note that thegenerated LDPC code is not optimized to avoid short cycles, which mayresult in a non-negligible error floor. For encoding, theLinearEncoderblock can be used, but the construction does notguarantee that the parity-check matrix (pcm) has full rank.- Parameters:
v (int) – Desired degree of each variable node (VN).
c (int) – Desired degree of each check node (CN).
n (int) – Desired codeword length.
allow_flex_len (bool, (defaultTrue)) – IfTrue, the resulting codeword length may beslightly increased to meet the degree requirements.
verbose (bool, (defaultTrue)) – IfTrue, prints code parameters.
- Returns:
pcm (numpy.ndarray) – Parity-check matrix of shape[n - k, n].
k (int) – Number of information bits per codeword.
n (int) – Number of codeword bits.
coderate (float) – Code rate of the LDPC code.
Notes
This algorithm is designed only for regular node degrees. To achievestate-of-the-art bit-error-rate performance, optimizing irregular degreeprofiles is usually necessary (see[tenBrink]).
- sionna.phy.fec.utils.make_systematic(mat,is_pcm=False)[source]
Converts a binary matrix to its systematic form.
This function transforms a binary matrix into systematic form, where thefirstk columns (or lastk columns if
is_pcmis True) form anidentity matrix.- Parameters:
mat (numpy.ndarray) – Binary matrix of shape[k, n] to be transformed to systematic form.
is_pcm (bool, (defaultFalse)) – IfTrue,
matis treated as a parity-check matrix,and the identity part will be placed in the lastk columns.
- Returns:
mat_sys (numpy.ndarray) – Binary matrix in systematic form, where the firstk columns (or lastk columns if
is_pcmis True) form the identity matrix.column_swaps (list of tuple of int) – A list of integer tuples representing the column swaps performed toachieve the systematic form, in order of execution.
Notes
This function may swap columns of the input matrix to achieve systematicform. As a result, the output matrix represents a permuted version of thecode, defined by the
column_swapslist. To revert to the originalcolumn order, apply the inverse permutation in reverse order of the swaps.If
is_pcmisTrue, indicating a parity-check matrix, the identitymatrix portion will be arranged in the lastk columns.
- sionna.phy.fec.utils.gm2pcm(gm,verify_results=True)[source]
Generates the parity-check matrix for a given generator matrix.
This function converts the generator matrix
gm(denoted as\(\mathbf{G}\)) to systematic form and uses the following relationshipto compute the parity-check matrix\(\mathbf{H}\) over GF(2):\[\mathbf{G} = [\mathbf{I} | \mathbf{M}]\Rightarrow \mathbf{H} = [\mathbf{M}^T | \mathbf{I}]. \tag{1}\]This is derived from the requirement for an all-zero syndrome, such that:
\[\mathbf{H} \mathbf{c}^T = \mathbf{H} * (\mathbf{u} * \mathbf{G})^T =\mathbf{H} * \mathbf{G}^T * \mathbf{u}^T = \mathbf{0},\]where\(\mathbf{c}\) represents an arbitrary codeword and\(\mathbf{u}\) the corresponding information bits.
This leads to:
\[\mathbf{G} * \mathbf{H}^T = \mathbf{0}. \tag{2}\]It can be seen that (1) satisfies (2), as in GF(2):
\[[\mathbf{I} | \mathbf{M}] * [\mathbf{M}^T | \mathbf{I}]^T = \mathbf{M} + \mathbf{M} = \mathbf{0}.\]- Parameters:
gm (numpy.ndarray) – Binary generator matrix of shape[k, n].
verify_results (bool, (defaultTrue)) – IfTrue, verifies that the generated parity-checkmatrix is orthogonal to the generator matrix in GF(2).
- Returns:
Binary parity-check matrix of shape[n - k, n].
- Return type:
numpy.ndarray
Notes
This function requires
gmto have full rank. An error is raised ifgmdoes not meet this requirement.
- sionna.phy.fec.utils.pcm2gm(pcm,verify_results=True)[source]
Generates the generator matrix for a given parity-check matrix.
This function converts the parity-check matrix
pcm(denoted as\(\mathbf{H}\)) to systematic form and uses the following relationshipto compute the generator matrix\(\mathbf{G}\) over GF(2):\[\mathbf{G} = [\mathbf{I} | \mathbf{M}]\Rightarrow \mathbf{H} = [\mathbf{M}^T | \mathbf{I}]. \tag{1}\]This derivation is based on the requirement for an all-zero syndrome:
\[\mathbf{H} \mathbf{c}^T = \mathbf{H} * (\mathbf{u} * \mathbf{G})^T =\mathbf{H} * \mathbf{G}^T * \mathbf{u}^T = \mathbf{0},\]where\(\mathbf{c}\) represents an arbitrary codeword and\(\mathbf{u}\) the corresponding information bits.
This leads to:
\[\mathbf{G} * \mathbf{H}^T = \mathbf{0}. \tag{2}\]It can be shown that (1) satisfies (2), as in GF(2):
\[[\mathbf{I} | \mathbf{M}] * [\mathbf{M}^T | \mathbf{I}]^T = \mathbf{M} + \mathbf{M} = \mathbf{0}.\]- Parameters:
pcm (numpy.ndarray) – Binary parity-check matrix of shape[n - k, n].
verify_results (bool, (defaultTrue)) – IfTrue, verifies that the generated generator matrixis orthogonal to the parity-check matrix in GF(2).
- Returns:
Binary generator matrix of shape[k, n].
- Return type:
numpy.ndarray
Notes
This function requires
pcmto have full rank. An error is raised ifpcmdoes not meet this requirement.
- sionna.phy.fec.utils.verify_gm_pcm(gm,pcm)[source]
Verifies that the generator matrix\(\mathbf{G}\) (
gm) andparity-check matrix\(\mathbf{H}\) (pcm) are orthogonal in GF(2).For a valid code with an all-zero syndrome, the following condition musthold:
\[\mathbf{H} \mathbf{c}^T = \mathbf{H} * (\mathbf{u} * \mathbf{G})^T =\mathbf{H} * \mathbf{G}^T * \mathbf{u}^T = \mathbf{0},\]where\(\mathbf{c}\) represents an arbitrary codeword and\(\mathbf{u}\) the corresponding information bits.
Since\(\mathbf{u}\) can be arbitrary, this leads to the condition:
\[\mathbf{H} * \mathbf{G}^T = \mathbf{0}.\]- Parameters:
gm (numpy.ndarray) – Binary generator matrix of shape[k, n].
pcm (numpy.ndarray) – Binary parity-check matrix of shape[n - k, n].
- Returns:
True if
gmandpcmdefine a valid pair of orthogonalparity-check and generator matrices in GF(2).- Return type:
bool
EXIT Analysis
The LDPC BP decoder allows to track the internal information flow (extrinsic information) during decoding via callbacks. This can be plotted in so-called EXIT Charts[tenBrinkEXIT] to visualize the decoding convergence.

This short code snippet shows how to generate and plot EXIT charts:
# parametersebno_db=2.5# simulation SNRbatch_size=10000num_bits_per_symbol=2# QPSKnum_iter=20# number of decoding iterationspcm_id=4# decide which parity check matrix should be used (0-2: BCH; 3: (3,6)-LDPC 4: LDPC 802.11npcm,k,n,coderate=load_parity_check_examples(pcm_id,verbose=True)noise_var=ebnodb2no(ebno_db=ebno_db,num_bits_per_symbol=num_bits_per_symbol,coderate=coderate)# init callbacks for tracking of EXIT chartscb_exit_vn=EXITCallback(num_iter)cb_exit_cn=EXITCallback(num_iter)# init componentsdecoder=LDPCBPDecoder(pcm,hard_out=False,cn_update="boxplus",num_iter=num_iter,v2c_callbacks=[cb_exit_vn,],# register callbacksc2v_callbacks=[cb_exit_cn,],)# register callbacks# generates fake llrs as if the all-zero codeword was transmitted over an AWNG channel with BPSK modulationllr_source=GaussianPriorSource()# generate fake LLRs (Gaussian approximation)# Remark: the EXIT callbacks require all-zero codeword simulationsllr_ch=llr_source([batch_size,n],noise_var)# simulate free running decoder (for EXIT trajectory)decoder(llr_ch)# calculate analytical EXIT characteristics# Hint: these curves assume asymptotic code length, i.e., may become inaccurate in the short length regimeIa,Iev,Iec=get_exit_analytic(pcm,ebno_db)# and plot the analytical exit curvesplt=plot_exit_chart(Ia,Iev,Iec)# and add simulated trajectory (requires "track_exit=True")plot_trajectory(plt,cb_exit_vn.mi.numpy(),cb_exit_cn.mi.numpy(),ebno_db)
Remark: for rate-matched 5G LDPC codes, the EXIT approximation becomesinaccurate due to the rate-matching and the very specific structure of thecode.
- sionna.phy.fec.utils.plot_exit_chart(mi_a=None,mi_ev=None,mi_ec=None,title='EXIT-Chart')[source]
Plots an EXIT-chart based on mutual information curves[tenBrinkEXIT].
This utility function generates an EXIT-chart plot. If all inputs areNone, an empty EXIT chart is created; otherwise, mutual informationcurves are plotted.
- Parameters:
mi_a (numpy.ndarray,optional) – Array of floats representing the a priori mutual information.
mi_v (numpy.ndarray,optional) – Array of floats representing the variable node mutual information.
mi_c (numpy.ndarray,optional) – Array of floats representing the check node mutual information.
title (str) – Title of the EXIT chart.
- Returns:
A handle to the generated matplotlib figure.
- Return type:
matplotlib.figure.Figure
- sionna.phy.fec.utils.get_exit_analytic(pcm,ebno_db)[source]
Calculates analytic EXIT curves for a given parity-check matrix.
This function extracts the degree profile from the provided parity-checkmatrix
pcmand calculates the EXIT (Extrinsic Information Transfer)curves for variable nodes (VN) and check nodes (CN) decoders. Note that thisapproach relies on asymptotic analysis, which requires a sufficiently largecodeword length for accurate predictions.It assumes transmission over an AWGN channel with BPSK modulation at anSNR specified by
ebno_db. For more details on the equations, see[tenBrink] and[tenBrinkEXIT].- Parameters:
pcm (numpy.ndarray) – The parity-check matrix.
ebno_db (float) – Channel SNR in dB.
- Returns:
mi_a (numpy.ndarray) – Array of floats containing the a priori mutual information.
mi_ev (numpy.ndarray) – Array of floats containing the extrinsic mutual information of thevariable node decoder for each
mi_avalue.mi_ec (numpy.ndarray) – Array of floats containing the extrinsic mutual information of thecheck node decoder for each
mi_avalue.
Notes
This function assumes random, unstructured parity-check matrices. Thus,applying it to parity-check matrices with specific structures or constraintsmay result in inaccurate EXIT predictions. Additionally, this function isbased on asymptotic properties and performs best with large parity-checkmatrices. For more information, refer to[tenBrink].
- sionna.phy.fec.utils.plot_trajectory(plot,mi_v,mi_c,ebno=None)[source]
Plots the trajectory of an EXIT-chart.
This utility function plots the trajectory of mutual information values inan EXIT-chart, based on variable and check node mutual information values.
- Parameters:
plot (matplotlib.figure.Figure) – A handle to a matplotlib figure where the trajectory will be plotted.
mi_v (numpy.ndarray) – Array of floats representing the variable node mutual informationvalues.
mi_c (numpy.ndarray) – Array of floats representing the check node mutual information values.
ebno (float) – The Eb/No value in dB, used for the legend entry.
Miscellaneous
- classsionna.phy.fec.utils.GaussianPriorSource(*,precision=None,**kwargs)[source]
Generates synthetic Log-Likelihood Ratios (LLRs) for Gaussian channels.
Generates synthetic Log-Likelihood Ratios (LLRs) as if an all-zero codewordwas transmitted over a Binary Additive White Gaussian Noise (Bi-AWGN)channel. The LLRs are generated based on either the noise variance
noor mutual information. If mutual information is used, it represents theinformation associated with a binary random variable observed through anAWGN channel.
The generated LLRs follow a Gaussian distribution with parameters:
\[\sigma_{\text{llr}}^2 = \frac{4}{\sigma_\text{ch}^2}\]\[\mu_{\text{llr}} = \frac{\sigma_\text{llr}^2}{2}\]where\(\sigma_\text{ch}^2\) is the noise variance specified by
no.If the mutual information is provided as input, the J-function as describedin[Brannstrom] is used to relate the mutual information to thecorresponding LLR distribution.
- Parameters:
precision (None (default) | ‘single’ | ‘double’) – Precision used for internal calculations and outputs.If set toNone,
precisionis used.- Input:
output_shape (tf.int) – Integer tensor or Python list defining the shape of the generated LLRtensor.
no (None (default) | tf.float) – Scalar defining the noise variance for the synthetic AWGN channel.
mi (None (default) | tf.float) – Scalar defining the mutual information for the synthetic AWGN channel.Only used of
nois None.
- Output:
tf.Tensor of dtype ``dtype`` (defaults to `tf.float32`) – Tensor with shape defined by
output_shape.
- sionna.phy.fec.utils.bin2int(arr)[source]
Converts a binary array to its integer representation.
This function converts an iterable binary array to its equivalent integer.For example,[1, 0, 1] is converted to5.
- Parameters:
arr (iterable ofint orfloat) – An iterable that contains binary values (0’s and 1’s).
- Returns:
The integer representation of the binary array.
- Return type:
int
- sionna.phy.fec.utils.int2bin(num,length)[source]
Converts an integer to a binary list of specified length.
This function converts an integer
numto a list of 0’s and 1’s, withthe binary representation padded to a length oflength. Bothnumandlengthmust be non-negative.For example:
If
num=5andlength=4, the output is[0, 1, 0, 1].If
num=12andlength=3, the output is[1, 0, 0] (truncated to length).
- Parameters:
num (int) – The integer to be converted into binary representation.
length (int) – The desired length of the binary output list.
- Returns:
A list of 0’s and 1’s representing the binary form of
num, paddedor truncated to a length oflength.- Return type:
list of int
- sionna.phy.fec.utils.bin2int_tf(arr)[source]
Converts a binary tensor to an integer tensor.
Interprets the binary representation across the last dimension of
arr,from most significant to least significant bit. For example, an inputof[0, 1, 1] is converted to3.- Parameters:
arr (tf.Tensor) – Tensor of integers or floats containing binary values (0’s and 1’s)along the last dimension.
- Returns:
Tensor with the integer representation of
arr.- Return type:
tf.Tensor
- sionna.phy.fec.utils.int2bin_tf(ints,length)[source]
Converts an integer tensor to a binary tensor with specified bit length.
This function converts each integer in the input tensor
intsto a binaryrepresentation, with an additional dimension of sizelengthadded at theend to represent the binary bits. Thelengthparameter must benon-negative.- Parameters:
ints (tf.Tensor) – Tensor of arbitrary shape[…, k] containing integers to beconverted into binary representation.
length (int) – An integer specifying the bit length of the binary representation foreach integer.
- Returns:
A tensor of the same shape as
intswith an additional dimension ofsizelengthat the end, i.e., shape[…, k, length].This tensor contains the binary representation of each integer inints.- Return type:
tf.Tensor
- sionna.phy.fec.utils.int_mod_2(x)[source]
Modulo 2 operation and implicit rounding for floating point inputs
Performs more efficient modulo-2 operation for integer inputs.Usestf.math.floormod for floating inputs and applies implicit roundingfor floating point inputs.
- Parameters:
x (tf.Tensor) – Tensor to which the modulo 2 operation is applied.
- Returns:
x_mod – Binary Tensor containing the result of the modulo 2 operation, with thesame shape as
x.- Return type:
tf.Tensor
- sionna.phy.fec.utils.llr2mi(llr,s=None,reduce_dims=True)[source]
Approximates the mutual information based on Log-Likelihood Ratios(LLRs).
This function approximates the mutual information for a given set of
llrvalues, assuming anall-zero codeword transmission as derived in[Hagenauer]:\[I \approx 1 - \sum \operatorname{log_2} \left( 1 + \operatorname{e}^{-\text{llr}} \right)\]The approximation relies on thesymmetry condition:
\[p(\text{llr}|x=0) = p(\text{llr}|x=1) \cdot \operatorname{exp}(\text{llr})\]For cases where the transmitted codeword is not all-zero, this methodrequires knowledge of the original bit sequence
sto adjust the LLRsigns accordingly, simulating an all-zero codeword transmission.Note that the LLRs are defined as\(\frac{p(x=1)}{p(x=0)}\), whichreverses the sign compared to the solution in[Hagenauer].
- Parameters:
llr (tf.float) – Tensor of arbitrary shape containing LLR values.
s (None |tf.float) – Tensor of the same shape as
llrrepresenting the signs of thetransmitted sequence (assuming BPSK), with values of +/-1.reduce_dims (bool, (defaultTrue)) – IfTrue, reduces all dimensions and returns a scalar.If False, averages only over the last dimension.
- Returns:
mi – If
reduce_dimsisTrue, returns a scalar tensor. Otherwise, returnsa tensor with the same shape asllrexcept for the last dimension,which is removed. Contains the approximated mutual information.- Return type:
tf.float
- sionna.phy.fec.utils.j_fun(mu)[source]
Computes theJ-function
TheJ-function relates mutual information to the mean ofGaussian-distributed Log-Likelihood Ratios (LLRs) using the Gaussianapproximation. This function implements the approximation proposed in[Brannstrom]:
\[J(\mu) \approx \left( 1 - 2^{H_\text{1}(2\mu)^{H_\text{2}}}\right)^{H_\text{3}}\]where\(\mu\) represents the mean of the LLR distribution, and theconstants are defined as\(H_\text{1}=0.3073\),\(H_\text{2}=0.8935\), and\(H_\text{3}=1.1064\).
Input values are clipped to [1e-10, 1000] for numerical stability.The output is clipped to a maximum LLR of 20.
- Parameters:
mu (tf.float32) – Tensor of arbitrary shape, representing the mean of the LLR values.
- Returns:
Tensor of the same shape and dtype as
mu, containing the calculatedmutual information values.- Return type:
tf.float32
- sionna.phy.fec.utils.j_fun_inv(mi)[source]
Computes the inverse of theJ-function
TheJ-function relates mutual information to the mean ofGaussian-distributed Log-Likelihood Ratios (LLRs) using the Gaussianapproximation. This function computes the inverseJ-function based on theapproximation proposed in[Brannstrom]:
\[J(\mu) \approx \left( 1 - 2^{H_\text{1}(2\mu)^{H_\text{2}}}\right)^{H_\text{3}}\]where\(\mu\) is the mean of the LLR distribution, and constants aredefined as\(H_\text{1}=0.3073\),\(H_\text{2}=0.8935\), and\(H_\text{3}=1.1064\).
Input values are clipped to [1e-10, 1] for numerical stability.The output is clipped to a maximum LLR of 20.
- Parameters:
mi (tf.float32) – Tensor of arbitrary shape, representing mutual information values.
- Returns:
Tensor of the same shape and dtype as
mi, containing the computedmean values of the LLR distribution.- Return type:
tf.float32
- References:
- [tenBrinkEXIT](1,2,3)
S. ten Brink, “Convergence Behavior of IterativelyDecoded Parallel Concatenated Codes,” IEEE Transactions onCommunications, vol. 49, no. 10, pp. 1727-1737, 2001.
[Brannstrom](1,2,3)F. Brannstrom, L. K. Rasmussen, and A. J. Grant,“Convergence analysis and optimal scheduling for multipleconcatenated codes,” IEEE Trans. Inform. Theory, vol. 51, no. 9,pp. 3354–3364, 2005.
[Hagenauer](1,2)J. Hagenauer, “The Turbo Principle in MobileCommunications,” in Proc. IEEE Int. Symp. Inf. Theory and its Appl.(ISITA), 2002.