def combine_kronecker(expr): """Combine KronekeckerProduct with expression. If possible write operations on KroneckerProducts of compatible shapes as a single KroneckerProduct. Examples ======== >>> from sympy.matrices.expressions import MatrixSymbol, KroneckerProduct, combine_kronecker >>> from sympy import symbols >>> m, n = symbols(r'm, n', integer=True) >>> A = MatrixSymbol('A', m, n) >>> B = MatrixSymbol('B', n, m) >>> combine_kronecker(KroneckerProduct(A, B)*KroneckerProduct(B, A)) KroneckerProduct(A*B, B*A) >>> combine_kronecker(KroneckerProduct(A, B)+KroneckerProduct(B.T, A.T)) KroneckerProduct(A + B.T, B + A.T) >>> combine_kronecker(KroneckerProduct(A, B)**m) KroneckerProduct(A**m, B**m) """ def haskron(expr): return isinstance(expr, MatrixExpr) and expr.has(KroneckerProduct) rule = exhaust( bottom_up(exhaust(condition(haskron, typed( {MatAdd: kronecker_mat_add, MatMul: kronecker_mat_mul, MatPow: kronecker_mat_pow}))))) result = rule(expr) doit = getattr(result, 'doit', None) if doit is not None: return doit() else: return result
def block_collapse(expr): """Evaluates a block matrix expression >>> from sympy import MatrixSymbol, BlockMatrix, symbols, \ Identity, Matrix, ZeroMatrix, block_collapse >>> 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]]) >>> print(B) Matrix([ [X, Z], [0, Y]]) >>> C = BlockMatrix([[Identity(n), Z]]) >>> print(C) Matrix([[I, Z]]) >>> print(block_collapse(C*B)) Matrix([[X, Z*Y + Z]]) """ hasbm = lambda expr: 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) try: return result.doit() except AttributeError: return result
def block_collapse(expr): """Evaluates a block matrix expression >>> from sympy import MatrixSymbol, BlockMatrix, symbols, \ Identity, Matrix, ZeroMatrix, block_collapse >>> 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]]) >>> print B [X, Z] [0, Y] >>> C = BlockMatrix([[Identity(n), Z]]) >>> print C [I, Z] >>> print block_collapse(C*B) [X, Z + Z*Y] """ rule = canon(typed({MatAdd: do_one(bc_matadd, bc_block_plus_ident), MatMul: do_one(bc_matmul, bc_dist), BlockMatrix: bc_unpack})) result = rule(expr) try: return result.doit() except AttributeError: return result
def combine_kronecker(expr): """Combine KronekeckerProduct with expression. If possible write operations on KroneckerProducts of compatible shapes as a single KroneckerProduct. Examples ======== >>> from sympy.matrices.expressions import MatrixSymbol, KroneckerProduct, combine_kronecker >>> from sympy import symbols >>> m, n = symbols(r'm, n', integer=True) >>> A = MatrixSymbol('A', m, n) >>> B = MatrixSymbol('B', n, m) >>> combine_kronecker(KroneckerProduct(A, B)*KroneckerProduct(B, A)) KroneckerProduct(A*B, B*A) >>> combine_kronecker(KroneckerProduct(A, B)+KroneckerProduct(B.T, A.T)) KroneckerProduct(A + B.T, B + A.T) >>> combine_kronecker(KroneckerProduct(A, B)**m) KroneckerProduct(A**m, B**m) """ def haskron(expr): return isinstance(expr, MatrixExpr) and expr.has(KroneckerProduct) rule = exhaust( bottom_up(exhaust(condition(haskron, typed( {MatAdd: kronecker_mat_add, MatMul: kronecker_mat_mul, MatPow: kronecker_mat_pow}))))) result = rule(expr) try: return result.doit() except AttributeError: return result
def block_collapse(expr): """Evaluates a block matrix expression >>> from sympy import MatrixSymbol, BlockMatrix, symbols, \ Identity, Matrix, ZeroMatrix, block_collapse >>> 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]]) >>> print B [X, Z] [0, Y] >>> C = BlockMatrix([[Identity(n), Z]]) >>> print C [I, Z] >>> print block_collapse(C*B) [X, Z + Z*Y] """ rule = canon( typed({ MatAdd: do_one(bc_matadd, bc_block_plus_ident), MatMul: do_one(bc_matmul, bc_dist), BlockMatrix: bc_unpack })) result = rule(expr) try: return result.doit() except AttributeError: return result
def block_collapse(expr): """Evaluates a block matrix expression >>> from sympy import MatrixSymbol, BlockMatrix, symbols, \ Identity, Matrix, ZeroMatrix, block_collapse >>> 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]]) >>> print(B) Matrix([ [X, Z], [0, Y]]) >>> C = BlockMatrix([[Identity(n), Z]]) >>> print(C) Matrix([[I, Z]]) >>> print(block_collapse(C*B)) Matrix([[X, Z + Z*Y]]) """ from sympy.strategies.util import expr_fns hasbm = lambda expr: isinstance(expr, MatrixExpr) and expr.has(BlockMatrix) conditioned_rl = condition( hasbm, typed( {MatAdd: do_one(bc_matadd, bc_block_plus_ident), MatMul: do_one(bc_matmul, bc_dist), MatPow: bc_matmul, Transpose: bc_transpose, Inverse: bc_inverse, BlockMatrix: do_one(bc_unpack, deblock)} ) ) rule = exhaust( bottom_up( exhaust(conditioned_rl), fns=expr_fns ) ) result = rule(expr) doit = getattr(result, 'doit', None) if doit is not None: return doit() else: return result
if exp == 1: args.append(base) else: args.append(base**exp) exp = current_exp base = current_base if exp == 1: args.append(base) else: args.append(base**exp) return newmul(factor, *args) rules = (any_zeros, remove_ids, xxinv, unpack, rm_id(lambda x: x == 1), merge_explicit, factor_in_front, flatten, combine_powers) 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 from sympy.assumptions.ask import ask, Q
def _eval_expand_kroneckerproduct(self, **hints): return flatten(canon(typed({KroneckerProduct: distribute(KroneckerProduct, MatAdd)}))(self))
>>> pprint(expr) 2*x*(R.x*R.i + R.y*R.j + R.z*R.k)*Magnitude(VectorSymbol(v1)) >>> pprint(merge_explicit(expr)) (2*R.x*x*R.i + 2*R.y*x*R.j + 2*R.z*x*R.k)*Magnitude(VectorSymbol(v1)) """ groups = sift(vecmul.args, lambda arg: not isinstance(arg, VectorExpr)) print("\t", groups) if len(groups[True]) > 1: return VecMul(*(groups[False] + [reduce(mul, groups[True])])) else: return vecmul rules_vecmul = (merge_explicit_mul, ) canonicalize_vecmul = exhaust(typed({VecMul: do_one(*rules_vecmul)})) class VecPow(VectorExpr, Pow): """ A power of Vector expressions. VecPow inherits from and operates like SymPy Pow. """ def __new__(cls, base, exp): base = S(base) exp = S(exp) if base.is_Vector: raise TypeError("Vector power not available") if exp.is_Vector: raise TypeError("Vector power not available")