X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=dunshire%2Fmatrices.py;h=123085c6c02f69574dc614fcff49d46207b7981c;hb=a4a3482192852e512ae1fed1a114d8314ec63ba8;hp=66c21768403f19e8affa18fe23d1ffdf4f0ecd16;hpb=97eddc6f61ca53ba39f547360ced35a2f69908cb;p=dunshire.git diff --git a/dunshire/matrices.py b/dunshire/matrices.py index 66c2176..123085c 100644 --- a/dunshire/matrices.py +++ b/dunshire/matrices.py @@ -3,9 +3,10 @@ Utility functions for working with CVXOPT matrices (instances of the class:`cvxopt.base.matrix` class). """ +from copy import copy from math import sqrt from cvxopt import matrix -from cvxopt.lapack import gees, syevr +from cvxopt.lapack import gees, gesdd, syevr from . import options @@ -140,7 +141,10 @@ def eigenvalues(symmat): domain_dim = symmat.size[0] eigs = matrix(0, (domain_dim, 1), tc='d') - syevr(symmat, eigs) + + # Create a copy of ``symmat`` here because ``syevr`` clobbers it. + dummy = copy(symmat) + syevr(dummy, eigs) return list(eigs) @@ -326,12 +330,12 @@ def norm(matrix_or_vector): -------- >>> v = matrix([1,1]) - >>> print('{:.5f}'.format(norm(v))) - 1.41421 + >>> norm(v) + 1.414... >>> A = matrix([1,1,1,1], (2,2)) >>> norm(A) - 2.0 + 2.0... """ return sqrt(inner_product(matrix_or_vector, matrix_or_vector)) @@ -388,3 +392,57 @@ def vec(mat): """ return matrix(mat, (len(mat), 1)) + + +def condition_number(mat): + """ + Return the condition number of the given matrix. + + The condition number of a matrix quantifies how hard it is to do + numerical computation with that matrix. It is usually defined as + the ratio of the norm of the matrix to the norm of its inverse, and + therefore depends on the norm used. One way to compute the condition + number with respect to the 2-norm is as the ratio of the matrix's + largest and smallest singular values. Since we have easy access to + those singular values, that is the algorithm we use. + + The larger the condition number is, the worse the matrix is. + + Parameters + ---------- + mat : matrix + The matrix whose condition number you want. + + Returns + ------- + + float + The nonnegative condition number of ``mat``. + + Examples + -------- + + >>> condition_number(identity(3)) + 1.0 + + >>> A = matrix([[2,1],[1,2]]) + >>> abs(condition_number(A) - 3.0) < options.ABS_TOL + True + + >>> A = matrix([[2,1j],[-1j,2]]) + >>> abs(condition_number(A) - 3.0) < options.ABS_TOL + True + + """ + num_eigs = min(mat.size) + eigs = matrix(0, (num_eigs, 1), tc='d') + typecode = 'd' + if any([isinstance(entry, complex) for entry in mat]): + typecode = 'z' + dummy = matrix(mat, mat.size, tc=typecode) + gesdd(dummy, eigs) + + if len(eigs) > 0: + return eigs[0]/eigs[-1] + else: + return 0