[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] [gnuradio] 09/39: fec: LDPC: Adding scripts to generat
From: |
git |
Subject: |
[Commit-gnuradio] [gnuradio] 09/39: fec: LDPC: Adding scripts to generate matrices for encoder. |
Date: |
Thu, 15 Oct 2015 21:21:26 +0000 (UTC) |
This is an automated email from the git hooks/post-receive script.
jcorgan pushed a commit to branch master
in repository gnuradio.
commit 27871a568e51ca6e196ccb7b8415f892b6c8a843
Author: tracierenea <address@hidden>
Date: Sat Jul 12 13:46:17 2014 -0500
fec: LDPC: Adding scripts to generate matrices for encoder.
Adding python scripts which generate parity check matrices for use
with the LDPC Richardson Urbanke encoder. A significant amount of
matrix manipulation is required, so this process should be done before
using the encoder at run time. For large matrices, it will take quite
a while.
---
gr-fec/python/fec/LDPC/Generate_LDPC_matrix.py | 79 +++
.../fec/LDPC/Generate_LDPC_matrix_functions.py | 619 +++++++++++++++++++++
2 files changed, 698 insertions(+)
diff --git a/gr-fec/python/fec/LDPC/Generate_LDPC_matrix.py
b/gr-fec/python/fec/LDPC/Generate_LDPC_matrix.py
new file mode 100644
index 0000000..c815682
--- /dev/null
+++ b/gr-fec/python/fec/LDPC/Generate_LDPC_matrix.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+#
+# Copyright 2014 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from Generate_LDPC_matrix_functions import *
+
+# This is an example of how to generate a parity check matrix for
+# use with the LDPC Richardson Urbanke encoder. A significant amount
+# of matrix manipulation is required, so this process should be done
+# before using the encoder at run-time. This process can take quite
+# a while, with more time required for larger matrices.
+
+# Not all attempts to create a parity check matrix will be
+# successful. The script will terminate and output error messages
+# when the process fails. To increase verbosity, edit the verbose
+# variable at the top of Generate_LDPC_matrix_functions.py.
+
+# Because random number generation and
+# shuffling methods are used, it is not possible to predict what
+# starting conditions will result in success. It requires a bit of
+# trial and error.
+
+# ----------------------------------------------------------------- #
+
+# First, generate a regular LDPC parity check matrix. Specify
+# the properties desired. For example:
+n = 200 # number of columns, corresponds to codeword length
+p = 3 # column weight
+q = 5 # row weight
+
+parity_check_matrix = LDPC_matrix(n_p_q = [n,p,q])
+
+# Richardson and Urbanke's preprocessing method requires a full rank
+# matrix to start. The matrices generated by the
+# regular_LDPC_code_contructor function will never be full rank. So,
+# use the get_full_rank_H_matrix function.
+newH = get_full_rank_H_matrix(parity_check_matrix.H)
+
+# At this point, the matrix is no longer regular. (The row/column
+# weights are not the same for all rows/columns.)
+
+# Next, some preprocessing steps need to be performed as described
+# Richardson and Urbanke in Modern Coding Theory, Appendix A. This
+# can take a while...
+[bestH,g] = get_best_matrix(newH,100)
+
+# Print out some of the resulting properties.
+n = bestH.shape[1]
+k = n - bestH.shape[0]
+print "Parity check matrix properties:"
+print "\tSize :", bestH.shape
+print "\tRank :", linalg.matrix_rank(bestH)
+print "\tRate : %.3f" % ((k*1.0)/n)
+print "\tn :", n, " (codeword length)"
+print "\tk :", k, " (info word length)"
+print "\tgap : %i" % g
+
+# Save the matrix to an alist file for future use:
+alist_filename = "n_%04i_k_%04i_gap_%02i.alist" % (n,k,g)
+parity_check_matrix.write_alist_file(alist_filename,bestH)
+print '\nMatrix saved to alist file:', alist_filename, "\n"
\ No newline at end of file
diff --git a/gr-fec/python/fec/LDPC/Generate_LDPC_matrix_functions.py
b/gr-fec/python/fec/LDPC/Generate_LDPC_matrix_functions.py
new file mode 100644
index 0000000..85f8ce9
--- /dev/null
+++ b/gr-fec/python/fec/LDPC/Generate_LDPC_matrix_functions.py
@@ -0,0 +1,619 @@
+#!/usr/bin/env python
+#
+# Copyright 2014 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import string
+from numpy import *
+from numpy.random import shuffle, randint
+from numpy.linalg import inv, det
+
+# 0 gives no debug output, 1 gives a little, 2 gives a lot
+verbose = 0
+
+class LDPC_matrix:
+ """ Class for a LDPC parity check matrix """
+ def __init__(self, alist_filename = None,
+ n_p_q = None,
+ H_matrix = None):
+ if (alist_filename != None):
+ self.H = self.read_alist_file(alist_filename)
+ elif (n_p_q != None):
+ self.H = self.regular_LDPC_code_contructor(n_p_q)
+ elif (H_matrix != None):
+ self.H = H_matrix
+ else:
+ print 'Error: provide either an alist filename,',
+ print 'parameters for constructing regular LDPC parity',
+ print 'check matrix, or a numpy array.'
+
+ self.rank = linalg.matrix_rank(self.H)
+ self.numRows = self.H.shape[0]
+ self.n = self.H.shape[1]
+ self.k = self.n -self.numRows
+
+ def read_alist_file(self,filename):
+ """
+ This function reads in an alist file and creates the
+ corresponding parity check matrix H. The format of alist
+ files is described at:
+ http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html
+ """
+
+ myfile = open(filename,'r')
+ data = myfile.readlines()
+ size = string.split(data[0])
+ numCols = int(size[0])
+ numRows = int(size[1])
+ H = zeros((numRows,numCols))
+ for lineNumber in arange(4,4+numCols):
+ indices = string.split(data[lineNumber])
+ for index in indices:
+ H[int(index)-1,lineNumber-4] = 1
+ # The subsequent lines in the file list the indices for where
+ # the 1s are in the rows, but this is redundant
+ # information.
+
+ return H
+
+ def write_alist_file(self,filename,H,verbose=0):
+ """
+ This function writes an alist file for the parity check
+ matrix. The format of alist files is desribed at:
+ http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html
+ """
+
+ myfile = open(filename,'w')
+
+ numRows = H.shape[0]
+ numCols = H.shape[1]
+
+ tempstring = `numCols` + ' ' + `numRows` + '\n'
+ myfile.write(tempstring)
+
+ tempstring1 = ''
+ tempstring2 = ''
+ maxRowWeight = 0
+ for rowNum in arange(numRows):
+ nonzeros = array(H[rowNum,:].nonzero())
+ rowWeight = nonzeros.shape[1]
+ if rowWeight > maxRowWeight:
+ maxRowWeight = rowWeight
+ tempstring1 = tempstring1 + `rowWeight` + ' '
+ for tempArray in nonzeros:
+ for index in tempArray:
+ tempstring2 = tempstring2 + `index+1` + ' '
+ tempstring2 = tempstring2 + '\n'
+ tempstring1 = tempstring1 + '\n'
+
+ tempstring3 = ''
+ tempstring4 = ''
+ maxColWeight = 0
+ for colNum in arange(numCols):
+ nonzeros = array(H[:,colNum].nonzero())
+ colWeight = nonzeros.shape[1]
+ if colWeight > maxColWeight:
+ maxColWeight = colWeight
+ tempstring3 = tempstring3 + `colWeight` + ' '
+ for tempArray in nonzeros:
+ for index in tempArray:
+ tempstring4 = tempstring4 + `index+1` + ' '
+ tempstring4 = tempstring4 + '\n'
+ tempstring3 = tempstring3 + '\n'
+
+ tempstring = `maxColWeight` + ' ' + `maxRowWeight` + '\n'
+ # write out max column and row weights
+ myfile.write(tempstring)
+ # write out all of the column weights
+ myfile.write(tempstring3)
+ # write out all of the row weights
+ myfile.write(tempstring1)
+ # write out the nonzero indices for each column
+ myfile.write(tempstring4)
+ # write out the nonzero indices for each row
+ myfile.write(tempstring2)
+ # close the file
+ myfile.close()
+
+ def regular_LDPC_code_contructor(self,n_p_q):
+ """
+ This function constructs a LDPC parity check matrix
+ H. The algorithm follows Gallager's approach where we create
+ p submatrices and stack them together. Reference: Turbo
+ Coding for Satellite and Wireless Communications, section
+ 9,3.
+
+ Note: the matrices computed from this algorithm will never
+ have full rank. (Reference Gallager's Dissertation.) They
+ will have rank = (number of rows - p + 1). To convert it
+ to full rank, use the function get_full_rank_H_matrix
+ """
+
+ n = n_p_q[0] # codeword length
+ p = n_p_q[1] # column weight
+ q = n_p_q[2] # row weight
+ # TODO: There should probably be other guidelines for n/p/q,
+ # but I have not found any specifics in the literature....
+
+ # For this algorithm, n/p must be an integer, because the
+ # number of rows in each submatrix must be a whole number.
+ ratioTest = (n*1.0)/q
+ if ratioTest%1 != 0:
+ print '\nError in regular_LDPC_code_contructor: The'
+ print 'ratio of inputs n/q must be a whole number.\n'
+ return
+
+ # First submatrix first:
+ m = (n*p)/q # number of rows in H matrix
+ submatrix1 = zeros((m/p,n))
+ for row in arange(m/p):
+ range1 = row*q
+ range2 = (row+1)*q
+ submatrix1[row,range1:range2] = 1
+ H = submatrix1
+
+ # Create the other submatrices and vertically stack them on.
+ submatrixNum = 2
+ newColumnOrder = arange(n)
+ while submatrixNum <= p:
+ submatrix = zeros((m/p,n))
+ shuffle(newColumnOrder)
+
+ for columnNum in arange(n):
+ submatrix[:,columnNum] = \
+ submatrix1[:,newColumnOrder[columnNum]]
+
+ H = vstack((H,submatrix))
+ submatrixNum = submatrixNum + 1
+
+ # Double check the row weight and column weights.
+ size = H.shape
+ rows = size[0]
+ cols = size[1]
+
+ # Check the row weights.
+ for rowNum in arange(rows):
+ nonzeros = array(H[rowNum,:].nonzero())
+ if nonzeros.shape[1] != q:
+ print 'Row', rowNum, 'has incorrect weight!'
+ return
+
+ # Check the column weights
+ for columnNum in arange(cols):
+ nonzeros = array(H[:,columnNum].nonzero())
+ if nonzeros.shape[1] != p:
+ print 'Row', columnNum, 'has incorrect weight!'
+ return
+
+ return H
+
+def greedy_upper_triangulation(H):
+ """
+ This function performs row/column permutations to bring
+ H into approximate upper triangular form via greedy
+ upper triangulation method outlined in Modern Coding
+ Theory Appendix 1, Section A.2
+ """
+ H_t = H.copy()
+
+ # Per email from Dr. Urbanke, author of this textbook, this
+ # algorithm requires H to be full rank
+ if linalg.matrix_rank(H_t) != H_t.shape[0]:
+ print 'Rank of H:',linalg.matrix_rank(tempArray)
+ print 'H has', H_t.shape[0], 'rows'
+ print 'Error: H must be full rank.'
+ return
+
+ size = H_t.shape
+ n = size[1]
+ k = n - size[0]
+ g = t = 0
+
+ while t != (n-k-g):
+ H_residual = H_t[t:n-k-g,t:n]
+ size = H_residual.shape
+ numRows = size[0]
+ numCols = size[1]
+
+ minResidualDegrees = zeros((1,numCols))
+
+ for colNum in arange(numCols):
+ nonZeroElements = array(H_residual[:,colNum].nonzero())
+ minResidualDegrees[0,colNum] = nonZeroElements.shape[1]
+
+ # Find the minimum nonzero residual degree
+ nonZeroElementIndices = minResidualDegrees.nonzero()
+ nonZeroElements=minResidualDegrees[nonZeroElementIndices[0],\
+ nonZeroElementIndices[1]]
+ minimumResidualDegree = nonZeroElements.min()
+
+ # Get indices of all of the columns in H_t that have degree
+ # equal to the min positive residual degree, then pick a
+ # random column c.
+ indices = (minResidualDegrees == minimumResidualDegree)\
+ .nonzero()[1]
+ indices = indices + t
+ if indices.shape[0] == 1:
+ columnC = indices[0]
+ else:
+ randomIndex = randint(0,indices.shape[0],(1,1))[0][0]
+ columnC = indices[randomIndex]
+
+ Htemp = H_t.copy()
+
+ if minimumResidualDegree == 1:
+ # This is the 'extend' case
+ rowThatContainsNonZero = H_residual[:,columnC-t]\
+ .nonzero()[0][0]
+
+ # Swap column c with column t. (Book says t+1 but we
+ # index from 0, not 1.)
+ Htemp[:,columnC] = H_t[:,t]
+ Htemp[:,t] = H_t[:,columnC]
+ H_t = Htemp.copy()
+ Htemp = H_t.copy()
+ # Swap row r with row t. (Book says t+1 but we index from
+ # 0, not 1.)
+ Htemp[rowThatContainsNonZero + t,:] = H_t[t,:]
+ Htemp[t,:] = H_t[rowThatContainsNonZero + t,:]
+ H_t = Htemp.copy()
+ Htemp = H_t.copy()
+ else:
+ # This is the 'choose' case.
+ rowsThatContainNonZeros = H_residual[:,columnC-t]\
+ .nonzero()[0]
+
+ # Swap column c with column t. (Book says t+1 but we
+ # index from 0, not 1.)
+ Htemp[:,columnC] = H_t[:,t]
+ Htemp[:,t] = H_t[:,columnC]
+ H_t = Htemp.copy()
+ Htemp = H_t.copy()
+
+ # Swap row r1 with row t
+ r1 = rowsThatContainNonZeros[0]
+ Htemp[r1+t,:] = H_t[t,:]
+ Htemp[t,:] = H_t[r1+t,:]
+ numRowsLeft = rowsThatContainNonZeros.shape[0]-1
+ H_t = Htemp.copy()
+ Htemp = H_t.copy()
+
+ # Move the other rows that contain nonZero entries to the
+ # bottom of the matrix. We can't just swap them,
+ # otherwise we will be pulling up rows that we pushed
+ # down before. So, use a rotation method.
+ for index in arange (1,numRowsLeft+1):
+ rowInH_residual = rowsThatContainNonZeros[index]
+ rowInH_t = rowInH_residual + t - index +1
+ m = n-k
+ # Move the row with the nonzero element to the
+ # bottom; don't update H_t.
+ Htemp[m-1,:] = H_t[rowInH_t,:]
+ # Now rotate the bottom rows up.
+ sub_index = 1
+ while sub_index < (m - rowInH_t):
+ Htemp[m-sub_index-1,:] = H_t[m-sub_index,:]
+ sub_index = sub_index+1
+ H_t = Htemp.copy()
+ Htemp = H_t.copy()
+
+ # Save temp H as new H_t.
+ H_t = Htemp.copy()
+ Htemp = H_t.copy()
+ g = g + (minimumResidualDegree - 1)
+
+ t = t + 1
+
+ if g == 0:
+ if verbose: print 'Error: gap is 0.'
+ return
+
+ # We need to ensure phi is nonsingular.
+ T = H_t[0:t, 0:t]
+ E = H_t[t:t+g,0:t]
+ A = H_t[0:t,t:t+g]
+ C = H_t[t:t+g,t:t+g]
+ D = H_t[t:t+g,t+g:n]
+
+ invTmod2array = inv_mod2(T)
+ temp1 = dot(E,invTmod2array) % 2
+ temp2 = dot(temp1,A) % 2
+ phi = (C - temp2) % 2
+ if phi.any():
+ try:
+ # Try to take the inverse of phi.
+ invPhi = inv_mod2(phi)
+ except linalg.linalg.LinAlgError:
+ # Phi is singular
+ if verbose > 1: print 'Initial phi is singular'
+ else:
+ # Phi is nonsingular, so we need to use this version of H.
+ if verbose > 1: print 'Initial phi is nonsingular'
+ return [H_t, g, t]
+ else:
+ if verbose: print 'Initial phi is all zeros:\n', phi
+
+ # If the C and D submatrices are all zeros, there is no point in
+ # shuffling them around in an attempt to find a good phi.
+ if not (C.any() or D.any()):
+ if verbose:
+ print 'C and D are all zeros. There is no hope in',
+ print 'finding a nonsingular phi matrix. '
+ return
+
+ # We can't look at every row/column permutation possibility
+ # because there would be (n-t)! column shuffles and g! row
+ # shuffles. g has gotten up to 12 in tests, so 12! would still
+ # take quite some time. Instead, we will just pick an arbitrary
+ # number of max iterations to perform, then break.
+ maxIterations = 300
+ iterationCount = 0
+ columnsToShuffle = arange(t,n)
+ rowsToShuffle = arange(t,t+g)
+
+ while iterationCount < maxIterations:
+ if verbose > 1: print 'iterationCount:', iterationCount
+ tempH = H_t.copy()
+
+ shuffle(columnsToShuffle)
+ shuffle(rowsToShuffle)
+ index = 0
+ for newDestinationColumnNumber in arange(t,n):
+ oldColumnNumber = columnsToShuffle[index]
+ tempH[:,newDestinationColumnNumber] = \
+ H_t[:,oldColumnNumber]
+ index +=1
+
+ tempH2 = tempH.copy()
+ index = 0
+ for newDesinationRowNumber in arange(t,t+g):
+ oldRowNumber = rowsToShuffle[index]
+ tempH[newDesinationRowNumber,:] = tempH2[oldRowNumber,:]
+ index +=1
+
+ # Now test this new H matrix.
+ H_t = tempH.copy()
+ T = H_t[0:t, 0:t]
+ E = H_t[t:t+g,0:t]
+ A = H_t[0:t,t:t+g]
+ C = H_t[t:t+g,t:t+g]
+ invTmod2array = inv_mod2(T)
+ temp1 = dot(E,invTmod2array) % 2
+ temp2 = dot(temp1,A) % 2
+ phi = (C - temp2) % 2
+ if phi.any():
+ try:
+ # Try to take the inverse of phi.
+ invPhi = inv_mod2(phi)
+ except linalg.linalg.LinAlgError:
+ # Phi is singular
+ if verbose > 1: print 'Phi is still singular'
+ else:
+ # Phi is nonsingular, so we're done.
+ if verbose:
+ print 'Found a nonsingular phi on',
+ print 'iterationCount = ', iterationCount
+ return [H_t, g, t]
+ else:
+ if verbose > 1: print 'phi is all zeros'
+
+ iterationCount +=1
+
+ # If we've reached this point, then we haven't found a
+ # version of H that has a nonsingular phi.
+ if verbose: print '--- Error: nonsingular phi matrix not found.'
+
+
+def inv_mod2(squareMatrix):
+ """
+ Calculates the mod 2 inverse of a matrix.
+ """
+ A = squareMatrix.copy()
+ t = A.shape[0]
+
+ # Special case for one element array [1]
+ if A.size == 1 and A[0] == 1:
+ return array([1])
+
+ Ainverse = inv(A)
+ B = det(A)*Ainverse
+ C = B % 2
+
+ # Encountered lots of rounding errors with this function.
+ # Previously tried floor, C.astype(int), and casting with (int)
+ # and none of that works correctly, so doing it the tedious way.
+
+ test = dot(A,C) % 2
+ tempTest = zeros_like(test)
+ for colNum in arange(test.shape[1]):
+ for rowNum in arange(test.shape[0]):
+ value = test[rowNum,colNum]
+ if (abs(1-value)) < 0.01:
+ # this is a 1
+ tempTest[rowNum,colNum] = 1
+ elif (abs(2-value)) < 0.01:
+ # there shouldn't be any 2s after B % 2, but I'm
+ # seeing them!
+ tempTest[rowNum,colNum] = 0
+ elif (abs(0-value)) < 0.01:
+ # this is a 0
+ tempTest[rowNum,colNum] = 0
+ else:
+ if verbose > 1:
+ print 'In inv_mod2. Rounding error on this',
+ print 'value? Mod 2 has already been done.',
+ print 'value:', value
+
+ test = tempTest.copy()
+
+ if (test - eye(t,t) % 2).any():
+ if verbose:
+ print 'Error in inv_mod2: did not find inverse.'
+ # TODO is this the most appropriate error to raise?
+ raise linalg.linalg.LinAlgError
+ else:
+ return C
+
+def swap_columns(a,b,arrayIn):
+ """
+ Swaps two columns in a matrix.
+ """
+ arrayOut = arrayIn.copy()
+ arrayOut[:,a] = arrayIn[:,b]
+ arrayOut[:,b] = arrayIn[:,a]
+ return arrayOut
+
+def move_row_to_bottom(i,arrayIn):
+ """"
+ Moves a specified row (just one) to the bottom of the matrix,
+ then rotates the rows at the bottom up.
+
+ For example, if we had a matrix with 5 rows, and we wanted to
+ push row 2 to the bottom, then the resulting row order would be:
+ 1,3,4,5,2
+ """
+ arrayOut = arrayIn.copy()
+ numRows = arrayOut.shape[0]
+ # Push the specified row to the bottom.
+ arrayOut[numRows-1] = arrayIn[i,:]
+ # Now rotate the bottom rows up.
+ index = 2
+ while (numRows-index) >= i:
+ arrayOut[numRows-index,:] = arrayIn[numRows-index+1]
+ index = index + 1
+ return arrayOut
+
+def get_full_rank_H_matrix(H):
+ """
+ This function accepts a parity check matrix H and, if it is not
+ already full rank, will determine which rows are dependent and
+ remove them. The updated matrix will be returned.
+ """
+ tempArray = H.copy()
+ if linalg.matrix_rank(tempArray) == tempArray.shape[0]:
+ if verbose > 1: print 'Returning H; it is already full rank.'
+ return tempArray
+
+ numRows = tempArray.shape[0]
+ numColumns = tempArray.shape[1]
+ limit = numRows
+ rank = 0
+ i = 0
+
+ # Create an array to save the column permutations.
+ columnOrder = arange(numColumns).reshape(1,numColumns)
+
+ # Create an array to save the row permutations. We just need
+ # this to know which dependent rows to delete.
+ rowOrder = arange(numRows).reshape(numRows,1)
+
+ while i < limit:
+ if verbose > 1: print 'In get_full_rank_H_matrix; i:', i
+ # Flag indicating that the row contains a non-zero entry
+ found = False
+ for j in arange(i, numColumns):
+ if tempArray[i, j] == 1:
+ # Encountered a non-zero entry at (i, j)
+ found = True
+ # Increment rank by 1
+ rank = rank + 1
+ # Make the entry at (i,i) be 1
+ tempArray = swap_columns(j,i,tempArray)
+ # Keep track of the column swapping
+ columnOrder = swap_columns(j,i,columnOrder)
+ break
+ if found == True:
+ for k in arange(0,numRows):
+ if k == i: continue
+ # Checking for 1's
+ if tempArray[k, i] == 1:
+ # Add row i to row k
+ tempArray[k,:] = tempArray[k,:] + tempArray[i,:]
+ # Addition is mod2
+ tempArray = tempArray.copy() % 2
+ # All the entries above & below (i, i) are now 0
+ i = i + 1
+ if found == False:
+ # Push the row of 0s to the bottom, and move the bottom
+ # rows up (sort of a rotation thing).
+ tempArray = move_row_to_bottom(i,tempArray)
+ # Decrease limit since we just found a row of 0s
+ limit -= 1
+ # Keep track of row swapping
+ rowOrder = move_row_to_bottom(i,rowOrder)
+
+ # Don't need the dependent rows
+ finalRowOrder = rowOrder[0:i]
+
+ # Reorder H, per the permutations taken above .
+ # First, put rows in order, omitting the dependent rows.
+ newNumberOfRowsForH = finalRowOrder.shape[0]
+ newH = zeros((newNumberOfRowsForH, numColumns))
+ for index in arange(newNumberOfRowsForH):
+ newH[index,:] = H[finalRowOrder[index],:]
+
+ # Next, put the columns in order.
+ tempHarray = newH.copy()
+ for index in arange(numColumns):
+ newH[:,index] = tempHarray[:,columnOrder[0,index]]
+
+ if verbose:
+ print 'original H.shape:', H.shape
+ print 'newH.shape:', newH.shape
+
+ return newH
+
+def get_best_matrix(H,numIterations=100):
+ """
+ This function will run the Greedy Upper Triangulation algorithm
+ for numIterations times, looking for the lowest possible gap.
+ The submatrices returned are those needed for real-time encoding.
+ """
+
+ hadFirstJoy = 0
+ index = 1
+ while index <= numIterations:
+ if verbose:
+ print '--- In get_best_matrix, index:', index
+ try:
+ [betterH, gap, t] = greedy_upper_triangulation(H)
+ except:
+ if verbose > 1:
+ print 'greedy_upper_triangulation must have had error'
+ else:
+ if not hadFirstJoy:
+ hadFirstJoy = 1
+ bestGap = gap
+ bestH = betterH.copy()
+ bestT = t
+ elif gap < bestGap:
+ bestGap = gap
+ bestH = betterH.copy()
+ bestT = t
+
+ index += 1
+
+ if hadFirstJoy:
+ return [bestH,bestGap]
+ else:
+ if verbose:
+ print 'Error: Could not find appropriate H form',
+ print 'for encoding.'
+ return
- [Commit-gnuradio] [gnuradio] branch master updated (77083c5 -> 616fee5), git, 2015/10/15
- [Commit-gnuradio] [gnuradio] 03/39: fec: LDPC: Renaming some files., git, 2015/10/15
- [Commit-gnuradio] [gnuradio] 12/39: fec: LDPC: Improving memory management (GSL matrices)., git, 2015/10/15
- [Commit-gnuradio] [gnuradio] 11/39: fec: LDPC: Fixing simple, but crucial, error in decoder. doh!, git, 2015/10/15
- [Commit-gnuradio] [gnuradio] 06/39: fec: LDPC: Adding bit flip decoder variable work function., git, 2015/10/15
- [Commit-gnuradio] [gnuradio] 15/39: fec: LDPC: Change GRC block name text to match new class name., git, 2015/10/15
- [Commit-gnuradio] [gnuradio] 19/39: fec: LDPC: renaming some of the LDPC classes for clarity/consistency., git, 2015/10/15
- [Commit-gnuradio] [gnuradio] 09/39: fec: LDPC: Adding scripts to generate matrices for encoder.,
git <=
- [Commit-gnuradio] [gnuradio] 18/39: fec: LDPC: Updates to LDPC-related matrix classes., git, 2015/10/15
- [Commit-gnuradio] [gnuradio] 01/39: fec: LDPC: Adding class for LDPC parity check matrix., git, 2015/10/15
- [Commit-gnuradio] [gnuradio] 16/39: fec: LDPC: updates for LDPC functionality., git, 2015/10/15
- [Commit-gnuradio] [gnuradio] 22/39: fec: LDPC: Updating decoder to handle parity bits either first or last., git, 2015/10/15
- [Commit-gnuradio] [gnuradio] 28/39: qtgui: fixes calculation of BPSK BER curve., git, 2015/10/15
- [Commit-gnuradio] [gnuradio] 05/39: fec: LDPC: Adding LDPC encoder variable., git, 2015/10/15
- [Commit-gnuradio] [gnuradio] 34/39: fec: LDPC: changing namespace of ldpc_encoder back., git, 2015/10/15
- [Commit-gnuradio] [gnuradio] 30/39: fec: Updated docs for Forward Error Correction section in manual., git, 2015/10/15
- [Commit-gnuradio] [gnuradio] 32/39: fec: LDPC: removing apps until we can fix them up properly., git, 2015/10/15
- [Commit-gnuradio] [gnuradio] 35/39: fec: LDPC: better docs describing encoder/decoders and how to use., git, 2015/10/15