def sqrtm(A,disp=1): """Matrix square root If disp is non-zero display warning if singular matrix. If disp is zero then return residual ||A-X*X||_F / ||A||_F Uses algorithm by Nicholas J. Higham """ A = asarray(A) if len(A.shape)!=2: raise ValueError, "Non-matrix input to matrix function." T, Z = schur(A) T, Z = rsf2csf(T,Z) n,n = T.shape R = sb.zeros((n,n),T.dtype.char) for j in range(n): R[j,j] = sqrt(T[j,j]) for i in range(j-1,-1,-1): s = 0 for k in range(i+1,j): s = s + R[i,k]*R[k,j] R[i,j] = (T[i,j] - s)/(R[i,i] + R[j,j]) R, Z = all_mat(R,Z) X = (Z * R * Z.H) if disp: nzeig = sb.any(sb.diag(T)==0) if nzeig: print "Matrix is singular and may not have a square root." return X.A else: arg2 = norm(X*X - A,'fro')**2 / norm(A,'fro') return X.A, arg2
def funm(A,func,disp=1): """matrix function for arbitrary callable object func. """ # func should take a vector of arguments (see vectorize if # it needs wrapping. # Perform Shur decomposition (lapack ?gees) A = asarray(A) if len(A.shape)!=2: raise ValueError, "Non-matrix input to matrix function." if A.dtype.char in ['F', 'D', 'G']: cmplx_type = 1 else: cmplx_type = 0 T, Z = schur(A) T, Z = rsf2csf(T,Z) n,n = T.shape F = diag(func(diag(T))) # apply function to diagonal elements F = F.astype(T.dtype.char) # e.g. when F is real but T is complex minden = abs(T[0,0]) # implement Algorithm 11.1.1 from Golub and Van Loan # "matrix Computations." for p in range(1,n): for i in range(1,n-p+1): j = i + p s = T[i-1,j-1] * (F[j-1,j-1] - F[i-1,i-1]) ksl = slice(i,j-1) val = dot(T[i-1,ksl],F[ksl,j-1]) - dot(F[i-1,ksl],T[ksl,j-1]) s = s + val den = T[j-1,j-1] - T[i-1,i-1] if den != 0.0: s = s / den F[i-1,j-1] = s minden = min(minden,abs(den)) F = dot(dot(Z, F),transpose(conjugate(Z))) if not cmplx_type: F = toreal(F) tol = {0:feps, 1:eps}[_array_precision[F.dtype.char]] if minden == 0.0: minden = tol err = min(1, max(tol,(tol/minden)*norm(triu(T,1),1))) if product(ravel(logical_not(isfinite(F))),axis=0): err = Inf if disp: if err > 1000*tol: print "Result may be inaccurate, approximate err =", err return F else: return F, err
def sqrtm(A,disp=1): """Matrix square root. Parameters ---------- A : array, shape(M,M) Matrix whose square root to evaluate disp : boolean Print warning if error in the result is estimated large instead of returning estimated error. (Default: True) Returns ------- sgnA : array, shape(M,M) Value of the sign function at A (if disp == False) errest : float Frobenius norm of the estimated error, ||err||_F / ||A||_F Notes ----- Uses algorithm by Nicholas J. Higham """ A = asarray(A) if len(A.shape)!=2: raise ValueError, "Non-matrix input to matrix function." T, Z = schur(A) T, Z = rsf2csf(T,Z) n,n = T.shape R = np.zeros((n,n),T.dtype.char) for j in range(n): R[j,j] = sqrt(T[j,j]) for i in range(j-1,-1,-1): s = 0 for k in range(i+1,j): s = s + R[i,k]*R[k,j] R[i,j] = (T[i,j] - s)/(R[i,i] + R[j,j]) R, Z = all_mat(R,Z) X = (Z * R * Z.H) if disp: nzeig = np.any(diag(T)==0) if nzeig: print "Matrix is singular and may not have a square root." return X.A else: arg2 = norm(X*X - A,'fro')**2 / norm(A,'fro') return X.A, arg2
def funm(A,func,disp=1): """Evaluate a matrix function specified by a callable. Returns the value of matrix-valued function f at A. The function f is an extension of the scalar-valued function func to matrices. Parameters ---------- A : array, shape(M,M) Matrix at which to evaluate the function func : callable Callable object that evaluates a scalar function f. Must be vectorized (eg. using vectorize). disp : boolean Print warning if error in the result is estimated large instead of returning estimated error. (Default: True) Returns ------- fA : array, shape(M,M) Value of the matrix function specified by func evaluated at A (if disp == False) errest : float 1-norm of the estimated error, ||err||_1 / ||A||_1 """ # Perform Shur decomposition (lapack ?gees) A = asarray(A) if len(A.shape)!=2: raise ValueError, "Non-matrix input to matrix function." if A.dtype.char in ['F', 'D', 'G']: cmplx_type = 1 else: cmplx_type = 0 T, Z = schur(A) T, Z = rsf2csf(T,Z) n,n = T.shape F = diag(func(diag(T))) # apply function to diagonal elements F = F.astype(T.dtype.char) # e.g. when F is real but T is complex minden = abs(T[0,0]) # implement Algorithm 11.1.1 from Golub and Van Loan # "matrix Computations." for p in range(1,n): for i in range(1,n-p+1): j = i + p s = T[i-1,j-1] * (F[j-1,j-1] - F[i-1,i-1]) ksl = slice(i,j-1) val = dot(T[i-1,ksl],F[ksl,j-1]) - dot(F[i-1,ksl],T[ksl,j-1]) s = s + val den = T[j-1,j-1] - T[i-1,i-1] if den != 0.0: s = s / den F[i-1,j-1] = s minden = min(minden,abs(den)) F = dot(dot(Z, F),transpose(conjugate(Z))) if not cmplx_type: F = toreal(F) tol = {0:feps, 1:eps}[_array_precision[F.dtype.char]] if minden == 0.0: minden = tol err = min(1, max(tol,(tol/minden)*norm(triu(T,1),1))) if product(ravel(logical_not(isfinite(F))),axis=0): err = Inf if disp: if err > 1000*tol: print "Result may be inaccurate, approximate err =", err return F else: return F, err