def test_doit_args(): A = ImmutableMatrix([[1, 2], [3, 4]]) B = ImmutableMatrix([[2, 3], [4, 5]]) assert MatAdd(A, MatPow(B, 2)).doit() == A + B**2 assert MatAdd(A, MatMul(A, B)).doit() == A + A*B assert (MatAdd(A, X, MatMul(A, B), Y, MatAdd(2*A, B)).doit() == MatAdd(3*A + A*B + B, X, Y))
def test_Trace_doit_deep_False(): X = Matrix([[1, 2], [3, 4]]) q = MatPow(X, 2) assert Trace(q).doit(deep=False).arg == q q = MatAdd(X, 2 * X) assert Trace(q).doit(deep=False).arg == q q = MatMul(X, 2 * X) assert Trace(q).doit(deep=False).arg == q
def _(expr, assumptions): factor, mmul = expr.as_coeff_mmul() if (all(ask(Q.positive_definite(arg), assumptions) for arg in mmul.args) and factor > 0): return True if (len(mmul.args) >= 2 and mmul.args[0] == mmul.args[-1].T and ask(Q.fullrank(mmul.args[0]), assumptions)): return ask(Q.positive_definite(MatMul(*mmul.args[1:-1])), assumptions)
def MatMul(expr, assumptions): factor, mmul = expr.as_coeff_mmul() if all(ask(Q.symmetric(arg), assumptions) for arg in mmul.args): return True if len(mmul.args) >= 2 and mmul.args[0] == mmul.args[-1].T: if len(mmul.args) == 2: return True return ask(Q.symmetric(MatMul(*mmul.args[1:-1])), assumptions)
def MatMul(expr, assumptions): factor, mmul = expr.as_coeff_mmul() if all(ask(Q.symmetric(arg), assumptions) for arg in mmul.args): return True # TODO: implement sathandlers system for the matrices. # Now it duplicates the general fact: Implies(Q.diagonal, Q.symmetric). if ask(Q.diagonal(expr), assumptions): return True if len(mmul.args) >= 2 and mmul.args[0] == mmul.args[-1].T: if len(mmul.args) == 2: return True return ask(Q.symmetric(MatMul(*mmul.args[1:-1])), assumptions)
def _entry(self, i, j, **kwargs): from sympy.matrices.expressions import MatMul A = self.doit() if isinstance(A, MatPow): # We still have a MatPow, make an explicit MatMul out of it. if A.exp.is_Integer and A.exp.is_positive: A = MatMul(*[A.base for k in range(A.exp)]) elif not self._is_shape_symbolic(): return A._get_explicit_matrix()[i, j] else: # Leave the expression unevaluated: from sympy.matrices.expressions.matexpr import MatrixElement return MatrixElement(self, i, j) return A[i, j]
def _entry(self, i, j, **kwargs): from sympy.matrices.expressions import MatMul A = self.doit() if isinstance(A, MatPow): # We still have a MatPow, make an explicit MatMul out of it. if A.exp.is_Integer and A.exp.is_positive: A = MatMul(*[A.base for k in range(A.exp)]) #elif A.exp.is_Integer and self.exp.is_negative: # Note: possible future improvement: in principle we can take # positive powers of the inverse, but carefully avoid recursion, # perhaps by adding `_entry` to Inverse (as it is our subclass). # T = A.base.as_explicit().inverse() # A = MatMul(*[T for k in range(-A.exp)]) else: # Leave the expression unevaluated: from sympy.matrices.expressions.matexpr import MatrixElement return MatrixElement(self, i, j) return A[i, j]
def test_doit_nested_MatrixExpr(): X = ImmutableMatrix([[1, 2], [3, 4]]) Y = ImmutableMatrix([[2, 3], [4, 5]]) assert MatPow(MatMul(X, Y), 2).doit() == (X*Y)**2 assert MatPow(MatAdd(X, Y), 2).doit() == (X + Y)**2
def test_trace_constant_factor(): # Issue 9052: gave 2*Trace(MatMul(A)) instead of 2*Trace(A) assert trace(2 * A) == 2 * Trace(A) X = ImmutableMatrix([[1, 2], [3, 4]]) assert trace(MatMul(2, X)) == 10
def test_bc_matpow(): A = MatrixSymbol('A', n, n) assert bc_matpow(A**2) == MatMul(A, A, evaluate=False) assert bc_matpow(A**n) == A**n
def test_trace_constant_factor(): # Issue 9052: LHS gives Trace(MatMul(A)) assert trace(2 * A) == 2 * Trace(A) X = ImmutableMatrix([[1, 2], [3, 4]]) assert trace(MatMul(2, X)) == 10