drdot
drdot

Reputation: 3347

Create and invert large Galois field matrix

I have a matrix of size 128x128. Each entry is a binary field element (in my use case, only 0 and 1). I try to invert this matrix in matlab. I find some functions in matlab that does finite field matrix inversion here http://www.mathworks.com/help/comm/galois-field-computations.html.

However, these built-in functions only support matrix size upto 16x16. Any other methods that can overcome this limit? I an open to other tools such as python or C/C++.

If you would like to try out your method, here are the test matrix and its inverse.

Matrix A [0,0,0,1,0,0,1,0;1,1,1,0,1,0,1,1;1,1,1,0,1,1,0,1;0,1,0,0,0,0,1,0;0,1,1,1,1,1,1,0;1,0,1,1,0,0,1,0;0,0,1,0,0,0,1,0;0,0,0,0,0,1,0,0]

Matrix A^-1 [1,1,1,0,0,1,1,1;0,1,1,1,0,0,0,1;0,1,1,0,0,0,1,1;1,1,1,0,0,0,0,1;1,0,0,1,1,0,1,1;0,0,0,0,0,0,0,1;0,1,1,0,0,0,0,1;0,1,0,0,1,1,1,1]

Upvotes: 2

Views: 2304

Answers (1)

Matt Hostetter
Matt Hostetter

Reputation: 580

Inverting a matrix over a Galois field can be accomplished by performing Gaussian elimination (with all arithmetic performed in the Galois field) on [A | I], which results in [I | A^-1].

Here is some pseudocode to perform the Gaussian elimination (row reduction).

def row_reduce(A):
    A_rre = A.copy()
    p = 0  # The pivot

    for j in range(A.shape[1]):
        # Find a pivot in column `j` at or below row `p`
        idxs = np.nonzero(A_rre[p:,j])[0]
        if idxs.size == 0:
            continue
        i = p + idxs[0]  # Row with a pivot

        # Swap row `p` and `i`. The pivot is now located at row `p`.
        A_rre[[p,i],:] = A_rre[[i,p],:]

        # Force pivot value to be 1
        A_rre[p,:] /= A_rre[p,j]

        # Force zeros above and below the pivot
        idxs = np.nonzero(A_rre[:,j])[0].tolist()
        idxs.remove(p)
        A_rre[idxs,:] -= np.multiply.outer(A_rre[idxs,j], A_rre[p,:])

        p += 1
        if p == A_rre.shape[0]:
            break

    return A_rre

I had this use case, and couldn't find a Python library that accomplished this. So I created a Python package galois that extends NumPy arrays over Galois fields. It supports linear algebra using the normal np.linalg functions.

Here is an example using your test matrices.

In [1]: import numpy as np                                                                              

In [2]: import galois                                                                                   

In [3]: GF = galois.GF(2)                                                                               

In [4]: A = GF([[0,0,0,1,0,0,1,0],[1,1,1,0,1,0,1,1],[1,1,1,0,1,1,0,1],[0,1,0,0,0,0,1,0],[0,1,1,1,1,1,1,0
   ...: ],[1,0,1,1,0,0,1,0],[0,0,1,0,0,0,1,0],[0,0,0,0,0,1,0,0]]); A                                    
Out[4]: 
GF([[0, 0, 0, 1, 0, 0, 1, 0],
    [1, 1, 1, 0, 1, 0, 1, 1],
    [1, 1, 1, 0, 1, 1, 0, 1],
    [0, 1, 0, 0, 0, 0, 1, 0],
    [0, 1, 1, 1, 1, 1, 1, 0],
    [1, 0, 1, 1, 0, 0, 1, 0],
    [0, 0, 1, 0, 0, 0, 1, 0],
    [0, 0, 0, 0, 0, 1, 0, 0]], order=2)

In [5]: A_inv = np.linalg.inv(A); A_inv                                                                 
Out[5]: 
GF([[1, 1, 1, 0, 0, 1, 1, 1],
    [0, 1, 1, 1, 0, 0, 0, 1],
    [0, 1, 1, 0, 0, 0, 1, 1],
    [1, 1, 1, 0, 0, 0, 0, 1],
    [1, 0, 0, 1, 1, 0, 1, 1],
    [0, 0, 0, 0, 0, 0, 0, 1],
    [0, 1, 1, 0, 0, 0, 0, 1],
    [0, 1, 0, 0, 1, 1, 1, 1]], order=2)

In [6]: A @ A_inv                                                                                       
Out[6]: 
GF([[1, 0, 0, 0, 0, 0, 0, 0],
    [0, 1, 0, 0, 0, 0, 0, 0],
    [0, 0, 1, 0, 0, 0, 0, 0],
    [0, 0, 0, 1, 0, 0, 0, 0],
    [0, 0, 0, 0, 1, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 0, 0],
    [0, 0, 0, 0, 0, 0, 1, 0],
    [0, 0, 0, 0, 0, 0, 0, 1]], order=2)

Upvotes: 3

Related Questions