Comparing the Polar Coding results with Matlab
Applying Polar encoding/decoding on random transport blocks and comparing the results with the equivalent Matlab code “MatlabFiles/Polar.mlx”. Here is the execution results of this code in Matlab.
[1]:
import numpy as np
import scipy.io
import time
import neoradium as nr
matlabFilesPath = "./MatlabFiles"
[2]:
payloadLen = 30 # A (Must be no larger than 1706)
rateMatchedLen = 120
ebNo = 0.8
codeRate = (payloadLen+24)/rateMatchedLen # Effective code rate
bps = 2; # bits per symbol = 2 for QPSK
esNo = ebNo + 10*np.log10(bps) # energy per symbol over noise
snrdB = esNo + 10*np.log10(codeRate) # SNR in dB
noiseVar = 1/(10**(snrdB/10))
noiseStd = np.sqrt(noiseVar)
print("Code Rate: ", codeRate)
print("SNR: ", snrdB, "db")
print("Noise Variance:", noiseVar)
print("Noise STD: ", noiseStd)
Code Rate: 0.45
SNR: 0.3424250943932492 db
Noise Variance: 0.9241819678918566
Noise STD: 0.9613438343755353
[3]:
# Create a Polar Encoder
polarEncoder = nr.PolarEncoder(payloadLen, rateMatchedLen, 'dci')
polarEncoder.print()
Polar Encoder Properties:
dataType ......................: DCI
payloadSize (A) ...............: 30
rateMatchedLen (E) ............: 120
codeBlockSize (K) .............: 54
polarCodeSize (N) .............: 128
Max Log2(N) (nMax) ............: 9
Segmentation (iSeg) ...........: Disabled
Code Block CRC (crcPoly) ......: 24C
Input Interleaving (iIL) ......: Enabled
Coded bit Interleaving (iBIL)..: Disabled
Num Parity checks (nPC, nPCwm) : 0,0
[4]:
# Read input bits from Matlab-generated file
txpBlock = scipy.io.loadmat(matlabFilesPath+'/msg.mat')['msg'].reshape(-1)
print("Transport Block Shape: ", txpBlock.shape)
print("Transport Block: ", "".join(str(x) for x in txpBlock))
# Segmentation
codeBlocks = polarEncoder.doSegmentation(txpBlock)
print("Code Blocks Shape: ", codeBlocks.shape)
print("Code Blocks: ", "".join(str(x) for x in codeBlocks[0]))
# Compare with Matlab
codeBlocksMatlab = scipy.io.loadmat(matlabFilesPath+'/msgcrc.mat')['msgcrc'].T
assert np.abs(codeBlocks-codeBlocksMatlab).sum()==0, "MISMATCH WITH MATLAB!!!"
Transport Block Shape: (30,)
Transport Block: 100100110110000110100110000010
Code Blocks Shape: (1, 54)
Code Blocks: 100100110110000110100110000010111100001010001110100010
[5]:
# Encode
codeWords = polarEncoder.encode(codeBlocks)
print("Code Words Shape: ", codeWords.shape)
print("Code Words first 10 bits:", "".join(str(x) for x in codeWords[0][:10]))
# Compare with Matlab
codeWordsMatlab = scipy.io.loadmat(matlabFilesPath+'/encOut.mat')['encOut'].T
assert np.abs(codeWords-codeWordsMatlab).sum()==0, "MISMATCH WITH MATLAB!!!"
Code Words Shape: (1, 128)
Code Words first 10 bits: 1001110011
[6]:
# Rate Matching
rateMatchedCodeWords = polarEncoder.rateMatch(codeWords)
print("Rate-Matched Shape: ", rateMatchedCodeWords.shape)
print("First 10 bits: ", "".join(str(x) for x in rateMatchedCodeWords[0][:10]))
# Compare with Matlab
rateMatchedCodeWordsMatlab = scipy.io.loadmat(matlabFilesPath+'/modIn.mat')['modIn'].T
assert np.abs(rateMatchedCodeWords-rateMatchedCodeWordsMatlab).sum()==0, "MISMATCH WITH MATLAB!!!"
Rate-Matched Shape: (1, 120)
First 10 bits: 1001110011
[7]:
# QPSK Modulation
modulated = nr.Modem('QPSK').modulate(rateMatchedCodeWords)
print("modulated Shape: ", modulated.shape)
# Compare with Matlab
modulatedMatlab = scipy.io.loadmat(matlabFilesPath+'/modOut.mat')['modOut'].T
assert np.abs(modulated-modulatedMatlab).max()<1e-12, "MISMATCH WITH MATLAB!!!"
print("Max Diff. with Matlab:", np.abs(modulated-modulatedMatlab).max())
print("First 5 symbols:\n", modulated[0,:5])
modulated Shape: (1, 60)
Max Diff. with Matlab: 1.5700924586837752e-16
First 5 symbols:
[-0.70710678+0.70710678j 0.70710678-0.70710678j -0.70710678-0.70710678j
0.70710678+0.70710678j -0.70710678-0.70710678j]
[8]:
# Read the noise from the Matlab file
complexNoise = scipy.io.loadmat(matlabFilesPath+'/chanNoise.mat')['chanNoise'].T
print("Noise Shape: ", complexNoise.shape)
# Add noise to the modulated signal
rxSymbols = modulated + complexNoise
print("First 5 Rx Symbols:\n", rxSymbols[0,:5])
Noise Shape: (1, 60)
First 5 Rx Symbols:
[-0.51312371+0.76995541j 0.88901799-1.41258547j -1.44741359-1.38917752j
0.49504718+0.34599014j -1.58021683-0.80163037j]
[9]:
# Demodulation: Calculate LLR values from symbols:
llrs = nr.Modem('QPSK').getLLRsFromSymbols(rxSymbols, noiseVar)
print("LLR Shape: ", llrs.shape)
print("First 10 LLRs: \n", llrs[0,:10])
# Compare with Matlab
llrsMatlab = scipy.io.loadmat(matlabFilesPath+'/rxLLR.mat')['rxLLR'].T
print("Matlab First 10 LLRs: \n", llrsMatlab[0,:10])
assert np.abs(llrs-llrsMatlab).max()<1e-12, "MISMATCH WITH MATLAB!!!"
print("Max Diff. with Matlab:", np.abs(llrs-llrsMatlab).max())
LLR Shape: (1, 120)
First 10 LLRs:
[-1.57039747 2.35642204 2.72080897 -4.32316924 -4.42975952 -4.25153001
1.51507488 1.05889091 -4.83619924 -2.45336219]
Matlab First 10 LLRs:
[-1.57039747 2.35642204 2.72080897 -4.32316924 -4.42975952 -4.25153001
1.51507488 1.05889091 -4.83619924 -2.45336219]
Max Diff. with Matlab: 3.552713678800501e-15
[10]:
#Hard Decision:
hardCodeWord = 1*(llrs<0)
print("Hard Decision first 10 bits:", "".join(str(x) for x in hardCodeWord[0][:10]))
print("Org CodeWord first 10 bits: ", "".join(str(x) for x in codeWords[0][:10]))
Hard Decision first 10 bits: 1001110011
Org CodeWord first 10 bits: 1001110011
[11]:
# Create a Polar Decoder
polarDecoder = nr.PolarDecoder(payloadLen, rateMatchedLen, 'dci',
sclListSize=8, useMinsum=True)
polarDecoder.print()
Polar Decoder Properties:
dataType ......................: DCI
payloadSize (A) ...............: 30
rateMatchedLen (E) ............: 120
codeBlockSize (K) .............: 54
polarCodeSize (N) .............: 128
Max Log2(N) (nMax) ............: 9
Segmentation (iSeg) ...........: Disabled
Code Block CRC (crcPoly) ......: 24C
Input Interleaving (iIL) ......: Enabled
Coded bit Interleaving (iBIL)..: Disabled
Num Parity checks (nPC, nPCwm) : 0,0
SCL List Size .................: 8
MinSum Approximation ..........: Enabled
[12]:
# Recover rate
rateRecoveredRxBlocks = polarDecoder.recoverRate(llrs)
print("Rate Recovered Shape: ", rateRecoveredRxBlocks.shape)
print("First 10 LLRs: \n", rateRecoveredRxBlocks[0,:10])
# Compare with Matlab
rateRecoveredRxBlocksMatlab = scipy.io.loadmat(matlabFilesPath+'/decIn.mat')['decIn'].T
print("Matlab First 10 LLRs: \n", rateRecoveredRxBlocksMatlab[0,:10])
assert np.abs(rateRecoveredRxBlocks-rateRecoveredRxBlocksMatlab).max()<1e-12, "MISMATCH WITH MATLAB!!!"
print("Max Diff. with Matlab:", np.abs(rateRecoveredRxBlocks-rateRecoveredRxBlocksMatlab).max())
Rate Recovered Shape: (1, 128)
First 10 LLRs:
[-1.57039747 2.35642204 2.72080897 -4.32316924 -4.42975952 -4.25153001
1.51507488 1.05889091 -4.83619924 -2.45336219]
Matlab First 10 LLRs:
[-1.57039747 2.35642204 2.72080897 -4.32316924 -4.42975952 -4.25153001
1.51507488 1.05889091 -4.83619924 -2.45336219]
Max Diff. with Matlab: 3.552713678800501e-15
[13]:
# Decode the rate-recovered transport blocks
decTxBlock, numCrcErrors = polarDecoder.decode(rateRecoveredRxBlocks)
print("Number of CRC Errors: ", numCrcErrors)
print("Decoded Transport Block Shape: ", decTxBlock.shape)
print("Decoded Transport Block: ", "".join(str(x) for x in decTxBlock))
print("Original Transport Block: ", "".join(str(x) for x in txpBlock))
# Compare with Matlab
decTxBlockMatlab = scipy.io.loadmat(matlabFilesPath+'/decBits.mat')['decBits'].reshape(-1)[:payloadLen]
print("Matlab Decoded Transport Block:", "".join(str(x) for x in decTxBlockMatlab))
assert np.abs(txpBlock-decTxBlock).sum()==0, "MISMATCH WITH MATLAB!!!"
Number of CRC Errors: 0
Decoded Transport Block Shape: (30,)
Decoded Transport Block: 100100110110000110100110000010
Original Transport Block: 100100110110000110100110000010
Matlab Decoded Transport Block: 100100110110000110100110000010
[ ]:
[ ]: