예제 #1
0
def solve_singular_case(A: nmod_mat) -> nmod_mat:
    """
    Return a solution for a singular set of equations.
    The system may be singular because there are
    multiple solutions. In this case I will return
    a particular solution.
    If the solution does not exist raise a NoSolution
    exception.
    """
    nrows = A.nrows()
    ncols = A.ncols()
    null_count = count_null_rows(A)
    if null_count == 0:
        raise NoSolutionError()
    # a solution exists create a return value with all zeros
    X = nmod_mat(ncols - 1, 1, A.modulus())
    # starting at the bottom, skip over the null rows
    for row in range(nrows - null_count - 1, -1, -1):
        col = find_leading_one(A, row)
        # pick off the value of the solution from the last column
        X[col, 0] = A[row, ncols - 1]
        # back substitute this row on the remaining rows
        for row1 in range(row - 1, -1, -1):
            f = A[row1, col]
            A[row1, col] = 0
            for col1 in range(col + 1, ncols):
                A[row1, col1] -= f * A[row, col1]
    return X
예제 #2
0
        def flint_matmult(a: np.ndarray, b: np.ndarray) -> np.ndarray:
            from flint import nmod_mat, fmpz_mat
            if self.use_mod:
                a = nmod_mat(a.tolist(), MOD)
                b = nmod_mat(b.tolist(), MOD)
            else:
                a = fmpz_mat(a.tolist())
                b = fmpz_mat(b.tolist())

            y = a * b
            z = [
                list(map(int,
                         _.strip('][').split(','))) for _ in str(y).split('\n')
            ]
            res = np.array(z, dtype=np.uint64)
            return res
예제 #3
0
def solve_system_mod(a, mod=2):
    n = len(a)
    m = len(a[0])

    A = flint.nmod_mat(n, m, a.flatten().tolist(), mod)
    A_ = A.rref()[0]
    M = np.array([np.array([int(num.str()) for num in a]) for a in A_.table()])
    M_ = M[:, :m - 1]
    b_ = M[:, m - 1]
    res = back_substitution_mod(M_, b_, mod=mod)

    return res
예제 #4
0
def create_nmod_mat(m: List[Any], p: int) -> nmod_mat:
    """
    Return the nmod_mat created from an integer matrix and prime
    This is called by test() (see below)
    """
    nrows = len(m)
    if isinstance(m[0], int):
        M = nmod_mat(nrows, 1, p)
        for row in range(nrows):
            M[row, 0] = m[row]
    elif isinstance(m[0], list):
        ncols = len(m[0])
        M = nmod_mat(nrows, ncols, p)
        for row in range(nrows):
            if len(m[row]) != ncols:
                raise ValueError
            for col in range(ncols):
                M[row, col] = m[row][col]
    else:
        raise ValueError
    return M
예제 #5
0
def solve_normal_case(A: nmod_mat) -> nmod_mat:
    """
    Completes the solution for the non-singular case
    by performing back substution on the matrix
    A which must be in echelon form comming in.
    """
    nrows = A.nrows()
    ncols = A.ncols()
    back_substitution(A)
    X = nmod_mat(nrows, 1, A.modulus())
    for i in range(nrows):
        X[i, 0] = A[i, ncols - 1]
    return X
예제 #6
0
def augment(M: nmod_mat, Y: nmod_mat) -> nmod_mat:
    """
    Create a matrix representing a set of linear
    equations by gluing on Y to the right side of M
    """
    nrows = M.nrows()
    ncols = M.ncols()
    if not (nrows > 0 and nrows == ncols):
        raise ValueError
    if not (Y.nrows() == nrows and Y.ncols() == 1):
        raise ValueError
    if not Y.modulus() == M.modulus():
        raise ValueError
    A = nmod_mat(nrows, ncols + 1, M.modulus())
    for row in range(nrows):
        for col in range(ncols):
            A[row, col] = M[row, col]
        A[row, ncols] = Y[row, 0]
    return A
예제 #7
0
def Berlekamp_Welch(
        aList: List[int],   # inputs
        bList: List[int],   # received codeword
        k: int,
        t: int,
        p: int              # prime
    ) -> nmod_poly:
    """
    Berlekamp-Welsch-Decoder

    This function throws an exception if no solution exists

    see https://en.wikipedia.org/wiki/Berlekamp%E2%80%93Welch_algorithm
    """
    if len(aList) < 1:
        raise FuzzyError("aList is empty")
    if len(aList) != len(bList):
        raise FuzzyError("bList is empty")
    if k < 1 or t < 1:
        raise FuzzyError("k={0} and t={1} are not consistent".format(k, t))
    if p < 2 or not isprime(p):
        raise FuzzyError("p is not prime")

    n = len(aList)

    # Create the Berlekamp-Welch system of equations
    # and store them as an n x n matrix 'm' and a
    # constant source vector 'y' of length n

    m_entries: List[nmod] = []
    y_entries: List[nmod] = []
    for i in range(n):
        a: int = aList[i]
        b: int = bList[i]
        apowers: List[nmod] = mod_get_powers(a, k + t, p)
        for j in range(k+t):
            m_entries.append(apowers[j])
        for j in range(t):
            m_entries.append(-b * apowers[j])
        y_entries.append(b * apowers[t])

    m: nmod_mat = nmod_mat(n, n, m_entries, p)
    y: nmod_mat = nmod_mat(n, 1, y_entries, p)

    # solve the linear system of equations m * x = y for x

    try:
        x = gauss.solve(m, y).entries()
    except gauss.NoSolutionError:
        raise FuzzyError("No solution exists")

    # create the polynomials Q and E

    Qs: List[nmod] = x[:k+t]
    Es: List[nmod] = x[k+t:]
    Es.append(nmod(1, p))
    Q: nmod_poly = nmod_poly(Qs, p)
    E: nmod_poly = nmod_poly(Es, p)

    Answer: nmod_poly = Q // E
    Remainder: nmod_poly = Q - Answer * E
    if len(Remainder.coeffs()) > 0:
        raise FuzzyError("Remainder is not zero")
    return Answer
예제 #8
0
def rref_prime(mat, p):
    res, _ = flint.nmod_mat(mat.tolist(), p).rref()
    return res.table()
예제 #9
0
 def inv(self):
     eye = flint.nmod_mat(self.arr.shape[0], self.arr.shape[1], [
         int(e)
         for e in np.eye(self.arr.shape[0], self.arr.shape[1]).flatten()
     ], 2)
     return GF2Matrix.from_flint(self.to_flint().solve(eye))
예제 #10
0
 def to_flint(self):
     return flint.nmod_mat(self.arr.shape[0], self.arr.shape[1],
                           [int(e) for e in self.arr.flatten()], 2)