def MatrixSlice(expr, assumptions): if AskDiagonalHandler._is_empty_or_1x1(expr): return True if not expr.on_diag: return None else: return ask(Q.diagonal(expr.parent), assumptions)
def _(expr, assumptions): if _is_empty_or_1x1(expr): return True if not expr.on_diag: return None else: return ask(Q.diagonal(expr.parent), assumptions)
def doit(self, **hints): from sympy.assumptions import ask, Q from sympy import Transpose, Mul, MatMul from sympy import MatrixBase, eye vector = self._vector # This accounts for shape (1, 1) and identity matrices, among others: if ask(Q.diagonal(vector)): return vector if isinstance(vector, MatrixBase): ret = eye(max(vector.shape)) for i in range(ret.shape[0]): ret[i, i] = vector[i] return type(vector)(ret) if vector.is_MatMul: matrices = [arg for arg in vector.args if arg.is_Matrix] scalars = [arg for arg in vector.args if arg not in matrices] if scalars: return ( Mul.fromiter(scalars) * DiagMatrix(MatMul.fromiter(matrices).doit()).doit() ) if isinstance(vector, Transpose): vector = vector.arg return DiagMatrix(vector)
def MatrixSlice(expr, assumptions): # 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 not expr.on_diag: return None else: return ask(Q.symmetric(expr.parent), assumptions)
def MatrixSymbol(expr, assumptions): if not expr.is_square: return False # 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 Q.symmetric(expr) in conjuncts(assumptions): return True
def MatPow(expr, assumptions): # only for integer powers base, exp = expr.args int_exp = ask(Q.integer(exp), assumptions) if not int_exp: return None non_negative = ask(~Q.negative(exp), assumptions) if (non_negative or non_negative == False and ask(Q.invertible(base), assumptions)): return ask(Q.diagonal(base), assumptions) return None
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 doit(self, **hints): from sympy.assumptions import ask, Q from sympy import Transpose, Mul, MatMul vector = self._vector # This accounts for shape (1, 1) and identity matrices, among others: if ask(Q.diagonal(vector)): return vector if vector.is_MatMul: matrices = [arg for arg in vector.args if arg.is_Matrix] scalars = [arg for arg in vector.args if arg not in matrices] if scalars: return Mul.fromiter(scalars)*DiagonalizeVector(MatMul.fromiter(matrices).doit()).doit() if isinstance(vector, Transpose): vector = vector.arg return DiagonalizeVector(vector)
def MatAdd(expr, assumptions): if all(ask(Q.diagonal(arg), assumptions) for arg in expr.args): return True
def MatMul(expr, assumptions): factor, matrices = expr.as_coeff_matrices() if all(ask(Q.diagonal(m), assumptions) for m in matrices): return True
def MatMul(expr, assumptions): if AskDiagonalHandler._is_empty_or_1x1(expr): return True factor, matrices = expr.as_coeff_matrices() if all(ask(Q.diagonal(m), assumptions) for m in matrices): return True
def MatrixSymbol(expr, assumptions): if AskDiagonalHandler._is_empty_or_1x1(expr): return True if Q.diagonal(expr) in conjuncts(assumptions): return True
def get_known_facts(x=None): """ Facts between unary predicates. Parameters ========== x : Symbol, optional Placeholder symbol for unary facts. Default is ``Symbol('x')``. Returns ======= fact : Known facts in conjugated normal form. """ if x is None: x = Symbol('x') fact = And( # primitive predicates for extended real exclude each other. Exclusive(Q.negative_infinite(x), Q.negative(x), Q.zero(x), Q.positive(x), Q.positive_infinite(x)), # build complex plane Exclusive(Q.real(x), Q.imaginary(x)), Implies(Q.real(x) | Q.imaginary(x), Q.complex(x)), # other subsets of complex Exclusive(Q.transcendental(x), Q.algebraic(x)), Equivalent(Q.real(x), Q.rational(x) | Q.irrational(x)), Exclusive(Q.irrational(x), Q.rational(x)), Implies(Q.rational(x), Q.algebraic(x)), # integers Exclusive(Q.even(x), Q.odd(x)), Implies(Q.integer(x), Q.rational(x)), Implies(Q.zero(x), Q.even(x)), Exclusive(Q.composite(x), Q.prime(x)), Implies(Q.composite(x) | Q.prime(x), Q.integer(x) & Q.positive(x)), Implies(Q.even(x) & Q.positive(x) & ~Q.prime(x), Q.composite(x)), # hermitian and antihermitian Implies(Q.real(x), Q.hermitian(x)), Implies(Q.imaginary(x), Q.antihermitian(x)), Implies(Q.zero(x), Q.hermitian(x) | Q.antihermitian(x)), # define finity and infinity, and build extended real line Exclusive(Q.infinite(x), Q.finite(x)), Implies(Q.complex(x), Q.finite(x)), Implies( Q.negative_infinite(x) | Q.positive_infinite(x), Q.infinite(x)), # commutativity Implies(Q.finite(x) | Q.infinite(x), Q.commutative(x)), # matrices Implies(Q.orthogonal(x), Q.positive_definite(x)), Implies(Q.orthogonal(x), Q.unitary(x)), Implies(Q.unitary(x) & Q.real_elements(x), Q.orthogonal(x)), Implies(Q.unitary(x), Q.normal(x)), Implies(Q.unitary(x), Q.invertible(x)), Implies(Q.normal(x), Q.square(x)), Implies(Q.diagonal(x), Q.normal(x)), Implies(Q.positive_definite(x), Q.invertible(x)), Implies(Q.diagonal(x), Q.upper_triangular(x)), Implies(Q.diagonal(x), Q.lower_triangular(x)), Implies(Q.lower_triangular(x), Q.triangular(x)), Implies(Q.upper_triangular(x), Q.triangular(x)), Implies(Q.triangular(x), Q.upper_triangular(x) | Q.lower_triangular(x)), Implies(Q.upper_triangular(x) & Q.lower_triangular(x), Q.diagonal(x)), Implies(Q.diagonal(x), Q.symmetric(x)), Implies(Q.unit_triangular(x), Q.triangular(x)), Implies(Q.invertible(x), Q.fullrank(x)), Implies(Q.invertible(x), Q.square(x)), Implies(Q.symmetric(x), Q.square(x)), Implies(Q.fullrank(x) & Q.square(x), Q.invertible(x)), Equivalent(Q.invertible(x), ~Q.singular(x)), Implies(Q.integer_elements(x), Q.real_elements(x)), Implies(Q.real_elements(x), Q.complex_elements(x)), ) return fact
def _(expr, assumptions): if _is_empty_or_1x1(expr): return True if Q.diagonal(expr) in conjuncts(assumptions): return True
def Inverse(expr, assumptions): return ask(Q.diagonal(expr.arg), assumptions)
def MatrixSymbol(expr, assumptions): if Q.diagonal(expr) in conjuncts(assumptions): return True
def _(expr, assumptions): if _is_empty_or_1x1(expr): return True factor, matrices = expr.as_coeff_matrices() if all(ask(Q.diagonal(m), assumptions) for m in matrices): return True
def Transpose(expr, assumptions): return ask(Q.diagonal(expr.arg), assumptions)
def MatrixSlice(expr, assumptions): if not expr.on_diag: return None else: return ask(Q.diagonal(expr.parent), assumptions)
def _(expr, assumptions): return ask(Q.diagonal(expr.arg), assumptions)