Пример #1
0
def lu(A):
    """
    A -> P, L, U

    LU factorisation of a square matrix A. L is the lower, U the upper part.
    P is the permutation matrix indicating the row swaps.

    P*A = L*U

    If you need efficiency, use the low-level method LU_decomp instead, it's
    much more memory efficient.
    """
    # get factorization
    A, p = LU_decomp(A.copy())
    n = A.rows
    L = matrix(n)
    U = matrix(n)
    for i in xrange(n):
        for j in xrange(n):
            if i > j:
                L[i, j] = A[i, j]
            elif i == j:
                L[i, j] = 1
                U[i, j] = A[i, j]
            else:
                U[i, j] = A[i, j]
    # calculate permutation matrix
    P = eye(n)
    for k in xrange(len(p)):
        swap_row(P, k, p[k])
    return P, L, U
Пример #2
0
def lu(A):
    """
    A -> P, L, U

    LU factorisation of a square matrix A. L is the lower, U the upper part.
    P is the permutation matrix indicating the row swaps.

    P*A = L*U

    If you need efficiency, use the low-level method LU_decomp instead, it's
    much more memory efficient.
    """
    # get factorization
    A, p = LU_decomp(A)
    n = A.rows
    L = matrix(n)
    U = matrix(n)
    for i in xrange(n):
        for j in xrange(n):
            if i > j:
                L[i,j] = A[i,j]
            elif i == j:
                L[i,j] = 1
                U[i,j] = A[i,j]
            else:
                U[i,j] = A[i,j]
    # calculate permutation matrix
    P = eye(n)
    for k in xrange(len(p)):
        swap_row(P, k, p[k])
    return P, L, U
Пример #3
0
def L_solve(L, b, p=None):
    """
    Solve the lower part of a LU factorized matrix for y.
    """
    L.rows == L.cols, 'need n*n matrix'
    n = L.rows
    assert len(b) == n
    b = copy(b)
    if p:  # swap b according to p
        for k in xrange(0, len(p)):
            swap_row(b, k, p[k])
    # solve
    for i in xrange(1, n):
        for j in xrange(i):
            b[i] -= L[i, j] * b[j]
    return b
Пример #4
0
def L_solve(L, b, p=None):
    """
    Solve the lower part of a LU factorized matrix for y.
    """
    assert L.rows == L.cols, 'need n*n matrix'
    n = L.rows
    assert len(b) == n
    b = copy(b)
    if p: # swap b according to p
        for k in xrange(0, len(p)):
            swap_row(b, k, p[k])
    # solve
    for i in xrange(1, n):
        for j in xrange(i):
            b[i] -= L[i,j] * b[j]
    return b
Пример #5
0
def LU_decomp(A, overwrite=False, use_cache=True):
    """
    LU-factorization of a n*n matrix using the Gauss algorithm.
    Returns L and U in one matrix and the pivot indices.

    Use overwrite to specify whether A will be overwritten with L and U.
    """
    if not A.rows == A.cols:
        raise ValueError('need n*n matrix')
    # get from cache if possible
    if use_cache and isinstance(A, matrix) and A._LU:
        return A._LU
    if not overwrite:
        orig = A
        A = A.copy()
    tol = absmin(mnorm(A,1) * eps) # each pivot element has to be bigger
    n = A.rows
    p = [None]*(n - 1)
    for j in xrange(n - 1):
        # pivoting, choose max(abs(reciprocal row sum)*abs(pivot element))
        biggest = 0
        for k in xrange(j, n):
            s = fsum([absmin(A[k,l]) for l in xrange(j, n)])
            if absmin(s) <= tol:
                raise ZeroDivisionError('matrix is numerically singular')
            current = 1/s * absmin(A[k,j])
            if current > biggest: # TODO: what if equal?
                biggest = current
                p[j] = k
        # swap rows according to p
        swap_row(A, j, p[j])
        if absmin(A[j,j]) <= tol:
            raise ZeroDivisionError('matrix is numerically singular')
        # calculate elimination factors and add rows
        for i in xrange(j + 1, n):
            A[i,j] /= A[j,j]
            for k in xrange(j + 1, n):
                A[i,k] -= A[i,j]*A[j,k]
    if absmin(A[n - 1,n - 1]) <= tol:
        raise ZeroDivisionError('matrix is numerically singular')
    # cache decomposition
    if not overwrite and isinstance(orig, matrix):
        orig._LU = (A, p)
    return A, p
Пример #6
0
def LU_decomp(A, overwrite=False, use_cache=True):
    """
    LU-factorization of a n*n matrix using the Gauss algorithm.
    Returns L and U in one matrix and the pivot indices.

    Use overwrite to specify whether A will be overwritten with L and U.
    """
    if not A.rows == A.cols:
        raise ValueError('need n*n matrix')
    # get from cache if possible
    if use_cache and isinstance(A, matrix) and A._LU:
        return A._LU
    if not overwrite:
        orig = A
        A = A.copy()
    tol = absmin(mnorm(A,1) * eps) # each pivot element has to be bigger
    n = A.rows
    p = [None]*(n - 1)
    for j in xrange(n - 1):
        # pivoting, choose max(abs(reciprocal row sum)*abs(pivot element))
        biggest = 0
        for k in xrange(j, n):
            s = fsum([absmin(A[k,l]) for l in xrange(j, n)])
            if absmin(s) <= tol:
                raise ZeroDivisionError('matrix is numerically singular')
            current = 1/s * absmin(A[k,j])
            if current > biggest: # TODO: what if equal?
                biggest = current
                p[j] = k
        # swap rows according to p
        swap_row(A, j, p[j])
        if absmin(A[j,j]) <= tol:
            raise ZeroDivisionError('matrix is numerically singular')
        # calculate elimination factors and add rows
        for i in xrange(j + 1, n):
            A[i,j] /= A[j,j]
            for k in xrange(j + 1, n):
                A[i,k] -= A[i,j]*A[j,k]
    if absmin(A[n - 1,n - 1]) <= tol:
        raise ZeroDivisionError('matrix is numerically singular')
    # cache decomposition
    if not overwrite and isinstance(orig, matrix):
        orig._LU = (A, p)
    return A, p