def log_matrix_power(lM, n): ''' This function returns the logarithm of lM**n, where the ** denotes the matrix power operation. Matrix multiplication is done using logdot, a more numerically stable way to calculate np.log(np.dot(A,B)) for two matrices A and B It is modified from numpy.linalg's matrix_power function. ''' lM = asanyarray(lM) if lM.ndim != 2 or lM.shape[0] != lM.shape[1]: raise ValueError("input must be a square array") if not issubdtype(type(n), int): raise TypeError("exponent must be an integer") result = lM if n <= 3: for _ in range(n - 1): result = logdot(result, lM) return result # binary decomposition to reduce the number of Matrix # multiplications for n > 3. beta = binary_repr(n) Z, q, t = lM, 0, len(beta) while beta[t - q - 1] == '0': Z = logdot(Z, Z) q += 1 result = Z for k in range(q + 1, t): Z = logdot(Z, Z) if beta[t - k - 1] == '1': result = logdot(result, Z) return result
def matrix_power(M, n, mod_val): # Implementation shadows numpy's matrix_power, but with modulo included M = asanyarray(M) if len(M.shape) != 2 or M.shape[0] != M.shape[1]: raise ValueError("input must be a square array") #if not issubdtype(type(n), int): # raise TypeError("exponent must be an integer") from numpy.linalg import inv if n==0: M = M.copy() M[:] = identity(M.shape[0]) return M elif n<0: M = inv(M) n *= -1 result = M % mod_val if n <= 3: for _ in range(n-1): result = dot(result, M) % mod_val return result # binary decompositon to reduce the number of matrix # multiplications for n > 3 beta = binary_repr(n) Z, q, t = M, 0, len(beta) while beta[t-q-1] == '0': Z = dot(Z, Z) % mod_val q += 1 result = Z for k in range(q+1, t): Z = dot(Z, Z) % mod_val if beta[t-k-1] == '1': result = dot(result, Z) % mod_val return result % mod_val
def matrix_power(M, n): """ Raise a square matrix to the (integer) power `n`. For positive integers `n`, the power is computed by repeated matrix squarings and matrix multiplications. If ``n == 0``, the identity matrix of the same shape as M is returned. If ``n < 0``, the inverse is computed and then raised to the ``abs(n)``. Parameters ---------- M : ndarray or matrix object Matrix to be "powered." Must be square, i.e. ``M.shape == (m, m)``, with `m` a positive integer. n : int The exponent can be any integer or long integer, positive, negative, or zero. Returns ------- M**n : ndarray or matrix object The return value is the same shape and type as `M`; if the exponent is positive or zero then the type of the elements is the same as those of `M`. If the exponent is negative the elements are floating-point. Raises ------ LinAlgError If the matrix is not numerically invertible. See Also -------- matrix Provides an equivalent function as the exponentiation operator (``**``, not ``^``). Examples -------- >>> from numpy import linalg as LA >>> i = np.array([[0, 1], [-1, 0]]) # matrix equiv. of the imaginary unit >>> LA.matrix_power(i, 3) # should = -i array([[ 0, -1], [ 1, 0]]) >>> LA.matrix_power(np.matrix(i), 3) # matrix arg returns matrix matrix([[ 0, -1], [ 1, 0]]) >>> LA.matrix_power(i, 0) array([[1, 0], [0, 1]]) >>> LA.matrix_power(i, -3) # should = 1/(-i) = i, but w/ f.p. elements array([[ 0., 1.], [-1., 0.]]) Somewhat more sophisticated example >>> q = np.zeros((4, 4)) >>> q[0:2, 0:2] = -i >>> q[2:4, 2:4] = i >>> q # one of the three quaternion units not equal to 1 array([[ 0., -1., 0., 0.], [ 1., 0., 0., 0.], [ 0., 0., 0., 1.], [ 0., 0., -1., 0.]]) >>> LA.matrix_power(q, 2) # = -np.eye(4) array([[-1., 0., 0., 0.], [ 0., -1., 0., 0.], [ 0., 0., -1., 0.], [ 0., 0., 0., -1.]]) """ M = asanyarray(M) if len(M.shape) != 2 or M.shape[0] != M.shape[1]: raise ValueError("input must be a square array") if not issubdtype(type(n), int): raise TypeError("exponent must be an integer") from numpy.linalg import inv if n == 0: M = M.copy() M[:] = identity(M.shape[0]) return M elif n < 0: M = inv(M) n *= -1 result = M if n <= 3: for _ in range(n - 1): result = N.dot(result, M) return result # binary decomposition to reduce the number of Matrix # multiplications for n > 3. beta = binary_repr(n) Z, q, t = M, 0, len(beta) while beta[t - q - 1] == '0': Z = N.dot(Z, Z) q += 1 result = Z for k in range(q + 1, t): Z = N.dot(Z, Z) if beta[t - k - 1] == '1': result = N.dot(result, Z) return result
def matrix_power(M, n): """ Raise a square matrix to the (integer) power `n`. For positive integers `n`, the power is computed by repeated matrix squarings and matrix multiplications. If ``n == 0``, the identity matrix of the same shape as M is returned. If ``n < 0``, the inverse is computed and then raised to the ``abs(n)``. Parameters ---------- M : ndarray or matrix object Matrix to be "powered." Must be square, i.e. ``M.shape == (m, m)``, with `m` a positive integer. n : int The exponent can be any integer or long integer, positive, negative, or zero. Returns ------- M**n : ndarray or matrix object The return value is the same shape and type as `M`; if the exponent is positive or zero then the type of the elements is the same as those of `M`. If the exponent is negative the elements are floating-point. Raises ------ LinAlgError If the matrix is not numerically invertible. See Also -------- matrix Provides an equivalent function as the exponentiation operator (``**``, not ``^``). Examples -------- >>> from numpy import linalg as LA >>> i = np.array([[0, 1], [-1, 0]]) # matrix equiv. of the imaginary unit >>> LA.matrix_power(i, 3) # should = -i array([[ 0, -1], [ 1, 0]]) >>> LA.matrix_power(np.matrix(i), 3) # matrix arg returns matrix matrix([[ 0, -1], [ 1, 0]]) >>> LA.matrix_power(i, 0) array([[1, 0], [0, 1]]) >>> LA.matrix_power(i, -3) # should = 1/(-i) = i, but w/ f.p. elements array([[ 0., 1.], [-1., 0.]]) Somewhat more sophisticated example >>> q = np.zeros((4, 4)) >>> q[0:2, 0:2] = -i >>> q[2:4, 2:4] = i >>> q # one of the three quarternion units not equal to 1 array([[ 0., -1., 0., 0.], [ 1., 0., 0., 0.], [ 0., 0., 0., 1.], [ 0., 0., -1., 0.]]) >>> LA.matrix_power(q, 2) # = -np.eye(4) array([[-1., 0., 0., 0.], [ 0., -1., 0., 0.], [ 0., 0., -1., 0.], [ 0., 0., 0., -1.]]) """ M = asanyarray(M) if len(M.shape) != 2 or M.shape[0] != M.shape[1]: raise ValueError("input must be a square array") if not issubdtype(type(n), int): raise TypeError("exponent must be an integer") from numpy.linalg import inv if n==0: M = M.copy() M[:] = identity(M.shape[0]) return M elif n<0: M = inv(M) n *= -1 result = M if n <= 3: for _ in range(n-1): result=N.dot(result, M) return result # binary decomposition to reduce the number of Matrix # multiplications for n > 3. beta = binary_repr(n) Z, q, t = M, 0, len(beta) while beta[t-q-1] == '0': Z = N.dot(Z, Z) q += 1 result = Z for k in range(q+1, t): Z = N.dot(Z, Z) if beta[t-k-1] == '1': result = N.dot(result, Z) return result
def matrix_power(M,n): """ Raise a square matrix to the (integer) power n. For positive integers n, the power is computed by repeated matrix squarings and matrix multiplications. If n=0, the identity matrix of the same type as M is returned. If n<0, the inverse is computed and raised to the exponent. Parameters ---------- M : array_like Must be a square array (that is, of dimension two and with equal sizes). n : integer The exponent can be any integer or long integer, positive negative or zero. Returns ------- M to the power n The return value is a an array the same shape and size as M; if the exponent was positive or zero then the type of the elements is the same as those of M. If the exponent was negative the elements are floating-point. Raises ------ LinAlgException If the matrix is not numerically invertible, an exception is raised. See Also -------- The matrix() class provides an equivalent function as the exponentiation operator. Examples -------- >>> np.linalg.matrix_power(np.array([[0,1],[-1,0]]),10) array([[-1, 0], [ 0, -1]]) """ M = asanyarray(M) if len(M.shape) != 2 or M.shape[0] != M.shape[1]: raise ValueError("input must be a square array") if not issubdtype(type(n),int): raise TypeError("exponent must be an integer") from numpy.linalg import inv if n==0: M = M.copy() M[:] = identity(M.shape[0]) return M elif n<0: M = inv(M) n *= -1 result = M if n <= 3: for _ in range(n-1): result=N.dot(result,M) return result # binary decomposition to reduce the number of Matrix # multiplications for n > 3. beta = binary_repr(n) Z,q,t = M,0,len(beta) while beta[t-q-1] == '0': Z = N.dot(Z,Z) q += 1 result = Z for k in range(q+1,t): Z = N.dot(Z,Z) if beta[t-k-1] == '1': result = N.dot(result,Z) return result