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
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
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
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
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
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
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
def rref_prime(mat, p): res, _ = flint.nmod_mat(mat.tolist(), p).rref() return res.table()
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))
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)