def mnorm(A, p=1): r""" Gives the matrix (operator) `p`-norm of A. Currently ``p=1`` and ``p=inf`` are supported: ``p=1`` gives the 1-norm (maximal column sum) ``p=inf`` gives the `\infty`-norm (maximal row sum). You can use the string 'inf' as well as float('inf') or mpf('inf') ``p=2`` (not implemented) for a square matrix is the usual spectral matrix norm, i.e. the largest singular value. ``p='f'`` (or 'F', 'fro', 'Frobenius, 'frobenius') gives the Frobenius norm, which is the elementwise 2-norm. The Frobenius norm is an approximation of the spectral norm and satisfies .. math :: \frac{1}{\sqrt{\mathrm{rank}(A)}} \|A\|_F \le \|A\|_2 \le \|A\|_F The Frobenius norm lacks some mathematical properties that might be expected of a norm. For general elementwise `p`-norms, use :func:`norm` instead. **Examples** >>> from mpmath import * >>> mp.dps = 15 >>> A = matrix([[1, -1000], [100, 50]]) >>> mnorm(A, 1) mpf('1050.0') >>> mnorm(A, inf) mpf('1001.0') >>> mnorm(A, 'F') mpf('1006.2310867787777') """ A = matrix(A) if type(p) is not int: if type(p) is str and 'frobenius'.startswith(p.lower()): return norm(A, 2) p = mpmathify(p) m, n = A.rows, A.cols if p == 1: return max( fsum((A[i, j] for i in xrange(m)), absolute=1) for j in xrange(n)) elif p == inf: return max( fsum((A[i, j] for j in xrange(n)), absolute=1) for i in xrange(m)) else: raise NotImplementedError("matrix p-norm for arbitrary p")
def mnorm(A, p=1): r""" Gives the matrix (operator) `p`-norm of A. Currently ``p=1`` and ``p=inf`` are supported: ``p=1`` gives the 1-norm (maximal column sum) ``p=inf`` gives the `\infty`-norm (maximal row sum). You can use the string 'inf' as well as float('inf') or mpf('inf') ``p=2`` (not implemented) for a square matrix is the usual spectral matrix norm, i.e. the largest singular value. ``p='f'`` (or 'F', 'fro', 'Frobenius, 'frobenius') gives the Frobenius norm, which is the elementwise 2-norm. The Frobenius norm is an approximation of the spectral norm and satisfies .. math :: \frac{1}{\sqrt{\mathrm{rank}(A)}} \|A\|_F \le \|A\|_2 \le \|A\|_F The Frobenius norm lacks some mathematical properties that might be expected of a norm. For general elementwise `p`-norms, use :func:`norm` instead. **Examples** >>> from mpmath import * >>> mp.dps = 15 >>> A = matrix([[1, -1000], [100, 50]]) >>> mnorm(A, 1) mpf('1050.0') >>> mnorm(A, inf) mpf('1001.0') >>> mnorm(A, 'F') mpf('1006.2310867787777') """ A = matrix(A) if type(p) is not int: if type(p) is str and 'frobenius'.startswith(p.lower()): return norm(A, 2) p = mpmathify(p) m, n = A.rows, A.cols if p == 1: return max(fsum((A[i,j] for i in xrange(m)), absolute=1) for j in xrange(n)) elif p == inf: return max(fsum((A[i,j] for j in xrange(n)), absolute=1) for i in xrange(m)) else: raise NotImplementedError("matrix p-norm for arbitrary p")
def norm(x, p=2): r""" Gives the entrywise `p`-norm of an iterable *x*, i.e. the vector norm `\left(\sum_k |x_k|^p\right)^{1/p}`, for any given `1 \le p \le \infty`. Special cases: If *x* is not iterable, this just returns ``absmax(x)``. ``p=1`` gives the sum of absolute values. ``p=2`` is the standard Euclidean vector norm. ``p=inf`` gives the magnitude of the largest element. For *x* a matrix, ``p=2`` is the Frobenius norm. For operator matrix norms, use :func:`mnorm` instead. You can use the string 'inf' as well as float('inf') or mpf('inf') to specify the infinity norm. **Examples** >>> from mpmath import * >>> mp.dps = 15 >>> x = matrix([-10, 2, 100]) >>> norm(x, 1) mpf('112.0') >>> norm(x, 2) mpf('100.5186549850325') >>> norm(x, inf) mpf('100.0') """ try: iter(x) except TypeError: return absmax(x) if type(p) is not int: p = mpmathify(p) if p == inf: return max(absmax(i) for i in x) elif p == 1: return fsum(x, absolute=1) elif p == 2: return sqrt(fsum(x, absolute=1, squared=1)) elif p > 1: return nthroot(fsum(abs(i)**p for i in x), p) else: raise ValueError('p has to be >= 1')
def norm_p(x, p=2): """ Calculate the p-norm of a vector. 0 < p <= oo Note: you may want to use float('inf') or mpmath's equivalent to specify oo. """ if p == inf: return max(absmax(i) for i in x) elif p > 1: return nthroot(fsum(abs(i)**p for i in x), p) elif p == 1: return fsum(abs(i) for i in x) else: raise ValueError('p has to be an integer greater than 0')
def cholesky_solve(A, b, **kwargs): """ Ax = b => x Solve a symmetric positive-definite linear equation system. This is twice as efficient as lu_solve. Typical use cases: * A.T*A * Hessian matrix * differential equations """ # do not overwrite A nor b A, b = matrix(A, **kwargs).copy(), matrix(b, **kwargs).copy() if A.rows != A.cols: raise ValueError('can only solve determined system') # Cholesky factorization L = cholesky(A) # solve n = L.rows assert len(b) == n for i in xrange(n): b[i] -= fsum(L[i,j] * b[j] for j in xrange(i)) b[i] /= L[i,i] x = U_solve(L.T, b) return x
def mnorm_oo(A): """ Calculate the oo-norm (maximal row sum) of a matrix. """ assert isinstance(A, matrix) m, n = A.rows, A.cols return max(fsum(absmax(A[i,j]) for j in xrange(n)) for i in xrange(m))
def householder(A): """ (A|b) -> H, p, x, res (A|b) is the coefficient matrix with left hand side of an optionally overdetermined linear equation system. H and p contain all information about the transformation matrices. x is the solution, res the residual. """ assert isinstance(A, matrix) m = A.rows n = A.cols assert m >= n - 1 # calculate Householder matrix p = [] for j in xrange(0, n - 1): s = fsum((A[i,j])**2 for i in xrange(j, m)) if not abs(s) > eps: raise ValueError('matrix is numerically singular') p.append(-sign(A[j,j]) * sqrt(s)) kappa = s - p[j] * A[j,j] A[j,j] -= p[j] for k in xrange(j+1, n): y = fsum(A[i,j] * A[i,k] for i in xrange(j, m)) / kappa for i in xrange(j, m): A[i,k] -= A[i,j] * y # solve Rx = c1 x = [A[i,n - 1] for i in xrange(n - 1)] for i in xrange(n - 2, -1, -1): x[i] -= fsum(A[i,j] * x[j] for j in xrange(i + 1, n - 1)) x[i] /= p[i] # calculate residual if not m == n - 1: r = [A[m-1-i, n-1] for i in xrange(m - n + 1)] else: # determined system, residual should be 0 r = [0]*m # maybe a bad idea, changing r[i] will change all elements return A, p, x, r
def cholesky(A): """ Cholesky decompositon of a symmetric positive-definite matrix. Can be used to solve linear equation systems twice as efficient compared to LU decomposition or to test whether A is positive-definite. A = L * L.T Only L (the lower part) is returned. """ assert isinstance(A, matrix) if not A.rows == A.cols: raise ValueError('need n*n matrix') n = A.rows L = matrix(n) for j in xrange(n): s = A[j,j] - fsum(L[j,k]**2 for k in xrange(j)) if s < eps: raise ValueError('matrix not positive-definite') L[j,j] = sqrt(s) for i in xrange(j, n): L[i,j] = (A[i,j] - fsum(L[i,k] * L[j,k] for k in xrange(j))) \ / L[j,j] return L
def cholesky(A): """ Cholesky decomposition of a symmetric positive-definite matrix. Can be used to solve linear equation systems twice as efficient compared to LU decomposition or to test whether A is positive-definite. A = L * L.T Only L (the lower part) is returned. """ assert isinstance(A, matrix) if not A.rows == A.cols: raise ValueError('need n*n matrix') n = A.rows L = matrix(n) for j in xrange(n): s = A[j,j] - fsum(L[j,k]**2 for k in xrange(j)) if s < eps: raise ValueError('matrix not positive-definite') L[j,j] = sqrt(s) for i in xrange(j, n): L[i,j] = (A[i,j] - fsum(L[i,k] * L[j,k] for k in xrange(j))) \ / L[j,j] return L
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