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))
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))
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
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