Пример #1
0
    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"
            )
Пример #2
0
    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 __pow__(self, other):
     if other != 1 and not self.is_square:
         raise ShapeError("Power of non-square matrix %s" % self)
     if other == 0:
         return Identity(self.rows)
     if other < 1:
         raise ValueError("Matrix det == 0; not invertible.")
     return self
Пример #4
0
 def __pow__(self, other):
     if not self.is_square:
         raise ShapeError("Power of non-square matrix %s" % self)
     if other is S.NegativeOne:
         return Inverse(self)
     elif other is S.Zero:
         return Identity(self.rows)
     elif other is S.One:
         return self
     return MatPow(self, other)
 def __pow__(self, other):
     if not self.is_square:
         raise ShapeError("Power of non-square matrix %s" % self)
     elif self.is_Identity:
         return self
     elif other is S.Zero:
         return Identity(self.rows)
     elif other is S.One:
         return self
     return MatPow(self, other).doit(deep=False)
Пример #6
0
 def __pow__(self, other):
     if other != 1 and not self.is_square:
         raise ShapeError("Power of non-square matrix %s" % self)
     if other == 0:
         return Identity(self.rows)
     return self
Пример #7
0
    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'
            )
Пример #8
0
def linear_factors(expr, *syms):
    """Reduce a Matrix Expression to a sum of linear factors

    Given symbols and a matrix expression linear in those symbols return a
    dict mapping symbol to the linear factor

    >>> from sympy import MatrixSymbol, linear_factors, symbols
    >>> n, m, l = symbols('n m l')
    >>> A = MatrixSymbol('A', n, m)
    >>> B = MatrixSymbol('B', m, l)
    >>> C = MatrixSymbol('C', n, l)
    >>> linear_factors(2*A*B + C, B, C)
    {B: 2*A, C: I}
    """

    expr = matrixify(expand(expr))
    d = {}
    if expr.is_Matrix and expr.is_Symbol:
        if expr in syms:
            d[expr] = Identity(expr.n)

    if expr.is_Add:
        for sym in syms:
            total_factor = 0
            for arg in expr.args:
                factor = arg.coeff(sym)
                if not factor:
                    # .coeff fails when powers are in the expression
                    if sym in arg.free_symbols:
                        raise ValueError("Expression not linear in symbols")
                    else:
                        factor = 0
                factor = sympify(factor)
                if not factor.is_Matrix:
                    if factor.is_zero:
                        factor = ZeroMatrix(expr.n, sym.n)
                        if not sym.m == expr.m:
                            raise ShapeError(
                                "%s not compatible as factor of %s" %
                                (sym, expr))
                    else:
                        factor = Identity(sym.n) * factor
                total_factor += factor
            d[sym] = total_factor
    elif expr.is_Mul:
        for sym in syms:
            factor = expr.coeff(sym)
            if not factor:
                # .coeff fails when powers are in the expression
                if sym in expr.free_symbols:
                    raise ValueError("Expression not linear in symbols")
                else:
                    factor = 0
            factor = sympify(factor)
            if not factor.is_Matrix:
                if factor.is_zero:
                    factor = ZeroMatrix(expr.n, sym.n)
                    if not sym.m == expr.m:
                        raise ShapeError("%s not compatible as factor of %s" %
                                         (sym, expr))
                else:
                    factor = Identity(sym.n) * factor
            d[sym] = factor

    if any(sym in matrix_symbols(Tuple(*d.values())) for sym in syms):
        raise ValueError("Expression not linear in symbols")

    return d