def test_array_expr_zero_array(): za1 = ZeroArray(k, l, m, n) zm1 = ZeroMatrix(m, n) za2 = ZeroArray(k, m, m, n) zm2 = ZeroMatrix(m, m) zm3 = ZeroMatrix(k, k) assert CodegenArrayTensorProduct(M, N, za1) == ZeroArray(k, k, k, k, k, l, m, n) assert CodegenArrayTensorProduct(M, N, zm1) == ZeroArray(k, k, k, k, m, n) assert CodegenArrayContraction(za1, (3,)) == ZeroArray(k, l, m) assert CodegenArrayContraction(zm1, (1,)) == ZeroArray(m) assert CodegenArrayContraction(za2, (1, 2)) == ZeroArray(k, n) assert CodegenArrayContraction(zm2, (0, 1)) == 0 assert CodegenArrayDiagonal(za2, (1, 2)) == ZeroArray(k, n, m) assert CodegenArrayDiagonal(zm2, (0, 1)) == ZeroArray(m) assert CodegenArrayPermuteDims(za1, [2, 1, 3, 0]) == ZeroArray(m, l, n, k) assert CodegenArrayPermuteDims(zm1, [1, 0]) == ZeroArray(n, m) assert CodegenArrayElementwiseAdd(za1) == za1 assert CodegenArrayElementwiseAdd(zm1) == ZeroArray(m, n) tp1 = CodegenArrayTensorProduct(MatrixSymbol("A", k, l), MatrixSymbol("B", m, n)) assert CodegenArrayElementwiseAdd(tp1, za1) == tp1 tp2 = CodegenArrayTensorProduct(MatrixSymbol("C", k, l), MatrixSymbol("D", m, n)) assert CodegenArrayElementwiseAdd(tp1, za1, tp2) == CodegenArrayElementwiseAdd(tp1, tp2) assert CodegenArrayElementwiseAdd(M, zm3) == M assert CodegenArrayElementwiseAdd(M, N, zm3) == CodegenArrayElementwiseAdd(M, N)
def H_representation(V: Iterable[Matrix], S: Iterable[Matrix]): A_1 = BlockMatrix(tuple(V)).as_explicit() A_2 = BlockMatrix(tuple(S)).as_explicit() n = A_1.shape[0] p = A_1.shape[1] q = A_2.shape[1] A_Q = BlockMatrix([ [Identity(n), -A_1, -A_2], [-Identity(n), A_1, A_2], [Matrix([n*[0]]), Matrix([p*[1]]), Matrix([q*[0]])], [ZeroMatrix(p, n), -Identity(p), ZeroMatrix(p, q)], [ZeroMatrix(q, n), ZeroMatrix(q, p), -Identity(q)] ]).as_explicit() b_Q = Matrix(2*n*[0] + [1] + p*[0] + q*[0]) return A_Q, b_Q
def test_multivariate_crosscovariance(): raises(ShapeError, lambda: Covariance(X, Y.T)) raises(ShapeError, lambda: Covariance(X, A)) expr = Covariance(a.T, b.T) assert expr.shape == (1, 1) assert expr.expand() == ZeroMatrix(1, 1) expr = Covariance(a, b) assert expr == Covariance(a, b) == CrossCovarianceMatrix(a, b) assert expr.expand() == ZeroMatrix(k, k) assert expr.shape == (k, k) assert expr.rows == k assert expr.cols == k assert isinstance(expr, CrossCovarianceMatrix) expr = Covariance(A * X + a, b) assert expr.expand() == ZeroMatrix(k, k) expr = Covariance(X, Y) assert isinstance(expr, CrossCovarianceMatrix) assert expr.expand() == expr expr = Covariance(X, X) assert isinstance(expr, CrossCovarianceMatrix) assert expr.expand() == VarianceMatrix(X) expr = Covariance(X + Y, Z) assert isinstance(expr, CrossCovarianceMatrix) assert expr.expand() == CrossCovarianceMatrix( X, Z) + CrossCovarianceMatrix(Y, Z) expr = Covariance(A * X, Y) assert isinstance(expr, CrossCovarianceMatrix) assert expr.expand() == A * CrossCovarianceMatrix(X, Y) expr = Covariance(X, B * Y) assert isinstance(expr, CrossCovarianceMatrix) assert expr.expand() == CrossCovarianceMatrix(X, Y) * B.T expr = Covariance(A * X + a, B.T * Y + b) assert isinstance(expr, CrossCovarianceMatrix) assert expr.expand() == A * CrossCovarianceMatrix(X, Y) * B expr = Covariance(A * X + B * Y + a, C.T * Z + D.T * W + b) assert isinstance(expr, CrossCovarianceMatrix) assert expr.expand() == A*CrossCovarianceMatrix(X, W)*D + A*CrossCovarianceMatrix(X, Z)*C \ + B*CrossCovarianceMatrix(Y, W)*D + B*CrossCovarianceMatrix(Y, Z)*C
def test_triangular(): assert ask(Q.upper_triangular(X + Z.T + Identity(2)), Q.upper_triangular(X) & Q.lower_triangular(Z)) is True assert ask(Q.upper_triangular(X * Z.T), Q.upper_triangular(X) & Q.lower_triangular(Z)) is True assert ask(Q.lower_triangular(Identity(3))) is True assert ask(Q.lower_triangular(ZeroMatrix(3, 3))) is True
def _get_blocks(param): if param == 'covar': S_11 = self.covar.blockform if S_11 is None: S_11 = [[self.covar]] S_12 = [[ZeroMatrix(i.shape[0], j.shape[0]) for j in comp2] for i in comp1] S_21 = utils.mattrans(S_12) S_22 = other.covar.blockform if S_22 is None: S_22 = [[other.covar]] return S_11, S_12, S_21, S_22 elif param == 'mean': mu_1 = self.mean.blockform if mu_1 is None: if not self.mean.expanded is None: mu_1 = [self.mean.expanded] else: mu_1 = [self.mean] mu_2 = other.mean.blockform if mu_2 is None: if not other.mean.expanded is None: mu_2 = [other.mean.expanded] else: mu_2 = [other.mean] return mu_1, mu_2 else: raise Exception("Invalid entry for param")
def test_diagonal(): assert ask(Q.diagonal(X + Z.T + Identity(2)), Q.diagonal(X) & Q.diagonal(Z)) is True assert ask(Q.diagonal(ZeroMatrix(3, 3))) assert ask(Q.lower_triangular(X) & Q.upper_triangular(X), Q.diagonal(X)) assert ask(Q.diagonal(X), Q.lower_triangular(X) & Q.upper_triangular(X)) assert ask(Q.symmetric(X), Q.diagonal(X)) assert ask(Q.triangular(X), Q.diagonal(X))
def _get_zero_with_shape_like(cls, expr): if isinstance(expr, (MatrixCommon, NDimArray)): return expr.zeros(*expr.shape) elif isinstance(expr, MatrixExpr): return ZeroMatrix(*expr.shape) else: raise RuntimeError( "Unable to determine shape of array-derivative.")
def any_zeros(mul): if any([ arg.is_zero or (arg.is_Matrix and arg.is_ZeroMatrix) for arg in mul.args ]): matrices = [arg for arg in mul.args if arg.is_Matrix] return ZeroMatrix(matrices[0].rows, matrices[-1].cols) return mul
def test_arrayexpr_convert_array_to_matrix(): cg = ArrayContraction(ArrayTensorProduct(M), (0, 1)) assert convert_array_to_matrix(cg) == Trace(M) cg = ArrayContraction(ArrayTensorProduct(M, N), (0, 1), (2, 3)) assert convert_array_to_matrix(cg) == Trace(M) * Trace(N) cg = ArrayContraction(ArrayTensorProduct(M, N), (0, 3), (1, 2)) assert convert_array_to_matrix(cg) == Trace(M * N) cg = ArrayContraction(ArrayTensorProduct(M, N), (0, 2), (1, 3)) assert convert_array_to_matrix(cg) == Trace(M * N.T) cg = convert_matrix_to_array(M * N * P) assert convert_array_to_matrix(cg) == M * N * P cg = convert_matrix_to_array(M * N.T * P) assert convert_array_to_matrix(cg) == M * N.T * P cg = ArrayContraction(ArrayTensorProduct(M,N,P,Q), (1, 2), (5, 6)) assert convert_array_to_matrix(cg) == ArrayTensorProduct(M * N, P * Q) cg = ArrayContraction(ArrayTensorProduct(-2, M, N), (1, 2)) assert convert_array_to_matrix(cg) == -2 * M * N a = MatrixSymbol("a", k, 1) b = MatrixSymbol("b", k, 1) c = MatrixSymbol("c", k, 1) cg = PermuteDims( ArrayContraction( ArrayTensorProduct( a, ArrayAdd( ArrayTensorProduct(b, c), ArrayTensorProduct(c, b), ) ), (2, 4)), [0, 1, 3, 2]) assert convert_array_to_matrix(cg) == a * (b.T * c + c.T * b) za = ZeroArray(m, n) assert convert_array_to_matrix(za) == ZeroMatrix(m, n) cg = ArrayTensorProduct(3, M) assert convert_array_to_matrix(cg) == 3 * M # Partial conversion to matrix multiplication: expr = ArrayContraction(ArrayTensorProduct(M, N, P, Q), (0, 2), (1, 4, 6)) assert convert_array_to_matrix(expr) == ArrayContraction(ArrayTensorProduct(M.T*N, P, Q), (0, 2, 4)) x = MatrixSymbol("x", k, 1) cg = PermuteDims( ArrayContraction(ArrayTensorProduct(OneArray(1), x, OneArray(1), DiagMatrix(Identity(1))), (0, 5)), Permutation(1, 2, 3)) assert convert_array_to_matrix(cg) == x expr = ArrayAdd(M, PermuteDims(M, [1, 0])) assert convert_array_to_matrix(expr) == M + Transpose(M)
def test_fullrank(): assert ask(Q.fullrank(X), Q.fullrank(X)) assert ask(Q.fullrank(X.T), Q.fullrank(X)) is True assert ask(Q.fullrank(X)) is None assert ask(Q.fullrank(Y)) is None assert ask(Q.fullrank(X * Z), Q.fullrank(X) & Q.fullrank(Z)) is True assert ask(Q.fullrank(Identity(3))) is True assert ask(Q.fullrank(ZeroMatrix(3, 3))) is False assert ask(Q.invertible(X), ~Q.fullrank(X)) == False
def test_matrix_derivative_by_scalar(): assert A.diff(i) == ZeroMatrix(k, k) assert (A*(X + B)*c).diff(i) == ZeroMatrix(k, 1) assert x.diff(i) == ZeroMatrix(k, 1) assert (x.T*y).diff(i) == ZeroMatrix(1, 1) assert (x*x.T).diff(i) == ZeroMatrix(k, k) assert (x + y).diff(i) == ZeroMatrix(k, 1) assert hadamard_power(x, 2).diff(i) == ZeroMatrix(k, 1) assert hadamard_power(x, i).diff(i) == HadamardProduct(x.applyfunc(log), HadamardPower(x, i)) assert hadamard_product(x, y).diff(i) == ZeroMatrix(k, 1) assert hadamard_product(i*OneMatrix(k, 1), x, y).diff(i) == hadamard_product(x, y) assert (i*x).diff(i) == x assert (sin(i)*A*B*x).diff(i) == cos(i)*A*B*x assert x.applyfunc(sin).diff(i) == ZeroMatrix(k, 1) assert Trace(i**2*X).diff(i) == 2*i*Trace(X)
def klee_minty(n: int, µ): A = ZeroMatrix(2*n, n).as_mutable() A[0,0] = 1 A[1,0] = -1 for i in range(1, n): A[2*i,i-1:i+1] = [[µ, 1]] A[2*i+1,i-1:i+1] = [[µ, -1]] b = Matrix(2*n*[1]) c = Matrix((n-1)*[0] + [1]) return A, b, c
def expand(self, **hints): arg = self.args[0] condition = self._condition if not is_random(arg): return ZeroMatrix(*self.shape) if isinstance(arg, RandomSymbol): return self elif isinstance(arg, Add): rv = [] for a in arg.args: if is_random(a): rv.append(a) variances = Add( *map(lambda xv: Variance(xv, condition).expand(), rv)) map_to_covar = lambda x: 2 * Covariance(*x, condition=condition ).expand() covariances = Add( *map(map_to_covar, itertools.combinations(rv, 2))) return variances + covariances elif isinstance(arg, (Mul, MatMul)): nonrv = [] rv = [] for a in arg.args: if is_random(a): rv.append(a) else: nonrv.append(a) if len(rv) == 0: return ZeroMatrix(*self.shape) # Avoid possible infinite loops with MatMul: if len(nonrv) == 0: return self # Variance of many multiple matrix products is not implemented: if len(rv) > 1: return self return Mul.fromiter(nonrv) * Variance( Mul.fromiter(rv), condition) * (Mul.fromiter(nonrv)).transpose() # this expression contains a RandomSymbol somehow: return self
def test_codegen_array_recognize_matrix_mul_lines(): cg = CodegenArrayContraction(CodegenArrayTensorProduct(M), (0, 1)) assert recognize_matrix_expression(cg) == Trace(M) cg = CodegenArrayContraction(CodegenArrayTensorProduct(M, N), (0, 1), (2, 3)) assert recognize_matrix_expression(cg) == Trace(M) * Trace(N) cg = CodegenArrayContraction(CodegenArrayTensorProduct(M, N), (0, 3), (1, 2)) assert recognize_matrix_expression(cg) == Trace(M * N) cg = CodegenArrayContraction(CodegenArrayTensorProduct(M, N), (0, 2), (1, 3)) assert recognize_matrix_expression(cg) == Trace(M * N.T) cg = parse_indexed_expression((M * N * P)[i, j]) assert recognize_matrix_expression(cg) == M * N * P cg = parse_matrix_expression(M * N * P) assert recognize_matrix_expression(cg) == M * N * P cg = parse_indexed_expression((M * N.T * P)[i, j]) assert recognize_matrix_expression(cg) == M * N.T * P cg = parse_matrix_expression(M * N.T * P) assert recognize_matrix_expression(cg) == M * N.T * P cg = CodegenArrayContraction(CodegenArrayTensorProduct(M, N, P, Q), (1, 2), (5, 6)) assert recognize_matrix_expression(cg) == CodegenArrayTensorProduct( M * N, P * Q) expr = -2 * M * N elem = expr[i, j] cg = parse_indexed_expression(elem) assert recognize_matrix_expression(cg) == -2 * M * N a = MatrixSymbol("a", k, 1) b = MatrixSymbol("b", k, 1) c = MatrixSymbol("c", k, 1) cg = CodegenArrayPermuteDims( CodegenArrayContraction( CodegenArrayTensorProduct( a, CodegenArrayElementwiseAdd( CodegenArrayTensorProduct(b, c), CodegenArrayTensorProduct(c, b), )), (2, 4)), [0, 1, 3, 2]) assert recognize_matrix_expression(cg) == a * (b.T * c + c.T * b) za = ZeroArray(m, n) assert recognize_matrix_expression(za) == ZeroMatrix(m, n) cg = CodegenArrayTensorProduct(3, M) assert recognize_matrix_expression(cg) == 3 * M
def _test_orthogonal_unitary(predicate): assert ask(predicate(X), predicate(X)) assert ask(predicate(X.T), predicate(X)) is True assert ask(predicate(X.I), predicate(X)) is True assert ask(predicate(Y)) is False assert ask(predicate(X)) is None assert ask(predicate(X * Z * X), predicate(X) & predicate(Z)) is True assert ask(predicate(Identity(3))) is True assert ask(predicate(ZeroMatrix(3, 3))) is False assert ask(Q.invertible(X), predicate(X)) assert not ask(predicate(X + Z), predicate(X) & predicate(Z))
def test_invertible(): assert ask(Q.invertible(X), Q.invertible(X)) assert ask(Q.invertible(Y)) is False assert ask(Q.invertible(X * Y), Q.invertible(X)) is False assert ask(Q.invertible(X * Z), Q.invertible(X)) is None assert ask(Q.invertible(X * Z), Q.invertible(X) & Q.invertible(Z)) is True assert ask(Q.invertible(X.T)) is None assert ask(Q.invertible(X.T), Q.invertible(X)) is True assert ask(Q.invertible(X.I)) is True assert ask(Q.invertible(Identity(3))) is True assert ask(Q.invertible(ZeroMatrix(3, 3))) is False
def test_orthogonal(): assert ask(Q.orthogonal(X), Q.orthogonal(X)) assert ask(Q.orthogonal(X.T), Q.orthogonal(X)) is True assert ask(Q.orthogonal(X.I), Q.orthogonal(X)) is True assert ask(Q.orthogonal(Y)) is False assert ask(Q.orthogonal(X)) is None assert ask(Q.orthogonal(X*Z*X), Q.orthogonal(X) & Q.orthogonal(Z)) is True assert ask(Q.orthogonal(Identity(3))) is True assert ask(Q.orthogonal(ZeroMatrix(3, 3))) is False assert ask(Q.invertible(X), Q.orthogonal(X)) assert not ask(Q.orthogonal(X + Z), Q.orthogonal(X) & Q.orthogonal(Z))
def test_subs_Matrix(): z = zeros(2) z1 = ZeroMatrix(2, 2) assert (x * y).subs({x: z, y: 0}) in [z, z1] assert (x * y).subs({y: z, x: 0}) == 0 assert (x * y).subs({y: z, x: 0}, simultaneous=True) in [z, z1] assert (x + y).subs({x: z, y: z}, simultaneous=True) in [z, z1] assert (x + y).subs({x: z, y: z}) in [z, z1] # Issue #15528 assert Mul(Matrix([[3]]), x).subs(x, 2.0) == Matrix([[6.0]]) # Does not raise a TypeError, see comment on the MatAdd postprocessor assert Add(Matrix([[3]]), x).subs(x, 2.0) == Add(Matrix([[3]]), 2.0)
def test_canonicalize(): X = MatrixSymbol('X', 2, 2) Y = MatrixSymbol('Y', 2, 2) expr = HadamardProduct(X, check=False) assert isinstance(expr, HadamardProduct) expr2 = expr.doit() # unpack is called assert isinstance(expr2, MatrixSymbol) Z = ZeroMatrix(2, 2) U = OneMatrix(2, 2) assert HadamardProduct(Z, X).doit() == Z assert HadamardProduct(U, X, X, U).doit() == HadamardPower(X, 2) assert HadamardProduct(X, U, Y).doit() == HadamardProduct(X, Y) assert HadamardProduct(X, Z, U, Y).doit() == Z
def test_NumPyPrinter(): from sympy import ( Lambda, ZeroMatrix, OneMatrix, FunctionMatrix, HadamardProduct, KroneckerProduct, Adjoint, DiagonalOf, DiagMatrix, DiagonalMatrix, ) from sympy.abc import a, b p = NumPyPrinter() assert p.doprint(sign(x)) == "numpy.sign(x)" A = MatrixSymbol("A", 2, 2) B = MatrixSymbol("B", 2, 2) C = MatrixSymbol("C", 1, 5) D = MatrixSymbol("D", 3, 4) assert p.doprint(A**(-1)) == "numpy.linalg.inv(A)" assert p.doprint(A**5) == "numpy.linalg.matrix_power(A, 5)" assert p.doprint(Identity(3)) == "numpy.eye(3)" u = MatrixSymbol("x", 2, 1) v = MatrixSymbol("y", 2, 1) assert p.doprint(MatrixSolve(A, u)) == "numpy.linalg.solve(A, x)" assert p.doprint(MatrixSolve(A, u) + v) == "numpy.linalg.solve(A, x) + y" assert p.doprint(ZeroMatrix(2, 3)) == "numpy.zeros((2, 3))" assert p.doprint(OneMatrix(2, 3)) == "numpy.ones((2, 3))" assert (p.doprint(FunctionMatrix(4, 5, Lambda( (a, b), a + b))) == "numpy.fromfunction(lambda a, b: a + b, (4, 5))") assert p.doprint(HadamardProduct(A, B)) == "numpy.multiply(A, B)" assert p.doprint(KroneckerProduct(A, B)) == "numpy.kron(A, B)" assert p.doprint(Adjoint(A)) == "numpy.conjugate(numpy.transpose(A))" assert p.doprint(DiagonalOf(A)) == "numpy.reshape(numpy.diag(A), (-1, 1))" assert p.doprint(DiagMatrix(C)) == "numpy.diagflat(C)" assert p.doprint(DiagonalMatrix(D)) == "numpy.multiply(D, numpy.eye(3, 4))" # Workaround for numpy negative integer power errors assert p.doprint(x**-1) == "x**(-1.0)" assert p.doprint(x**-2) == "x**(-2.0)" assert p.doprint(S.Exp1) == "numpy.e" assert p.doprint(S.Pi) == "numpy.pi" assert p.doprint(S.EulerGamma) == "numpy.euler_gamma" assert p.doprint(S.NaN) == "numpy.nan" assert p.doprint(S.Infinity) == "numpy.PINF" assert p.doprint(S.NegativeInfinity) == "numpy.NINF"
def test_matrix_derivative_by_scalar(): assert A.diff(i) == ZeroMatrix(k, k) assert (A*(X + B)*c).diff(i) == ZeroMatrix(k, 1) assert x.diff(i) == ZeroMatrix(k, 1) assert (x.T*y).diff(i) == ZeroMatrix(1, 1) assert (x*x.T).diff(i) == ZeroMatrix(k, k) assert (x + y).diff(i) == ZeroMatrix(k, 1) assert hadamard_power(x, 2).diff(i) == ZeroMatrix(k, 1) assert hadamard_power(x, i).diff(i).dummy_eq( HadamardProduct(x.applyfunc(log), HadamardPower(x, i))) assert hadamard_product(x, y).diff(i) == ZeroMatrix(k, 1) assert hadamard_product(i*OneMatrix(k, 1), x, y).diff(i) == hadamard_product(x, y) assert (i*x).diff(i) == x assert (sin(i)*A*B*x).diff(i) == cos(i)*A*B*x assert x.applyfunc(sin).diff(i) == ZeroMatrix(k, 1) assert Trace(i**2*X).diff(i) == 2*i*Trace(X) mu = symbols("mu") expr = (2*mu*x) assert expr.diff(x) == 2*mu*Identity(k)
def test_block_index(): I = Identity(3) Z = ZeroMatrix(3, 3) B = BlockMatrix([[I, I], [I, I]]) e3 = ImmutableMatrix(eye(3)) BB = BlockMatrix([[e3, e3], [e3, e3]]) assert B[0, 0] == B[3, 0] == B[0, 3] == B[3, 3] == 1 assert B[4, 3] == B[5, 1] == 0 BB = BlockMatrix([[e3, e3], [e3, e3]]) assert B.as_explicit() == BB.as_explicit() BI = BlockMatrix([[I, Z], [Z, I]]) assert BI.as_explicit().equals(eye(6))
def test_multivariate_variance(): raises(ShapeError, lambda: Variance(A)) expr = Variance(a) # type: VarianceMatrix assert expr == Variance(a) == VarianceMatrix(a) assert expr.expand() == ZeroMatrix(k, k) expr = Variance(a.T) assert expr == Variance(a.T) == VarianceMatrix(a.T) assert expr.expand() == ZeroMatrix(k, k) expr = Variance(X) assert expr == Variance(X) == VarianceMatrix(X) assert expr.shape == (k, k) assert expr.rows == k assert expr.cols == k assert isinstance(expr, VarianceMatrix) expr = Variance(A * X) assert expr == VarianceMatrix(A * X) assert expr.expand() == A * VarianceMatrix(X) * A.T assert isinstance(expr, VarianceMatrix) assert expr.shape == (k, k) expr = Variance(A * B * X) assert expr.expand() == A * B * VarianceMatrix(X) * B.T * A.T expr = Variance(m1 * X2) assert expr.expand() == expr expr = Variance(A2 * m1 * B2 * X2) assert expr.args[0].args == (A2, m1, B2, X2) assert expr.expand() == expr expr = Variance(A * X + B * Y) assert expr.expand() == 2*A*CrossCovarianceMatrix(X, Y)*B.T +\ A*VarianceMatrix(X)*A.T + B*VarianceMatrix(Y)*B.T
def test_positive_definite(): assert ask(Q.positive_definite(X), Q.positive_definite(X)) assert ask(Q.positive_definite(X.T), Q.positive_definite(X)) is True assert ask(Q.positive_definite(X.I), Q.positive_definite(X)) is True assert ask(Q.positive_definite(Y)) is False assert ask(Q.positive_definite(X)) is None assert ask(Q.positive_definite(X * Z * X), Q.positive_definite(X) & Q.positive_definite(Z)) is True assert ask(Q.positive_definite(X), Q.orthogonal(X)) assert ask(Q.positive_definite(Y.T * X * Y), Q.positive_definite(X) & Q.orthogonal(Y)) is True assert ask(Q.positive_definite(Identity(3))) is True assert ask(Q.positive_definite(ZeroMatrix(3, 3))) is False assert ask(Q.positive_definite(X + Z), Q.positive_definite(X) & Q.positive_definite(Z)) is True assert not ask(Q.positive_definite(-X), Q.positive_definite(X))
def expand(self, **hints): arg1 = self.args[0] arg2 = self.args[1] condition = self._condition if arg1 == arg2: return VarianceMatrix(arg1, condition).expand() if not is_random(arg1) or not is_random(arg2): return ZeroMatrix(*self.shape) if isinstance(arg1, RandomSymbol) and isinstance(arg2, RandomSymbol): return CrossCovarianceMatrix(arg1, arg2, condition) coeff_rv_list1 = self._expand_single_argument(arg1.expand()) coeff_rv_list2 = self._expand_single_argument(arg2.expand()) addends = [a*CrossCovarianceMatrix(r1, r2, condition=condition)*b.transpose() for (a, r1) in coeff_rv_list1 for (b, r2) in coeff_rv_list2] return Add.fromiter(addends)
def test_hadamard(): m, n, p = symbols('m, n, p', integer=True) A = MatrixSymbol('A', m, n) B = MatrixSymbol('B', m, n) C = MatrixSymbol('C', m, p) X = MatrixSymbol('X', m, m) I = Identity(m) with raises(TypeError): hadamard_product() assert hadamard_product(A) == A assert isinstance(hadamard_product(A, B), HadamardProduct) assert hadamard_product(A, B).doit() == hadamard_product(A, B) with raises(ShapeError): hadamard_product(A, C) hadamard_product(A, I) assert hadamard_product(X, I) == X assert isinstance(hadamard_product(X, I), MatrixSymbol) a = MatrixSymbol("a", k, 1) expr = MatAdd(ZeroMatrix(k, 1), OneMatrix(k, 1)) expr = HadamardProduct(expr, a) assert expr.doit() == a
def test_mixed_deriv_mixed_expressions(): expr = 3 * Trace(A) assert expr.diff(A) == 3 * Identity(k) expr = k deriv = expr.diff(A) assert isinstance(deriv, ZeroMatrix) assert deriv == ZeroMatrix(k, k) expr = Trace(A)**2 assert expr.diff(A) == (2 * Trace(A)) * Identity(k) expr = Trace(A) * A # TODO: this is not yet supported: assert expr.diff(A) == Derivative(expr, A) expr = Trace(Trace(A) * A) assert expr.diff(A) == (2 * Trace(A)) * Identity(k) expr = Trace(Trace(Trace(A) * A) * A) assert expr.diff(A) == (3 * Trace(A)**2) * Identity(k)
def _(expr: ZeroArray): if get_rank(expr) == 2: return ZeroMatrix(*expr.shape) else: return expr
from sympy import (Symbol, MatrixSymbol, ZeroMatrix, Add, Mul, MatAdd, MatMul, Determinant, Inverse, Trace, Transpose) from .symbols import d, Kron, SymmetricMatrixSymbol from .simplifications import simplify_matdiff MATRIX_DIFF_RULES = { # e =expression, s = a list of symbols respsect to which # we want to differentiate Symbol: lambda e, s: d(e) if (e in s) else 0, MatrixSymbol: lambda e, s: d(e) if (e in s) else ZeroMatrix(*e.shape), SymmetricMatrixSymbol: lambda e, s: d(e) if (e in s) else ZeroMatrix(*e.shape), Add: lambda e, s: Add(*[_matDiff_apply(arg, s) for arg in e.args]), Mul: lambda e, s: _matDiff_apply(e.args[0], s) if len(e.args)==1 else Mul(_matDiff_apply(e.args[0],s),Mul(*e.args[1:])) + Mul(e.args[0], _matDiff_apply(Mul(*e.args[1:]),s)), MatAdd: lambda e, s: MatAdd(*[_matDiff_apply(arg, s) for arg in e.args]), MatMul: lambda e, s: _matDiff_apply(e.args[0], s) if len(e.args)==1 else MatMul(_matDiff_apply(e.args[0],s),MatMul(*e.args[1:])) + MatMul(e.args[0], _matDiff_apply(MatMul(*e.args[1:]),s)), Kron: lambda e, s: _matDiff_apply(e.args[0],s) if len(e.args)==1 else Kron(_matDiff_apply(e.args[0],s),Kron(*e.args[1:])) + Kron(e.args[0],_matDiff_apply(Kron(*e.args[1:]),s)), Determinant: lambda e, s: MatMul(Determinant(e.args[0]), Trace(e.args[0].I*_matDiff_apply(e.args[0], s))), # inverse always has 1 arg, so we index Inverse: lambda e, s: -Inverse(e.args[0]) * _matDiff_apply(e.args[0], s) * Inverse(e.args[0]), # trace always has 1 arg Trace: lambda e, s: Trace(_matDiff_apply(e.args[0], s)), # transpose also always has 1 arg, index Transpose: lambda e, s: Transpose(_matDiff_apply(e.args[0], s)) } def _matDiff_apply(expr, syms): if expr.__class__ in list(MATRIX_DIFF_RULES.keys()): return MATRIX_DIFF_RULES[expr.__class__](expr, syms) elif expr.is_constant():
def _call_derive_scalar_by_matexpr(expr, v): # type: (Expr, MatrixExpr) -> Expr if expr.has(v): return _matrix_derivative(expr, v) else: return ZeroMatrix(*v.shape)