diff options
-rw-r--r-- | numpy/linalg/linalg.py | 38 | ||||
-rw-r--r-- | numpy/linalg/tests/test_linalg.py | 17 |
2 files changed, 54 insertions, 1 deletions
diff --git a/numpy/linalg/linalg.py b/numpy/linalg/linalg.py index c4575e377..1706ff4a9 100644 --- a/numpy/linalg/linalg.py +++ b/numpy/linalg/linalg.py @@ -16,6 +16,7 @@ __all__ = ['matrix_power', 'solve', 'tensorsolve', 'tensorinv', 'det', 'svd', 'eig', 'eigh','lstsq', 'norm', 'qr', + 'cond', 'LinAlgError' ] @@ -968,6 +969,43 @@ def svd(a, full_matrices=1, compute_uv=1): else: return s +def cond(x,p=None): + """Compute the condition number of a matrix. + + The condition number of x is the norm of x times the norm + of the inverse of x. The norm can be the usual L2 + (root-of-sum-of-squares) norm or a number of other matrix norms. + + Parameters + ---------- + x : array, shape (M, N) + The matrix whose condition number is sought. + p : {None, 1, -1, 2, -2, inf, -inf, 'fro'} + Order of the norm: + + p norm for matrices + ===== ============================ + None 2-norm, computed directly using the SVD + 'fro' Frobenius norm + inf max(sum(abs(x), axis=1)) + -inf min(sum(abs(x), axis=1)) + 1 max(sum(abs(x), axis=0)) + -1 min(sum(abs(x), axis=0)) + 2 2-norm (largest sing. value) + -2 smallest singular value + ===== ============================ + + Returns + ------- + c : float + The condition number of the matrix. May be infinite. + """ + if p is None: + s = svd(x,compute_uv=False) + return s[0]/s[-1] + else: + return norm(x,p)*norm(inv(x),p) + # Generalized inverse def pinv(a, rcond=1e-15 ): diff --git a/numpy/linalg/tests/test_linalg.py b/numpy/linalg/tests/test_linalg.py index 5321ae7c5..7d2390980 100644 --- a/numpy/linalg/tests/test_linalg.py +++ b/numpy/linalg/tests/test_linalg.py @@ -4,7 +4,7 @@ from numpy.testing import * set_package_path() from numpy import array, single, double, csingle, cdouble, dot, identity, \ - multiply, atleast_2d + multiply, atleast_2d, inf from numpy import linalg from linalg import matrix_power restore_path() @@ -73,6 +73,21 @@ class TestSVD(LinalgTestCase): u, s, vt = linalg.svd(a, 0) assert_almost_equal(a, dot(u*s, vt)) +class TestCondSVD(LinalgTestCase): + def do(self, a, b): + s = linalg.svd(a, compute_uv=False) + old_assert_almost_equal(s[0]/s[-1], linalg.cond(a), decimal=5) + +class TestCond2(LinalgTestCase): + def do(self, a, b): + s = linalg.svd(a, compute_uv=False) + old_assert_almost_equal(s[0]/s[-1], linalg.cond(a,2), decimal=5) + +class TestCondInf(NumpyTestCase): + def test(self): + A = array([[1.,0,0],[0,-2.,0],[0,0,3.]]) + assert_almost_equal(linalg.cond(A,inf),3.) + class TestPinv(LinalgTestCase): def do(self, a, b): a_ginv = linalg.pinv(a) |