Preserving dimensions when slicing symbolic block matrices in sympy

I am using sympy (python 3.6, sympy 1.0) to make it easier to compute matrix transformations in mathematical proofs.

To compute the Schur complements, it is necessary to cut off the block matrix consisting of symbolic matrices.

How to access the matrix directly with:

    M[0:1,1]

      

doesn't work I tried sympy.matrices.expressions.blockmatrix.blocks Unfortunately, blocks destroy matrix sizes when accessing a range of blocks:

    from sympy import *
    n = Symbol('n')
    Aj = MatrixSymbol('Aj', n,n)

    M = BlockMatrix([[Aj, Aj],[Aj, Aj]])
    M1 = M.blocks[0:1,0:1]
    M2 = M.blocks[0,0]

    print(M1.shape)
    print(M2.shape)

      

M.blocks returns a 1.1-dimensional matrix for M1, and M2 is right-n, n-dimensional.

Any suggestion on how to get the correct dimensions when using spacing?

+3


source to share


1 answer


The method blocks

returns an ImmutableMatrix object, not a BlockMatrix object. Here it is for reference:

def blocks(self):
    from sympy.matrices.immutable import ImmutableMatrix
    mats = self.args
    data = [[mats[i] if i == j else ZeroMatrix(mats[i].rows, mats[j].cols)
                    for j in range(len(mats))]
                    for i in range(len(mats))]
    return ImmutableMatrix(data)

      

The shape of an ImmutableMatrix object is determined by the number of characters it contains; the character structure is ignored. Hence you get (1,1).

When used, M.blocks[0,0]

you access the element of the matrix, which is Aj. This is called MatrixSymbol, so the form works as expected.



When used, M.blocks[0:1, 0:1]

you slice the SymPy matrix. Splitting always returns a sub-matrix, even if the size of the slice is 1 to 1. So you get ImmutableMatrix one recording Matrix([[Aj]])

. As mentioned above, the shape of this thing is (1,1), since no structural structure was found.

As suggested by user2357112, converting the sliced ​​block output to BlockMatrix forces the form to be defined by shape Aj

:

>>> M3 = BlockMatrix(M.blocks[0:, 0:1])
>>> M3.shape
(2*n, n)  

      

It is often useful to check the type of objects that behave in unpredictable ways: for example, type(M1)

and type(M2)

.

+1


source







All Articles