Comparing the LDPC results with Matlab

Applying LDPC encoding/decoding on random transport blocks and comparing the results with the equivalent Matlab code “MatlabFiles/LDPC.mlx”. Here is the execution results of this code in Matlab.

[1]:
import numpy as np
import scipy.io
import time

from neoradium import LdpcEncoder, LdpcDecoder

matlabFilesPath = "./MatlabFiles"
[2]:
# Create an LDPC encoder object
ldpcEncoder = LdpcEncoder(baseGraphNo=1, modulation='QPSK', txLayers=1, nRef=0, targetRate=449/1024)
[3]:
# Read input bits from Matlab-generated file
inBits = scipy.io.loadmat(matlabFilesPath+'/in.mat')['in'].reshape(-1)
inBits[:10]
[3]:
array([0, 0, 1, 1, 0, 0, 1, 1, 0, 1], dtype=int8)
[4]:
# Transport block padded with a 24-bit CRC
tbWithCrc = ldpcEncoder.appendCrc(inBits,'24A')
tbWithCrc.shape
[4]:
(10024,)
[5]:
# Do the segmentation:
codeBlocksCrc = ldpcEncoder.doSegmentation(tbWithCrc)

# NeoRadium does not set filler bits to -1. To match with matalab, we need to set these bits
# to -1. This is only needed when comparing segmentation results with matlab.
fillerStart = ldpcEncoder.codeBlockSize-ldpcEncoder.numFillerBits
codeBlocksCrc[:, fillerStart : fillerStart+ldpcEncoder.numFillerBits] = -1

# Compare results with Matlab:
codeBlocksCrcMatlab = scipy.io.loadmat(matlabFilesPath+'/cbsIn.mat')['cbsIn'].T
assert np.abs(codeBlocksCrc-codeBlocksCrcMatlab).sum()==0, "MISMATCH WITH MATLAB!!!"

print("CodeBlocks Shape (Including CRC):", codeBlocksCrc.shape)
print("liftingSize (Zc):                ", ldpcEncoder.liftingSize)
print("setIndex (Zero-Based):           ", ldpcEncoder.setIndex)
print("numFillerBits:                   ", ldpcEncoder.numFillerBits)

CodeBlocks Shape (Including CRC): (2, 5280)
liftingSize (Zc):                 240
setIndex (Zero-Based):            7
numFillerBits:                    244
[6]:
print("Base Graph Shape:", ldpcEncoder.baseGraph.shape)
print("8x8 sub-matrix at the \"Double Diagonal\" section:")
for r in ldpcEncoder.baseGraph[0:8,22:30]: print("    " + "   ".join("%3d"%x for x in r))
Base Graph Shape: (46, 68)
8x8 sub-matrix at the "Double Diagonal" section:
      1     0    -1    -1    -1    -1    -1    -1
      0     0     0    -1    -1    -1    -1    -1
     -1    -1     0     0    -1    -1    -1    -1
      1    -1    -1     0    -1    -1    -1    -1
     -1    -1    -1    -1     0    -1    -1    -1
    180    -1    -1    -1    -1     0    -1    -1
     -1    -1    -1    -1    -1    -1     0    -1
     -1    -1    -1    -1    -1    -1    -1     0
[7]:
# Check the valid LDPC coded blocks:
# Do not puncture first 2 columns because we need the whole coded blocks for the
# "isValidCodedBlock" function below
testCodedBlocks = ldpcEncoder.encode(codeBlocksCrc, puncture=False)

(ldpcEncoder.isValidCodedBlock(testCodedBlocks[0]),
 ldpcEncoder.isValidCodedBlock(testCodedBlocks[1]),
 ldpcEncoder.isValidCodedBlock(np.zeros(68*ldpcEncoder.liftingSize)),  # Always valid
 ldpcEncoder.isValidCodedBlock(np.ones(68*ldpcEncoder.liftingSize)))   # Intentionally Invalid

[7]:
(True, True, True, False)
[8]:
# Normal usage (1st 2 columns punctured, zero filler bits)
# Do segmentation
codeBlocksCrc = ldpcEncoder.doSegmentation(tbWithCrc)
# Encoding:
codedBlocks = ldpcEncoder.encode(codeBlocksCrc)
print("codedBlocks Shape:", codedBlocks.shape)

# NeoRadium does not set filler bits to -1. To match with matalab, we need to set these bits
# to -1. This is only needed when comparing encoder output (before rate matching) with matlab.
fillerStart = ldpcEncoder.codeBlockSize-ldpcEncoder.numFillerBits-2*ldpcEncoder.liftingSize
codedBlocks[:, fillerStart : fillerStart+ldpcEncoder.numFillerBits] = -1

# Compare results with Matlab:
codedBlocksMatlab = scipy.io.loadmat(matlabFilesPath+'/enc.mat')['enc'].T
assert np.abs(codedBlocks-codedBlocksMatlab).sum()==0, "MISMATCH WITH MATLAB!!!"


codedBlocks Shape: (2, 15840)
[9]:
rateMatchedCodeBlocks = ldpcEncoder.rateMatch(codedBlocks)
print("Rate-Matched coded blocks Shape:", rateMatchedCodeBlocks.shape)

# Compare results with Matlab:
rateMatchedCodeBlocksMatlab = scipy.io.loadmat(matlabFilesPath+'/chIn.mat')['chIn'].T
assert np.abs(rateMatchedCodeBlocks-rateMatchedCodeBlocksMatlab).sum()==0, "MISMATCH WITH MATLAB!!!"


Rate-Matched coded blocks Shape: (22808,)
[10]:
# Do all of it with one call end to end
rateMatchedCodeBlocks = ldpcEncoder.getRateMatchedCodeBlocks(inBits)

# Compare results with Matlab:
assert np.abs(rateMatchedCodeBlocks-rateMatchedCodeBlocksMatlab).sum()==0, "MISMATCH WITH MATLAB!!!"


[11]:
# Simple bipolar channel with no noise:
channelOutput = 1 - 2.0*rateMatchedCodeBlocks
[12]:
# Create an LDPC decoder
ldpcDecoder = LdpcDecoder(baseGraphNo=1, modulation='QPSK', txLayers=1, nRef=0);

# Recover rate
rxCodedBlocks = ldpcDecoder.recoverRate(channelOutput, len(inBits))

# Compare results with matlab:
rxCodedBlocksMatlab = scipy.io.loadmat(matlabFilesPath+'/raterec.mat')['raterec'].T
rxCodedBlocksMatlab[rxCodedBlocksMatlab==np.inf]=LdpcDecoder.LARGE_LLR  # Replace inf with our LARGE_LLR
assert np.abs(rxCodedBlocks-rxCodedBlocksMatlab).sum()==0, "MISMATCH WITH MATLAB!!!"

rxCodedBlocks.shape

[12]:
(2, 15840)
[13]:
# Decode the rate-recovered message
rxCodeBlocks = ldpcDecoder.decode(rxCodedBlocks)
rxCodeBlocks.shape
[13]:
(2, 5280)
[14]:
# Compare results with matlab:
rxCodeBlocksMatlab = scipy.io.loadmat(matlabFilesPath+'/decBits.mat')['decBits'].T
assert np.abs(rxCodeBlocks-rxCodeBlocksMatlab).sum()==0, "MISMATCH WITH MATLAB!!!"
[15]:
# Undo Segmentation and CRC checking
rxCodeBlocksWithoutCrc, crcMatch = ldpcDecoder.checkCrcAndMerge(rxCodeBlocks)
print("CRC Matched:", crcMatch)

# Compare results with matlab:
rxCodeBlocksWithoutCrcMatlab = scipy.io.loadmat(matlabFilesPath+'/decBlk.mat')['decBlk'].T
assert np.abs(rxCodeBlocksWithoutCrc-rxCodeBlocksWithoutCrc).sum()==0, "MISMATCH WITH MATLAB!!!"
rxCodeBlocksWithoutCrc.shape
CRC Matched: [ True  True]
[15]:
(10024,)
[16]:
# The transport block CRC checking
print(ldpcDecoder.checkCrc(rxCodeBlocksWithoutCrc,'24A'))
True
[17]:
# Compare with original input
assert np.abs(rxCodeBlocksWithoutCrc[:-24]-inBits).sum()==0, "MISMATCH WITH INPUT BITS!!!"
[ ]:

[ ]: