Ejemplo n.º 1
0
def cond(A, norm=lambda x: mnorm(x,1)):
    """
    Calculate the condition number of a matrix using a specified matrix norm.

    The condition number estimates the sensitivity of a matrix to errors.
    Example: small input errors for ill-conditionded coefficient matrices
    alter the solution of the system dramatically.

    For ill-conditioned matrices it's recommended to use qr_solve() instead
    of lu_solve(). This does not help with input errors however, it just avoids
    to add additional errors.

    Definition:    cond(A) = ||A|| * ||A**-1||
    """
    return norm(A) * norm(inverse(A))
Ejemplo n.º 2
0
def cond(A, norm=lambda x: mnorm(x,1)):
    """
    Calculate the condition number of a matrix using a specified matrix norm.

    The condition number estimates the sensitivity of a matrix to errors.
    Example: small input errors for ill-conditioned coefficient matrices
    alter the solution of the system dramatically.

    For ill-conditioned matrices it's recommended to use qr_solve() instead
    of lu_solve(). This does not help with input errors however, it just avoids
    to add additional errors.

    Definition:    cond(A) = ||A|| * ||A**-1||
    """
    return norm(A) * norm(inverse(A))
Ejemplo n.º 3
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
Ejemplo n.º 4
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
Ejemplo n.º 5
0
def exp_pade(a):
    """Exponential of a matrix using Pade approximants.

       See G. H. Golub, C. F. van Loan 'Matrix Computations',
         third Ed., page 572

       TODO:
         - find a good estimate for q
         - reduce the number of matrix multiplications to improve
           performance
    """
    def eps_pade(p):
        return mpf(2)**(3-2*p) * factorial(p)**2/(factorial(2*p)**2 * (2*p + 1))
    q = 4
    extraq = 8
    while 1:
        if eps_pade(q) < eps:
            break
        q += 1
    q += extraq
    j = max(1, int(log(mnorm(a,'inf'),2)))
    extra = q
    mp.dps += extra
    try:
        a = a/2**j
        na = a.rows
        den = eye(na)
        num = eye(na)
        x = eye(na)
        c = mpf(1)
        for k in range(1, q+1):
            c *= mpf(q - k + 1)/((2*q - k + 1) * k)
            x = a*x
            cx = c*x
            num += cx
            den += (-1)**k * cx
        f = lu_solve_mat(den, num)
        for k in range(j):
            f = f*f
    finally:
        mp.dps -= extra
    return f
Ejemplo n.º 6
0
def exp_pade(a):
    """Exponential of a matrix using Pade approximants.

       See G. H. Golub, C. F. van Loan 'Matrix Computations',
         third Ed., page 572

       TODO:
         - find a good estimate for q
         - reduce the number of matrix multiplications to improve
           performance
    """
    def eps_pade(p):
        return mpf(2)**(3-2*p) * factorial(p)**2/(factorial(2*p)**2 * (2*p + 1))
    q = 4
    extraq = 8
    while 1:
        if eps_pade(q) < eps:
            break
        q += 1
    q += extraq
    j = max(1, int(log(mnorm(a,'inf'),2)))
    extra = q
    mp.dps += extra
    try:
        a = a/2**j
        na = a.rows
        den = eye(na)
        num = eye(na)
        x = eye(na)
        c = mpf(1)
        for k in range(1, q+1):
            c *= mpf(q - k + 1)/((2*q - k + 1) * k)
            x = a*x
            cx = c*x
            num += cx
            den += (-1)**k * cx
        f = lu_solve_mat(den, num)
        for k in range(j):
            f = f*f
    finally:
        mp.dps -= extra
    return f