def tanhm(A): """matrix hyperbolic tangent. """ A = asarray(A) if A.dtype.char not in ['F','D']: return toreal(solve(coshm(A), sinhm(A))) else: return solve(coshm(A), sinhm(A))
def tanm(A): """matrix tangent. """ A = asarray(A) if A.dtype.char not in ['F','D','G']: return toreal(solve(cosm(A), sinm(A))) else: return solve(cosm(A), sinm(A))
def solve_discrete_lyapunov(a, q): """Solves the Discrete Lyapunov Equation (A'XA-X=-Q) directly. Parameters ---------- a : array_like A square matrix q : array_like Right-hand side square matrix Returns ------- x : array_like Solution to the continuous Lyapunov equation Notes ----- Algorithm is based on a direct analytical solution from: Hamilton, James D. Time Series Analysis, Princeton: Princeton University Press, 1994. 265. Print. http://www.scribd.com/doc/20577138/Hamilton-1994-Time-Series-Analysis """ lhs = kron(a, a.conj()) lhs = np.eye(lhs.shape[0]) - lhs x = solve(lhs, q.flatten()) return np.reshape(x, q.shape)
def logm(A,disp=1): """Matrix logarithm, inverse of expm.""" # Compute using general funm but then use better error estimator and # make one step in improving estimate using a rotation matrix. A = mat(asarray(A)) F, errest = funm(A,log,disp=0) errtol = 1000*eps # Only iterate if estimate of error is too large. if errest >= errtol: # Use better approximation of error errest = norm(expm(F)-A,1) / norm(A,1) if not isfinite(errest) or errest >= errtol: N,N = A.shape X,Y = ogrid[1:N+1,1:N+1] R = mat(orth(eye(N,dtype='d')+X+Y)) F, dontcare = funm(R*A*R.H,log,disp=0) F = R.H*F*R if (norm(imag(F),1)<=1000*errtol*norm(F,1)): F = mat(real(F)) E = mat(expm(F)) temp = mat(solve(E.T,(E-A).T)) F = F - temp.T errest = norm(expm(F)-A,1) / norm(A,1) if disp: if not isfinite(errest) or errest >= errtol: print "Result may be inaccurate, approximate err =", errest return F else: return F, errest
def expm(A, q=False): """Compute the matrix exponential using Pade approximation. Parameters ---------- A : array, shape(M,M) Matrix to be exponentiated Returns ------- expA : array, shape(M,M) Matrix exponential of A References ---------- N. J. Higham, "The Scaling and Squaring Method for the Matrix Exponential Revisited", SIAM. J. Matrix Anal. & Appl. 26, 1179 (2005). """ if q: warnings.warn("argument q=... in scipy.linalg.expm is deprecated.") A = asarray(A) A_L1 = norm(A,1) n_squarings = 0 if A.dtype == 'float64' or A.dtype == 'complex128': if A_L1 < 1.495585217958292e-002: U,V = _pade3(A) elif A_L1 < 2.539398330063230e-001: U,V = _pade5(A) elif A_L1 < 9.504178996162932e-001: U,V = _pade7(A) elif A_L1 < 2.097847961257068e+000: U,V = _pade9(A) else: maxnorm = 5.371920351148152 n_squarings = max(0, int(ceil(log2(A_L1 / maxnorm)))) A = A / 2**n_squarings U,V = _pade13(A) elif A.dtype == 'float32' or A.dtype == 'complex64': if A_L1 < 4.258730016922831e-001: U,V = _pade3(A) elif A_L1 < 1.880152677804762e+000: U,V = _pade5(A) else: maxnorm = 3.925724783138660 n_squarings = max(0, int(ceil(log2(A_L1 / maxnorm)))) A = A / 2**n_squarings U,V = _pade7(A) else: raise ValueError("invalid type: "+str(A.dtype)) P = U + V # p_m(A) : numerator Q = -U + V # q_m(A) : denominator R = solve(Q,P) # squaring step to undo scaling for i in range(n_squarings): R = dot(R,R) return R
def tanhm(A): """Compute the hyperbolic matrix tangent. This routine uses expm to compute the matrix exponentials. Parameters ---------- A : array, shape(M,M) Returns ------- tanhA : array, shape(M,M) Hyperbolic matrix tangent of A """ A = asarray(A) if A.dtype.char not in ['F','D']: return toreal(solve(coshm(A), sinhm(A))) else: return solve(coshm(A), sinhm(A))
def expm(A,q=7): """Compute the matrix exponential using Pade approximation. Parameters ---------- A : array, shape(M,M) Matrix to be exponentiated q : integer Order of the Pade approximation Returns ------- expA : array, shape(M,M) Matrix exponential of A """ A = asarray(A) ss = True if A.dtype.char in ['f', 'F']: pass ## A.savespace(1) else: pass ## A.savespace(0) # Scale A so that norm is < 1/2 nA = norm(A,Inf) if nA==0: return identity(len(A), A.dtype.char) from numpy import log2 val = log2(nA) e = int(floor(val)) j = max(0,e+1) A = A / 2.0**j # Pade Approximation for exp(A) X = A c = 1.0/2 N = eye(*A.shape) + c*A D = eye(*A.shape) - c*A for k in range(2,q+1): c = c * (q-k+1) / (k*(2*q-k+1)) X = dot(A,X) cX = c*X N = N + cX if not k % 2: D = D + cX; else: D = D - cX; F = solve(D,N) for k in range(1,j+1): F = dot(F,F) pass ## A.savespace(ss) return F
def logm(A, disp=True): """Compute matrix logarithm. The matrix logarithm is the inverse of expm: expm(logm(A)) == A Parameters ---------- A : array, shape(M,M) Matrix whose logarithm to evaluate disp : boolean Print warning if error in the result is estimated large instead of returning estimated error. (Default: True) Returns ------- logA : array, shape(M,M) Matrix logarithm of A (if disp == False) errest : float 1-norm of the estimated error, ||err||_1 / ||A||_1 """ # Compute using general funm but then use better error estimator and # make one step in improving estimate using a rotation matrix. A = mat(asarray(A)) F, errest = funm(A,log,disp=0) errtol = 1000*eps # Only iterate if estimate of error is too large. if errest >= errtol: # Use better approximation of error errest = norm(expm(F)-A,1) / norm(A,1) if not isfinite(errest) or errest >= errtol: N,N = A.shape X,Y = ogrid[1:N+1,1:N+1] R = mat(orth(eye(N,dtype='d')+X+Y)) F, dontcare = funm(R*A*R.H,log,disp=0) F = R.H*F*R if (norm(imag(F),1)<=1000*errtol*norm(F,1)): F = mat(real(F)) E = mat(expm(F)) temp = mat(solve(E.T,(E-A).T)) F = F - temp.T errest = norm(expm(F)-A,1) / norm(A,1) if disp: if not isfinite(errest) or errest >= errtol: print "Result may be inaccurate, approximate err =", errest return F else: return F, errest