def inverse(mat: Matrix) -> Matrix: """returns the inverse matrix of mat :param mat: the matrix to invert :type mat: Matrix :return: the inverse matrix of mat :rtype: Matrix """ assert mat._is_square() return linsolve(mat, identity(mat.shape[0]))
def identity(n: int) -> Matrix: """generates an n by n identity matrix :param n: number of rows/columns :type n: int :return: n by b indentity matrix :rtype: Matrix """ id = [[int(i == j) for j in range(n)] for i in range(n)] return Matrix(id)
def zeroes(i: int, j: int) -> Matrix: """creates an i by j zero matrix :param i: number of columns :type i: int :param j: number of rows :type j: int :return: an i by j matrix filled with zeroes :rtype: Matrix """ return Matrix([[0] * j for _ in range(i)], valid=True)
def as_matrix(ls: list) -> Matrix: """ Parses the input 2D list into a Matrix. Convenience top-level function for linalg.matrix.Matrix() :param ls: list to convert into matrix :type ls: list :return: Matrix represtation of ls :rtype: Matrix """ return Matrix(ls)
def transpose(mat: Matrix) -> Matrix: """ computes the transpose of a given matrix :param mat: matrix to perform the operation on :type mat: Matrix :return: transposed matrix :rtype: Matrix """ x, y = mat.shape return Matrix([[mat[a][b] for a in range(y)] for b in range(x)])
def det(mat: Matrix) -> float: """computes the determinant for a given matrix :param mat: matrix to compute the determinant for :type mat: Matrix :return: the determinant for mat :rtype: float """ assert mat._is_square() L, U, P, S = lu(mat) n = mat.shape[0] l_pd, u_pd = 1, 1 for i in range(n): l_pd *= L[i][i] u_pd *= U[i][i] return (-1) ** S * l_pd * u_pd
def random_matrix(dim: tuple, rng: tuple, use_float: bool = False) -> Matrix: """generates a random matrix :param dim: dimensions of matrix :type dim: tuple :param rng: range of randomized elements :type rng: tuple :param float: whether to use floats for elements (default False) :type float: bool :return: randomized matrix of specified size and range :rtype: Matrix """ ls = [[random.uniform(*rng) for _ in range(dim[1])] for _ in range(dim[0])] if not use_float: ls = [[round(x) for x in row] for row in ls] return Matrix(ls)
def pivotize(mat: Matrix) -> (Matrix, int): """creates the pivoting matrix for mat :param mat: the matrix to perform the operation on :type mat: Matrix :return: the pivoting matrix for self and the number of permutations :rtype: Matrix, int """ assert mat._is_square() n = mat.shape[0] S = 0 a = identity(n) for j in range(n): row = max(range(j, n), key=lambda i: abs(mat[i][j])) if j != row: S += 1 a[j], a[row] = a[row], a[j] return a, S
def lu(mat: Matrix) -> (Matrix, Matrix, Matrix, int): """implements LUP decomposition :return: returns a tuple with L, U, and P :rtype: Matrix, Matrix, Matrix, int """ assert mat._is_square() n = mat.shape[0] L, U = zeroes(n, n), zeroes(n, n) P, S = linalg.unary.pivotize(mat) A2 = P @ mat for j in range(n): L[j][j] = 1 for i in range(j + 1): s1 = sum(U[k][j] * L[i][k] for k in range(i)) U[i][j] = A2[i][j] - s1 for i in range(j, n): s2 = sum(U[k][j] * L[i][k] for k in range(j)) L[i][j] = (A2[i][j] - s2) / U[j][j] return L, U, P, S