def __pow__(self, other): if other != 1 and not self.is_square: raise NonSquareMatrixError("Power of non-square matrix %s" % self) if other == 0: return Identity(self.rows) if other < 1: raise NonInvertibleMatrixError("Matrix det == 0; not invertible") return self
def _eval_inverse(self): condition = self._is_1x1() if condition == True: return Identity(1) elif condition == False: raise NonInvertibleMatrixError("Matrix det == 0; not invertible.") else: return Inverse(self)
def _eval_power(self, exp): # exp = -1, 0, 1 are already handled at this stage if self._is_1x1() == True: return Identity(1) if (exp < 0) == True: raise NonInvertibleMatrixError("Matrix det == 0; not invertible") if ask(Q.integer(exp)): return self.shape[0]**(exp - 1) * OneMatrix(*self.shape) return super(OneMatrix, self)._eval_power(exp)
def LUdecomposition(self): """Returns the Block LU decomposition of a 2x2 Block Matrix Returns ======= (L, U) : Matrices L : Lower Diagonal Matrix U : Upper Diagonal Matrix Examples ======== >>> from sympy import symbols, MatrixSymbol, BlockMatrix, block_collapse >>> m, n = symbols('m n') >>> A = MatrixSymbol('A', n, n) >>> B = MatrixSymbol('B', n, m) >>> C = MatrixSymbol('C', m, n) >>> D = MatrixSymbol('D', m, m) >>> X = BlockMatrix([[A, B], [C, D]]) >>> L, U = X.LUdecomposition() >>> block_collapse(L*U) Matrix([ [A, B], [C, D]]) Raises ====== ShapeError If the block matrix is not a 2x2 matrix NonInvertibleMatrixError If the matrix "A" is non-invertible See Also ======== sympy.matrices.expressions.blockmatrix.BlockMatrix.UDLdecomposition sympy.matrices.expressions.blockmatrix.BlockMatrix.LDUdecomposition """ if self.blockshape == (2,2): [[A, B], [C, D]] = self.blocks.tolist() try: A = A**0.5 AI = A.I except NonInvertibleMatrixError: raise NonInvertibleMatrixError('Block LU decomposition cannot be calculated when\ "A" is singular') Z = ZeroMatrix(*B.shape) Q = self.schur()**0.5 L = BlockMatrix([[A, Z], [C*AI, Q]]) U = BlockMatrix([[A, AI*B],[Z.T, Q]]) return L, U else: raise ShapeError("Block LU decomposition is supported only for 2x2 block matrices")
def ddm_iinv(ainv, a, K): if not K.is_Field: raise ValueError('Not a field') # a is (m x n) m = len(a) if not m: return n = len(a[0]) if m != n: raise NonSquareMatrixError eye = [[K.one if i==j else K.zero for j in range(n)] for i in range(n)] Aaug = [row + eyerow for row, eyerow in zip(a, eye)] pivots = ddm_irref(Aaug, K) if pivots != list(range(n)): raise NonInvertibleMatrixError('Matrix det == 0; not invertible.') ainv[:] = [row[n:] for row in Aaug]
def _eval_inverse(self, expand='ignored'): if self._all_square_blocks(): return BlockDiagMatrix(*[mat.inverse() for mat in self.args]) # See comment in _eval_determinant() raise NonInvertibleMatrixError('Matrix det == 0; not invertible.')
def UDLdecomposition(self): """Returns the Block UDL decomposition of a 2x2 Block Matrix Returns ======= (U, D, L) : Matrices U : Upper Diagonal Matrix D : Diagonal Matrix L : Lower Diagonal Matrix Examples ======== >>> from sympy import symbols, MatrixSymbol, BlockMatrix, block_collapse >>> m, n = symbols('m n') >>> A = MatrixSymbol('A', n, n) >>> B = MatrixSymbol('B', n, m) >>> C = MatrixSymbol('C', m, n) >>> D = MatrixSymbol('D', m, m) >>> X = BlockMatrix([[A, B], [C, D]]) >>> U, D, L = X.UDLdecomposition() >>> block_collapse(U*D*L) Matrix([ [A, B], [C, D]]) Raises ====== ShapeError If the block matrix is not a 2x2 matrix NonInvertibleMatrixError If the matrix "D" is non-invertible See Also ======== sympy.matrices.expressions.blockmatrix.BlockMatrix.LDUdecomposition sympy.matrices.expressions.blockmatrix.BlockMatrix.LUdecomposition """ if self.blockshape == (2, 2): [[A, B], [C, D]] = self.blocks.tolist() try: DI = D.I except NonInvertibleMatrixError: raise NonInvertibleMatrixError( 'Block UDL decomposition cannot be calculated when\ "D" is singular') Ip = Identity(A.shape[0]) Iq = Identity(B.shape[1]) Z = ZeroMatrix(*B.shape) U = BlockMatrix([[Ip, B * DI], [Z.T, Iq]]) D = BlockDiagMatrix(self.schur('D'), D) L = BlockMatrix([[Ip, Z], [DI * C, Iq]]) return U, D, L else: raise ShapeError( "Block UDL decomposition is supported only for 2x2 block matrices" )
def schur(self, mat='A', generalized=False): """Return the Schur Complement of the 2x2 BlockMatrix Parameters ========== mat : String, optional The matrix with respect to which the Schur Complement is calculated. 'A' is used by default generalized : bool, optional If True, returns the generalized Schur Component which uses Moore-Penrose Inverse Examples ======== >>> from sympy import symbols, MatrixSymbol, BlockMatrix >>> m, n = symbols('m n') >>> A = MatrixSymbol('A', n, n) >>> B = MatrixSymbol('B', n, m) >>> C = MatrixSymbol('C', m, n) >>> D = MatrixSymbol('D', m, m) >>> X = BlockMatrix([[A, B], [C, D]]) The default Schur Complement is evaluated with "A" >>> X.schur() -C*A**(-1)*B + D >>> X.schur('D') A - B*D**(-1)*C Schur complement with non-invertible matrices is not defined. Instead, the generalized Schur complement can be calculated which uses the Moore-Penrose Inverse. To achieve this, `generalized` must be set to `True` >>> X.schur('B', generalized=True) C - D*(B.T*B)**(-1)*B.T*A >>> X.schur('C', generalized=True) -A*(C.T*C)**(-1)*C.T*D + B Returns ======= M : Matrix The Schur Complement Matrix Raises ====== ShapeError If the block matrix is not a 2x2 matrix NonInvertibleMatrixError If given matrix is non-invertible References ========== .. [1] Wikipedia Article on Schur Component : https://en.wikipedia.org/wiki/Schur_complement See Also ======== sympy.matrices.matrices.MatrixBase.pinv """ if self.blockshape == (2, 2): [[A, B], [C, D]] = self.blocks.tolist() d = {'A': A, 'B': B, 'C': C, 'D': D} try: inv = (d[mat].T * d[mat] ).inv() * d[mat].T if generalized else d[mat].inv() if mat == 'A': return D - C * inv * B elif mat == 'B': return C - D * inv * A elif mat == 'C': return B - A * inv * D elif mat == 'D': return A - B * inv * C #For matrices where no sub-matrix is square return self except NonInvertibleMatrixError: raise NonInvertibleMatrixError( 'The given matrix is not invertible. Please set generalized=True \ to compute the generalized Schur Complement which uses Moore-Penrose Inverse' ) else: raise ShapeError( 'Schur Complement can only be calculated for 2x2 block matrices' )
def _eval_inverse(self): raise NonInvertibleMatrixError("Matrix det == 0; not invertible.")
def _eval_power(self, exp): # exp = -1, 0, 1 are already handled at this stage if (exp < 0) == True: raise NonInvertibleMatrixError("Matrix det == 0; not invertible") return self