def block_collapse(expr): """Evaluates a block matrix expression >>> n, m, l = symbols('n m l') >>> X = MatrixSymbol('X', n, n) >>> Y = MatrixSymbol('Y', m, m) >>> Z = MatrixSymbol('Z', n, m) >>> B = BlockMatrix([[X, Z], [ZeroMatrix(m, n), Y]]) >>> B Matrix([ [X, Z], [0, Y]]) >>> C = BlockMatrix([[Identity(n), Z]]) >>> C Matrix([[I, Z]]) >>> block_collapse(C*B) Matrix([[X, Z + Z*Y]]) """ def hasbm(expr): return isinstance(expr, MatrixExpr) and expr.has(BlockMatrix) rule = exhaust( bottom_up(exhaust(condition(hasbm, typed( {MatAdd: do_one([bc_matadd, bc_block_plus_ident]), MatMul: do_one([bc_matmul, bc_dist]), Transpose: bc_transpose, Inverse: bc_inverse, BlockMatrix: do_one([bc_unpack, deblock])}))))) result = rule(expr) return result.doit()
if result != mmul: return newmul(factor, *result.args) # Recombine and return else: return mul def factor_in_front(mul): factor, matrices = mul.as_coeff_matrices() if factor != 1: return newmul(factor, *matrices) return mul rules = (any_zeros, remove_ids, xxinv, unpack, rm_id(lambda x: x == 1), merge_explicit, factor_in_front, flatten) canonicalize = exhaust(typed({MatMul: do_one(rules)})) def only_squares(*matrices): """ factor matrices only if they are square """ if matrices[0].rows != matrices[-1].cols: raise RuntimeError("Invalid matrices being multiplied") out = [] start = 0 for i, M in enumerate(matrices): if M.cols == matrices[start].rows: out.append(MatMul(*matrices[start:i + 1]).doit()) start = i + 1 return out
if result != mmul: return newmul(factor, *result.args) # Recombine and return else: return mul def factor_in_front(mul): factor, matrices = mul.as_coeff_matrices() if factor != 1: return newmul(factor, *matrices) return mul rules = (any_zeros, remove_ids, xxinv, unpack, rm_id(lambda x: x == 1), merge_explicit, factor_in_front, flatten) canonicalize = exhaust(typed({MatMul: do_one(rules)})) def only_squares(*matrices): """factor matrices only if they are square.""" if matrices[0].rows != matrices[-1].cols: raise RuntimeError("Invalid matrices being multiplied") out = [] start = 0 for i, M in enumerate(matrices): if M.cols == matrices[start].rows: out.append(MatMul(*matrices[start:i+1]).doit()) start = i+1 return out