Exemple #1
0
def test_squareBlockMatrix():
    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]])
    Y = BlockMatrix([[A]])

    assert X.is_square

    assert block_collapse(X + Identity(m + n)) == BlockMatrix([[A + Identity(n), B], [C, D + Identity(m)]])
    Q = X + Identity(m + n)

    assert (X + MatrixSymbol("Q", n + m, n + m)).is_MatAdd
    assert (X * MatrixSymbol("Q", n + m, n + m)).is_MatMul

    assert block_collapse(Y.I) == A.I
    assert block_collapse(X.inverse()) == BlockMatrix(
        [[(-B * D.I * C + A).I, -A.I * B * (D + -C * A.I * B).I], [-(D - C * A.I * B).I * C * A.I, (D - C * A.I * B).I]]
    )

    assert isinstance(X.inverse(), Inverse)

    assert not X.is_Identity

    Z = BlockMatrix([[Identity(n), B], [C, D]])
    assert not Z.is_Identity
Exemple #2
0
def test_BlockDiagMatrix():
    A = MatrixSymbol("A", n, n)
    B = MatrixSymbol("B", m, m)
    C = MatrixSymbol("C", l, l)
    M = MatrixSymbol("M", n + m + l, n + m + l)

    X = BlockDiagMatrix(A, B, C)
    Y = BlockDiagMatrix(A, 2 * B, 3 * C)

    assert X.blocks[1, 1] == B
    assert X.shape == (n + m + l, n + m + l)
    assert all(
        X.blocks[i, j].is_ZeroMatrix if i != j else X.blocks[i, j] in [A, B, C] for i in range(3) for j in range(3)
    )
    assert X.__class__(*X.args) == X

    assert isinstance(block_collapse(X.I * X), Identity)

    assert bc_matmul(X * X) == BlockDiagMatrix(A * A, B * B, C * C)
    assert block_collapse(X * X) == BlockDiagMatrix(A * A, B * B, C * C)
    # XXX: should be == ??
    assert block_collapse(X + X).equals(BlockDiagMatrix(2 * A, 2 * B, 2 * C))
    assert block_collapse(X * Y) == BlockDiagMatrix(A * A, 2 * B * B, 3 * C * C)
    assert block_collapse(X + Y) == BlockDiagMatrix(2 * A, 3 * B, 4 * C)

    # Ensure that BlockDiagMatrices can still interact with normal MatrixExprs
    assert (X * (2 * M)).is_MatMul
    assert (X + (2 * M)).is_MatAdd

    assert (X._blockmul(M)).is_MatMul
    assert (X._blockadd(M)).is_MatAdd
Exemple #3
0
def test_squareBlockMatrix():
    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]])
    Y = BlockMatrix([[A]])

    assert X.is_square

    assert (block_collapse(X + Identity(m + n)) == BlockMatrix(
        [[A + Identity(n), B], [C, D + Identity(m)]]))
    Q = X + Identity(m + n)

    assert (X + MatrixSymbol('Q', n + m, n + m)).is_MatAdd
    assert (X * MatrixSymbol('Q', n + m, n + m)).is_MatMul

    assert block_collapse(Y.I) == A.I
    assert block_collapse(X.inverse()) == BlockMatrix([[
        (-B * D.I * C + A).I, -A.I * B * (D + -C * A.I * B).I
    ], [-(D - C * A.I * B).I * C * A.I, (D - C * A.I * B).I]])

    assert isinstance(X.inverse(), Inverse)

    assert not X.is_Identity

    Z = BlockMatrix([[Identity(n), B], [C, D]])
    assert not Z.is_Identity
def test_BlockMatrix_inverse():
    A = MatrixSymbol('A', n, m)
    B = MatrixSymbol('B', n, n)
    C = MatrixSymbol('C', m, m)
    D = MatrixSymbol('D', m, n)
    X = BlockMatrix([[A, B], [C, D]])
    assert X.is_square
    assert isinstance(block_collapse(X.inverse()),
                      Inverse)  # Can't inverse when A, D aren't square

    # test code path for non-invertible D matrix
    A = MatrixSymbol('A', n, n)
    B = MatrixSymbol('B', n, m)
    C = MatrixSymbol('C', m, n)
    D = OneMatrix(m, m)
    X = BlockMatrix([[A, B], [C, D]])
    assert block_collapse(X.inverse()) == BlockMatrix([
        [
            A.I + A.I * B * (D - C * A.I * B).I * C * A.I,
            -A.I * B * (D - C * A.I * B).I
        ],
        [-(D - C * A.I * B).I * C * A.I, (D - C * A.I * B).I],
    ])

    # test code path for non-invertible A matrix
    A = OneMatrix(n, n)
    D = MatrixSymbol('D', m, m)
    X = BlockMatrix([[A, B], [C, D]])
    assert block_collapse(X.inverse()) == BlockMatrix([
        [(A - B * D.I * C).I, -(A - B * D.I * C).I * B * D.I],
        [
            -D.I * C * (A - B * D.I * C).I,
            D.I + D.I * C * (A - B * D.I * C).I * B * D.I
        ],
    ])
Exemple #5
0
def test_squareBlockMatrix():
    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]])
    Y = BlockMatrix([[A]])

    assert X.is_square

    assert (block_collapse(X + Identity(m + n)) ==
        BlockMatrix([[A + Identity(n), B], [C, D + Identity(m)]]))
    Q = X + Identity(m + n)

    assert block_collapse(Q.inverse()) == Inverse(block_collapse(Q))

    assert (X + MatrixSymbol('Q', n + m, n + m)).is_MatAdd
    assert (X * MatrixSymbol('Q', n + m, n + m)).is_MatMul

    assert Y.I.blocks[0, 0] == A.I
    assert X.inverse(expand=True) == BlockMatrix([
        [(-B*D.I*C + A).I, -A.I*B*(D + -C*A.I*B).I],
        [-(D - C*A.I*B).I*C*A.I, (D - C*A.I*B).I]])

    assert isinstance(X.inverse(expand=False), Inverse)
    assert isinstance(X.inverse(), Inverse)

    assert not X.is_Identity

    Z = BlockMatrix([[Identity(n), B], [C, D]])
    assert not Z.is_Identity
Exemple #6
0
def test_BlockDiagMatrix():
    A = MatrixSymbol('A', n, n)
    B = MatrixSymbol('B', m, m)
    C = MatrixSymbol('C', l, l)
    M = MatrixSymbol('M', n + m + l, n + m + l)

    X = BlockDiagMatrix(A, B, C)
    Y = BlockDiagMatrix(A, 2 * B, 3 * C)

    assert X.blocks[1, 1] == B
    assert X.shape == (n + m + l, n + m + l)
    assert all(
        X.blocks[i, j].is_ZeroMatrix if i != j else X.blocks[i,
                                                             j] in [A, B, C]
        for i in range(3) for j in range(3))
    assert X.__class__(*X.args) == X

    assert isinstance(block_collapse(X.I * X), Identity)

    assert bc_matmul(X * X) == BlockDiagMatrix(A * A, B * B, C * C)
    assert block_collapse(X * X) == BlockDiagMatrix(A * A, B * B, C * C)
    #XXX: should be == ??
    assert block_collapse(X + X).equals(BlockDiagMatrix(2 * A, 2 * B, 2 * C))
    assert block_collapse(X * Y) == BlockDiagMatrix(A * A, 2 * B * B,
                                                    3 * C * C)
    assert block_collapse(X + Y) == BlockDiagMatrix(2 * A, 3 * B, 4 * C)

    # Ensure that BlockDiagMatrices can still interact with normal MatrixExprs
    assert (X * (2 * M)).is_MatMul
    assert (X + (2 * M)).is_MatAdd

    assert (X._blockmul(M)).is_MatMul
    assert (X._blockadd(M)).is_MatAdd
Exemple #7
0
def test_block_collapse_type():
    bm1 = BlockDiagMatrix(ImmutableMatrix([1]), ImmutableMatrix([2]))
    bm2 = BlockDiagMatrix(ImmutableMatrix([3]), ImmutableMatrix([4]))

    assert bm1.T.__class__ == BlockDiagMatrix
    assert block_collapse(bm1 - bm2).__class__ == BlockDiagMatrix
    assert block_collapse(Inverse(bm1)).__class__ == BlockDiagMatrix
    assert block_collapse(Transpose(bm1)).__class__ == BlockDiagMatrix
    assert bc_transpose(Transpose(bm1)).__class__ == BlockDiagMatrix
    assert bc_inverse(Inverse(bm1)).__class__ == BlockDiagMatrix
Exemple #8
0
def test_BlockMatrix_2x2_inverse_symbolic():
    A = MatrixSymbol('A', n, m)
    B = MatrixSymbol('B', n, k - m)
    C = MatrixSymbol('C', k - n, m)
    D = MatrixSymbol('D', k - n, k - m)
    X = BlockMatrix([[A, B], [C, D]])
    assert X.is_square and X.shape == (k, k)
    assert isinstance(block_collapse(
        X.I), Inverse)  # Can't invert when none of the blocks is square

    # test code path where only A is invertible
    A = MatrixSymbol('A', n, n)
    B = MatrixSymbol('B', n, m)
    C = MatrixSymbol('C', m, n)
    D = ZeroMatrix(m, m)
    X = BlockMatrix([[A, B], [C, D]])
    assert block_collapse(X.inverse()) == BlockMatrix([
        [A.I + A.I * B * X.schur('A').I * C * A.I, -A.I * B * X.schur('A').I],
        [-X.schur('A').I * C * A.I, X.schur('A').I],
    ])

    # test code path where only B is invertible
    A = MatrixSymbol('A', n, m)
    B = MatrixSymbol('B', n, n)
    C = ZeroMatrix(m, m)
    D = MatrixSymbol('D', m, n)
    X = BlockMatrix([[A, B], [C, D]])
    assert block_collapse(X.inverse()) == BlockMatrix([
        [-X.schur('B').I * D * B.I, X.schur('B').I],
        [B.I + B.I * A * X.schur('B').I * D * B.I, -B.I * A * X.schur('B').I],
    ])

    # test code path where only C is invertible
    A = MatrixSymbol('A', n, m)
    B = ZeroMatrix(n, n)
    C = MatrixSymbol('C', m, m)
    D = MatrixSymbol('D', m, n)
    X = BlockMatrix([[A, B], [C, D]])
    assert block_collapse(X.inverse()) == BlockMatrix([
        [-C.I * D * X.schur('C').I, C.I + C.I * D * X.schur('C').I * A * C.I],
        [X.schur('C').I, -X.schur('C').I * A * C.I],
    ])

    # test code path where only D is invertible
    A = ZeroMatrix(n, n)
    B = MatrixSymbol('B', n, m)
    C = MatrixSymbol('C', m, n)
    D = MatrixSymbol('D', m, m)
    X = BlockMatrix([[A, B], [C, D]])
    assert block_collapse(X.inverse()) == BlockMatrix([
        [X.schur('D').I, -X.schur('D').I * B * D.I],
        [-D.I * C * X.schur('D').I, D.I + D.I * C * X.schur('D').I * B * D.I],
    ])
Exemple #9
0
def test_BlockMatrix():
    A = MatrixSymbol("A", n, m)
    B = MatrixSymbol("B", n, k)
    C = MatrixSymbol("C", l, m)
    D = MatrixSymbol("D", l, k)
    M = MatrixSymbol("M", m + k, p)
    N = MatrixSymbol("N", l + n, k + m)
    X = BlockMatrix(Matrix([[A, B], [C, D]]))

    assert X.__class__(*X.args) == X

    # block_collapse does nothing on normal inputs
    E = MatrixSymbol("E", n, m)
    assert block_collapse(A + 2 * E) == A + 2 * E
    F = MatrixSymbol("F", m, m)
    assert block_collapse(E.T * A * F) == E.T * A * F

    assert X.shape == (l + n, k + m)
    assert X.blockshape == (2, 2)
    assert transpose(X) == BlockMatrix(Matrix([[A.T, C.T], [B.T, D.T]]))
    assert transpose(X).shape == X.shape[::-1]

    # Test that BlockMatrices and MatrixSymbols can still mix
    assert (X * M).is_MatMul
    assert X._blockmul(M).is_MatMul
    assert (X * M).shape == (n + l, p)
    assert (X + N).is_MatAdd
    assert X._blockadd(N).is_MatAdd
    assert (X + N).shape == X.shape

    E = MatrixSymbol("E", m, 1)
    F = MatrixSymbol("F", k, 1)

    Y = BlockMatrix(Matrix([[E], [F]]))

    assert (X * Y).shape == (l + n, 1)
    assert block_collapse(X * Y).blocks[0, 0] == A * E + B * F
    assert block_collapse(X * Y).blocks[1, 0] == C * E + D * F

    # block_collapse passes down into container objects, transposes, and inverse
    assert block_collapse(transpose(X * Y)) == transpose(block_collapse(X * Y))
    assert block_collapse(Tuple(X * Y, 2 * X)) == (
        block_collapse(X * Y),
        block_collapse(2 * X),
    )

    # Make sure that MatrixSymbols will enter 1x1 BlockMatrix if it simplifies
    Ab = BlockMatrix([[A]])
    Z = MatrixSymbol("Z", *A.shape)
    assert block_collapse(Ab + Z) == A + Z
Exemple #10
0
def test_BlockDiagMatrix_nonsquare():
    A = MatrixSymbol('A', n, m)
    B = MatrixSymbol('B', k, l)
    X = BlockDiagMatrix(A, B)
    assert X.shape == (n + k, m + l)
    assert X.shape == (n + k, m + l)
    assert X.rowblocksizes == [n, k]
    assert X.colblocksizes == [m, l]
    C = MatrixSymbol('C', n, m)
    D = MatrixSymbol('D', k, l)
    Y = BlockDiagMatrix(C, D)
    assert block_collapse(X + Y) == BlockDiagMatrix(A + C, B + D)
    assert block_collapse(X * Y.T) == BlockDiagMatrix(A * C.T, B * D.T)
    raises(NonInvertibleMatrixError, lambda: BlockDiagMatrix(A, C.T).inverse())
Exemple #11
0
def test_BlockMatrix():
    A = MatrixSymbol('A', n, m)
    B = MatrixSymbol('B', n, k)
    C = MatrixSymbol('C', l, m)
    D = MatrixSymbol('D', l, k)
    M = MatrixSymbol('M', m + k, p)
    N = MatrixSymbol('N', l + n, k + m)
    X = BlockMatrix(Matrix([[A, B], [C, D]]))

    assert X.__class__(*X.args) == X

    # block_collapse does nothing on normal inputs
    E = MatrixSymbol('E', n, m)
    assert block_collapse(A + 2*E) == A + 2*E
    F = MatrixSymbol('F', m, m)
    assert block_collapse(E.T*A*F) == E.T*A*F

    assert X.shape == (l + n, k + m)
    assert X.blockshape == (2, 2)
    assert transpose(X) == BlockMatrix(Matrix([[A.T, C.T], [B.T, D.T]]))
    assert transpose(X).shape == X.shape[::-1]

    # Test that BlockMatrices and MatrixSymbols can still mix
    assert (X*M).is_MatMul
    assert X._blockmul(M).is_MatMul
    assert (X*M).shape == (n + l, p)
    assert (X + N).is_MatAdd
    assert X._blockadd(N).is_MatAdd
    assert (X + N).shape == X.shape

    E = MatrixSymbol('E', m, 1)
    F = MatrixSymbol('F', k, 1)

    Y = BlockMatrix(Matrix([[E], [F]]))

    assert (X*Y).shape == (l + n, 1)
    assert block_collapse(X*Y).blocks[0, 0] == A*E + B*F
    assert block_collapse(X*Y).blocks[1, 0] == C*E + D*F

    # block_collapse passes down into container objects, transposes, and inverse
    assert block_collapse(transpose(X*Y)) == transpose(block_collapse(X*Y))
    assert block_collapse(Tuple(X*Y, 2*X)) == (
        block_collapse(X*Y), block_collapse(2*X))

    # Make sure that MatrixSymbols will enter 1x1 BlockMatrix if it simplifies
    Ab = BlockMatrix([[A]])
    Z = MatrixSymbol('Z', *A.shape)
    assert block_collapse(Ab + Z) == A + Z
Exemple #12
0
def test_block_lu_decomposition():
    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]])

    #LDU decomposition
    L, D, U = X.LDUdecomposition()
    assert block_collapse(L*D*U) == X

    #UDL decomposition
    U, D, L = X.UDLdecomposition()
    assert block_collapse(U*D*L) == X

    #LU decomposition
    L, U = X.LUdecomposition()
    assert block_collapse(L*U) == X
Exemple #13
0
def test_BlockMatrix_3x3_symbolic():
    # Only test one of these, instead of all permutations, because it's slow
    rowblocksizes = (n, m, k)
    colblocksizes = (m, k, n)
    K = BlockMatrix([
        [MatrixSymbol('M%s%s' % (rows, cols), rows, cols) for cols in colblocksizes]
        for rows in rowblocksizes
    ])
    collapse = block_collapse(K.I)
    assert isinstance(collapse, BlockMatrix)
Exemple #14
0
def test_BlockMatrix_2x2_inverse_numeric():
    """Test 2x2 block matrix inversion numerically for all 4 formulas"""
    M = Matrix([[1, 2], [3, 4]])
    # rank deficient matrices that have full rank when two of them combined
    D1 = Matrix([[1, 2], [2, 4]])
    D2 = Matrix([[1, 3], [3, 9]])
    D3 = Matrix([[1, 4], [4, 16]])
    assert D1.rank() == D2.rank() == D3.rank() == 1
    assert (D1 + D2).rank() == (D2 + D3).rank() == (D3 + D1).rank() == 2

    # Only A is invertible
    K = BlockMatrix([[M, D1], [D2, D3]])
    assert block_collapse(K.inv()).as_explicit() == K.as_explicit().inv()
    # Only B is invertible
    K = BlockMatrix([[D1, M], [D2, D3]])
    assert block_collapse(K.inv()).as_explicit() == K.as_explicit().inv()
    # Only C is invertible
    K = BlockMatrix([[D1, D2], [M, D3]])
    assert block_collapse(K.inv()).as_explicit() == K.as_explicit().inv()
    # Only D is invertible
    K = BlockMatrix([[D1, D2], [D3, M]])
    assert block_collapse(K.inv()).as_explicit() == K.as_explicit().inv()
Exemple #15
0
def test_issue_21866():
    n  = 10
    I  = Identity(n)
    O  = ZeroMatrix(n, n)
    A  = BlockMatrix([[  I,  O,  O,  O ],
                      [  O,  I,  O,  O ],
                      [  O,  O,  I,  O ],
                      [  I,  O,  O,  I ]])
    Ainv = block_collapse(A.inv())
    AinvT = BlockMatrix([[  I,  O,  O,  O ],
                      [  O,  I,  O,  O ],
                      [  O,  O,  I,  O ],
                      [  -I,  O,  O,  I ]])
    assert Ainv == AinvT
Exemple #16
0
def test_issue_2460():
    bdm1 = BlockDiagMatrix(Matrix([i]), Matrix([j]))
    bdm2 = BlockDiagMatrix(Matrix([k]), Matrix([l]))
    assert block_collapse(bdm1 + bdm2) == BlockDiagMatrix(Matrix([i + k]), Matrix([j + l]))
Exemple #17
0
def test_issue_17624():
    a = MatrixSymbol("a", 2, 2)
    z = ZeroMatrix(2, 2)
    b = BlockMatrix([[a, z], [z, z]])
    assert block_collapse(b * b) == BlockMatrix([[a**2, z], [z, z]])
    assert block_collapse(b * b * b) == BlockMatrix([[a**3, z], [z, z]])
Exemple #18
0
def test_block_collapse_explicit_matrices():
    A = Matrix([[1, 2], [3, 4]])
    assert block_collapse(BlockMatrix([[A]])) == A

    A = ImmutableSparseMatrix([[1, 2], [3, 4]])
    assert block_collapse(BlockMatrix([[A]])) == A