def _array_diag2contr_diagmatrix(expr: ArrayDiagonal): if isinstance(expr.expr, ArrayTensorProduct): args = list(expr.expr.args) diag_indices = list(expr.diagonal_indices) mapping = _get_mapping_from_subranks( [_get_subrank(arg) for arg in args]) tuple_links = [[mapping[j] for j in i] for i in diag_indices] contr_indices = [] total_rank = get_rank(expr) replaced = [False for arg in args] for i, (abs_pos, rel_pos) in enumerate(zip(diag_indices, tuple_links)): if len(abs_pos) != 2: continue (pos1_outer, pos1_inner), (pos2_outer, pos2_inner) = rel_pos arg1 = args[pos1_outer] arg2 = args[pos2_outer] if get_rank(arg1) != 2 or get_rank(arg2) != 2: if replaced[pos1_outer]: diag_indices[i] = None if replaced[pos2_outer]: diag_indices[i] = None continue pos1_in2 = 1 - pos1_inner pos2_in2 = 1 - pos2_inner if arg1.shape[pos1_in2] == 1: if arg1.shape[pos1_inner] != 1: darg1 = DiagMatrix(arg1) else: darg1 = arg1 args.append(darg1) contr_indices.append( ((pos2_outer, pos2_inner), (len(args) - 1, pos1_inner))) total_rank += 1 diag_indices[i] = None args[pos1_outer] = OneArray(arg1.shape[pos1_in2]) replaced[pos1_outer] = True elif arg2.shape[pos2_in2] == 1: if arg2.shape[pos2_inner] != 1: darg2 = DiagMatrix(arg2) else: darg2 = arg2 args.append(darg2) contr_indices.append( ((pos1_outer, pos1_inner), (len(args) - 1, pos2_inner))) total_rank += 1 diag_indices[i] = None args[pos2_outer] = OneArray(arg2.shape[pos2_in2]) replaced[pos2_outer] = True diag_indices_new = [i for i in diag_indices if i is not None] cumul = list(accumulate([0] + [get_rank(arg) for arg in args])) contr_indices2 = [ tuple(cumul[a] + b for a, b in i) for i in contr_indices ] tc = ArrayContraction(ArrayTensorProduct(*args), *contr_indices2) td = ArrayDiagonal(tc, *diag_indices_new) return td return expr
def test_derivatives_elementwise_applyfunc(): from sympy.matrices.expressions.diagonal import DiagMatrix expr = x.applyfunc(tan) assert expr.diff(x).dummy_eq( DiagMatrix(x.applyfunc(lambda x: tan(x)**2 + 1))) assert expr[i, 0].diff(x[m, 0]).doit() == (tan(x[i, 0])**2 + 1)*KDelta(i, m) _check_derivative_with_explicit_matrix(expr, x, expr.diff(x)) expr = (i**2*x).applyfunc(sin) assert expr.diff(i).dummy_eq( HadamardProduct((2*i)*x, (i**2*x).applyfunc(cos))) assert expr[i, 0].diff(i).doit() == 2*i*x[i, 0]*cos(i**2*x[i, 0]) _check_derivative_with_explicit_matrix(expr, i, expr.diff(i)) expr = (log(i)*A*B).applyfunc(sin) assert expr.diff(i).dummy_eq( HadamardProduct(A*B/i, (log(i)*A*B).applyfunc(cos))) _check_derivative_with_explicit_matrix(expr, i, expr.diff(i)) expr = A*x.applyfunc(exp) assert expr.diff(x).dummy_eq(DiagMatrix(x.applyfunc(exp))*A.T) _check_derivative_with_explicit_matrix(expr, x, expr.diff(x)) expr = x.T*A*x + k*y.applyfunc(sin).T*x assert expr.diff(x).dummy_eq(A.T*x + A*x + k*y.applyfunc(sin)) _check_derivative_with_explicit_matrix(expr, x, expr.diff(x)) expr = x.applyfunc(sin).T*y assert expr.diff(x).dummy_eq(DiagMatrix(x.applyfunc(cos))*y) _check_derivative_with_explicit_matrix(expr, x, expr.diff(x)) expr = (a.T * X * b).applyfunc(sin) assert expr.diff(X).dummy_eq(a*(a.T*X*b).applyfunc(cos)*b.T) _check_derivative_with_explicit_matrix(expr, X, expr.diff(X)) expr = a.T * X.applyfunc(sin) * b assert expr.diff(X).dummy_eq( DiagMatrix(a)*X.applyfunc(cos)*DiagMatrix(b)) _check_derivative_with_explicit_matrix(expr, X, expr.diff(X)) expr = a.T * (A*X*B).applyfunc(sin) * b assert expr.diff(X).dummy_eq( A.T*DiagMatrix(a)*(A*X*B).applyfunc(cos)*DiagMatrix(b)*B.T) _check_derivative_with_explicit_matrix(expr, X, expr.diff(X)) expr = a.T * (A*X*b).applyfunc(sin) * b.T # TODO: not implemented #assert expr.diff(X) == ... #_check_derivative_with_explicit_matrix(expr, X, expr.diff(X)) expr = a.T*A*X.applyfunc(sin)*B*b assert expr.diff(X).dummy_eq( DiagMatrix(A.T*a)*X.applyfunc(cos)*DiagMatrix(B*b)) expr = a.T * (A*X.applyfunc(sin)*B).applyfunc(log) * b # TODO: wrong # assert expr.diff(X) == A.T*DiagMatrix(a)*(A*X.applyfunc(sin)*B).applyfunc(Lambda(k, 1/k))*DiagMatrix(b)*B.T expr = a.T * (X.applyfunc(sin)).applyfunc(log) * b
def test_arrayexpr_split_multiple_contractions(): a = MatrixSymbol("a", k, 1) b = MatrixSymbol("b", k, 1) A = MatrixSymbol("A", k, k) B = MatrixSymbol("B", k, k) C = MatrixSymbol("C", k, k) X = MatrixSymbol("X", k, k) cg = ArrayContraction( ArrayTensorProduct(A.T, a, b, b.T, (A * X * b).applyfunc(cos)), (1, 2, 8), (5, 6, 9)) assert cg.split_multiple_contractions().dummy_eq( ArrayContraction( ArrayTensorProduct(DiagMatrix(a), (A * X * b).applyfunc(cos), A.T, b, b.T), (0, 2), (1, 5), (3, 7, 8))) # assert recognize_matrix_expression(cg) # Check no overlap of lines: cg = ArrayContraction(ArrayTensorProduct(A, a, C, a, B), (1, 2, 4), (5, 6, 8), (3, 7)) assert cg.split_multiple_contractions() == cg cg = ArrayContraction(ArrayTensorProduct(a, b, A), (0, 2, 4), (1, 3)) assert cg.split_multiple_contractions() == cg
def test_derivatives_of_hadamard_expressions(): # Hadamard Product expr = hadamard_product(a, x, b) assert expr.diff(x) == DiagMatrix(hadamard_product(b, a)) expr = a.T*hadamard_product(A, X, B)*b assert expr.diff(X) == DiagMatrix(a)*hadamard_product(B, A)*DiagMatrix(b) # Hadamard Power expr = hadamard_power(x, 2) assert expr.diff(x).doit() == 2*DiagMatrix(x) expr = hadamard_power(x.T, 2) assert expr.diff(x).doit() == 2*DiagMatrix(x) expr = hadamard_power(x, S.Half) assert expr.diff(x) == S.Half*DiagMatrix(hadamard_power(x, Rational(-1, 2))) expr = hadamard_power(a.T*X*b, 2) assert expr.diff(X) == 2*a*a.T*X*b*b.T expr = hadamard_power(a.T*X*b, S.Half) assert expr.diff(X) == a/2*hadamard_power(a.T*X*b, Rational(-1, 2))*b.T
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_arrayexpr_split_multiple_contractions(): a = MatrixSymbol("a", k, 1) b = MatrixSymbol("b", k, 1) A = MatrixSymbol("A", k, k) B = MatrixSymbol("B", k, k) C = MatrixSymbol("C", k, k) X = MatrixSymbol("X", k, k) cg = ArrayContraction(ArrayTensorProduct(A.T, a, b, b.T, (A*X*b).applyfunc(cos)), (1, 2, 8), (5, 6, 9)) expected = ArrayContraction(ArrayTensorProduct(A.T, DiagMatrix(a), OneArray(1), b, b.T, (A*X*b).applyfunc(cos)), (1, 3), (2, 9), (6, 7, 10)) assert cg.split_multiple_contractions().dummy_eq(expected) # Check no overlap of lines: cg = ArrayContraction(ArrayTensorProduct(A, a, C, a, B), (1, 2, 4), (5, 6, 8), (3, 7)) assert cg.split_multiple_contractions() == cg cg = ArrayContraction(ArrayTensorProduct(a, b, A), (0, 2, 4), (1, 3)) assert cg.split_multiple_contractions() == cg
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)) assert ask(Q.diagonal(C0x0)) assert ask(Q.diagonal(A1x1)) assert ask(Q.diagonal(A1x1 + B1x1)) assert ask(Q.diagonal(A1x1*B1x1)) assert ask(Q.diagonal(V1.T*V2)) assert ask(Q.diagonal(V1.T*(X + Z)*V1)) assert ask(Q.diagonal(MatrixSlice(Y, (0, 1), (1, 2)))) is True assert ask(Q.diagonal(V1.T*(V1 + V2))) is True assert ask(Q.diagonal(X**3), Q.diagonal(X)) assert ask(Q.diagonal(Identity(3))) assert ask(Q.diagonal(DiagMatrix(V1))) assert ask(Q.diagonal(DiagonalMatrix(X)))