def gram_schmidt( a: MatrixType, n: Optional[int] = None ) -> Tuple[MatrixType, List[int]]: cnt_vectors = min(a.ncols, n) if n else a.ncols q = a.copy() perm = list(range(cnt_vectors)) for j in range(0, cnt_vectors): pivot_col_idx, pivot_norm = max( ((c, norm(q[:, c])) for c in range(j, cnt_vectors)), key=lambda x: x[1] ) # Swap columns if j != pivot_col_idx: temp = q[:, j].copy() q[:, j] = q[:, pivot_col_idx] q[:, pivot_col_idx] = temp perm[pivot_col_idx], perm[j] = perm[j], perm[pivot_col_idx] # Normalize q[:, j] /= pivot_norm u = q[:, j] # Remove U component everywhere q[:, j + 1 :] -= u @ (u.T @ q[:, j + 1 :]) return q, perm
def lu_decompose(a: MatrixType) -> LuDecomposition: validate.is_true("matrix", "must be square", a.is_square()) n = a.nrows # Init lu = a.copy() perm: List[int] = list(range(a.nrows)) cnt_row_exchanges = 0 for i in range(n): # All work will be done on sub-matrix lu[i:, i:] pivot_row_idx, pivot_value = max( enumerate(lu[i:, i], start=i), key=lambda x: abs(x[1]) ) if abs(pivot_value) < epsilon: raise ValueError( "Matrix has not independent rows (or columns) " "and hence cannot be LU decomposed" ) if pivot_row_idx != i: # Execute row exchange on perm temp_idx = perm[pivot_row_idx] perm[pivot_row_idx] = perm[i] perm[i] = temp_idx # Execute Row exchange on LU temp_row = lu[pivot_row_idx].copy() lu[pivot_row_idx] = lu[i] lu[i] = temp_row cnt_row_exchanges += 1 # Perform elimination factors_column = lu[i + 1 :, i] / pivot_value pivot_row = lu[i, i + 1 :] lu[i + 1 :, i] = factors_column lu[i + 1 :, i + 1 :] -= factors_column * pivot_row return LuDecomposition(lu, perm, cnt_row_exchanges)
def echelon(a: MatrixType) -> EchelonForm: m, n = a.shape # Init lu = a.copy() perm: List[int] = list(range(m)) cnt_row_exchanges = 0 j = 0 i = 0 pivot_cols = [] while i < m and j < n: # All work will be done on sub-matrix lu[i:, j:] pivot_row_idx, pivot_value = max( enumerate(lu[i:, j], start=i), key=lambda x: abs(x[1]) ) if abs(pivot_value) < epsilon: j += 1 continue if pivot_row_idx != i: # Execute row exchange on perm temp_idx = perm[pivot_row_idx] perm[pivot_row_idx] = perm[i] perm[i] = temp_idx # Execute Row exchange on LU temp_row = lu[pivot_row_idx].copy() lu[pivot_row_idx] = lu[i] lu[i] = temp_row cnt_row_exchanges += 1 # Perform elimination pivot_cols.append(j) factors_column = lu[i + 1 :, j] / pivot_value pivot_row = lu[i, j + 1 :] lu[i + 1 :, j] = factors_column lu[i + 1 :, j + 1 :] -= factors_column * pivot_row i += 1 j += 1 return EchelonForm(a, lu, perm, pivot_cols)
def shaped(data: Collection[N], shape: Shape): return MatrixType.from_flat_collection(data, shape)
def zeros(nrows: int = None, ncols: int = None, shape: Shape = None): return MatrixType.zeros(_shape(nrows, ncols, shape))
def eye(nrows: int = None, ncols: int = None, shape: Shape = None): return MatrixType.eye(_shape(nrows, ncols, shape))
def singleton(value: Number) -> MatrixType: return MatrixType.singleton(value)
def det(m: MatrixType) -> float: if not m.is_square(): raise ValueError("Determinants only make sense for square matrices") lu = elimination.lu_decompose(m) return lu.determinant()