def test_DiagonalizeVector(): x = MatrixSymbol('x', n, 1) d = DiagonalizeVector(x) assert d.shape == (n, n) assert d[0, 1] == 0 assert d[0, 0] == x[0, 0] a = MatrixSymbol('a', 1, 1) d = diagonalize_vector(a) assert isinstance(d, MatrixSymbol) assert a == d assert diagonalize_vector(Identity(3)) == Identity(3) assert DiagonalizeVector(Identity(3)).doit() == Identity(3) assert isinstance(DiagonalizeVector(Identity(3)), DiagonalizeVector) # A diagonal matrix is equal to its transpose: assert DiagonalizeVector(x).T == DiagonalizeVector(x) assert diagonalize_vector(x.T) == DiagonalizeVector(x) dx = DiagonalizeVector(x) assert dx[0, 0] == x[0, 0] assert dx[1, 1] == x[1, 0] assert dx[0, 1] == 0 assert dx[0, m] == x[0, 0]*KroneckerDelta(0, m) z = MatrixSymbol('z', 1, n) dz = DiagonalizeVector(z) assert dz[0, 0] == z[0, 0] assert dz[1, 1] == z[0, 1] assert dz[0, 1] == 0 assert dz[0, m] == z[0, m]*KroneckerDelta(0, m) v = MatrixSymbol('v', 3, 1) dv = DiagonalizeVector(v) assert dv.as_explicit() == Matrix([ [v[0, 0], 0, 0], [0, v[1, 0], 0], [0, 0, v[2, 0]], ]) v = MatrixSymbol('v', 1, 3) dv = DiagonalizeVector(v) assert dv.as_explicit() == Matrix([ [v[0, 0], 0, 0], [0, v[0, 1], 0], [0, 0, v[0, 2]], ]) dv = DiagonalizeVector(3*v) assert dv.args == (3*v,) assert dv.doit() == 3*DiagonalizeVector(v) assert isinstance(dv.doit(), MatMul)
def test_DiagonalizeVector(): x = MatrixSymbol('x', n, 1) d = DiagonalizeVector(x) assert d.shape == (n, n) assert d[0, 1] == 0 assert d[0, 0] == x[0, 0] a = MatrixSymbol('a', 1, 1) d = diagonalize_vector(a) assert isinstance(d, MatrixSymbol) assert a == d assert diagonalize_vector(Identity(3)) == Identity(3) assert DiagonalizeVector(Identity(3)).doit() == Identity(3) assert isinstance(DiagonalizeVector(Identity(3)), DiagonalizeVector) # A diagonal matrix is equal to its transpose: assert DiagonalizeVector(x).T == DiagonalizeVector(x) assert diagonalize_vector(x.T) == DiagonalizeVector(x) dx = DiagonalizeVector(x) assert dx[0, 0] == x[0, 0] assert dx[1, 1] == x[1, 0] assert dx[0, 1] == 0 assert dx[0, m] == x[0, 0] * KroneckerDelta(0, m) z = MatrixSymbol('z', 1, n) dz = DiagonalizeVector(z) assert dz[0, 0] == z[0, 0] assert dz[1, 1] == z[0, 1] assert dz[0, 1] == 0 assert dz[0, m] == z[0, m] * KroneckerDelta(0, m) v = MatrixSymbol('v', 3, 1) dv = DiagonalizeVector(v) assert dv.as_explicit() == Matrix([ [v[0, 0], 0, 0], [0, v[1, 0], 0], [0, 0, v[2, 0]], ]) v = MatrixSymbol('v', 1, 3) dv = DiagonalizeVector(v) assert dv.as_explicit() == Matrix([ [v[0, 0], 0, 0], [0, v[0, 1], 0], [0, 0, v[0, 2]], ]) dv = DiagonalizeVector(3 * v) assert dv.args == (3 * v, ) assert dv.doit() == 3 * DiagonalizeVector(v) assert isinstance(dv.doit(), MatMul)
def test_DiagonalizeVector(): x = MatrixSymbol('x', n, 1) d = DiagonalizeVector(x) assert d.shape == (n, n) assert d[0, 1] == 0 assert d[0, 0] == x[0, 0] a = MatrixSymbol('a', 1, 1) d = diagonalize_vector(a) assert isinstance(d, MatrixSymbol) assert a == d
def _eval_derivative_matrix_lines(self, x): d = Dummy("d") function = self.function(d) fdiff = function.fdiff() if isinstance(fdiff, Function): fdiff = type(fdiff) else: fdiff = Lambda(d, fdiff) lr = self.expr._eval_derivative_matrix_lines(x) if 1 in self.shape: # Vector: ewdiff = ElementwiseApplyFunction(fdiff, self.expr) ewdiff = diagonalize_vector(ewdiff) # is it a vector or a matrix or a scalar? lr[0].first *= ewdiff return lr else: # Matrix case: raise NotImplementedError
def test_DiagMatrix(): x = MatrixSymbol("x", n, 1) d = DiagMatrix(x) assert d.shape == (n, n) assert d[0, 1] == 0 assert d[0, 0] == x[0, 0] a = MatrixSymbol("a", 1, 1) d = diagonalize_vector(a) assert isinstance(d, MatrixSymbol) assert a == d assert diagonalize_vector(Identity(3)) == Identity(3) assert DiagMatrix(Identity(3)).doit() == Identity(3) assert isinstance(DiagMatrix(Identity(3)), DiagMatrix) # A diagonal matrix is equal to its transpose: assert DiagMatrix(x).T == DiagMatrix(x) assert diagonalize_vector(x.T) == DiagMatrix(x) dx = DiagMatrix(x) assert dx[0, 0] == x[0, 0] assert dx[1, 1] == x[1, 0] assert dx[0, 1] == 0 assert dx[0, m] == x[0, 0] * KroneckerDelta(0, m) z = MatrixSymbol("z", 1, n) dz = DiagMatrix(z) assert dz[0, 0] == z[0, 0] assert dz[1, 1] == z[0, 1] assert dz[0, 1] == 0 assert dz[0, m] == z[0, m] * KroneckerDelta(0, m) v = MatrixSymbol("v", 3, 1) dv = DiagMatrix(v) assert dv.as_explicit() == Matrix([ [v[0, 0], 0, 0], [0, v[1, 0], 0], [0, 0, v[2, 0]], ]) v = MatrixSymbol("v", 1, 3) dv = DiagMatrix(v) assert dv.as_explicit() == Matrix([ [v[0, 0], 0, 0], [0, v[0, 1], 0], [0, 0, v[0, 2]], ]) dv = DiagMatrix(3 * v) assert dv.args == (3 * v, ) assert dv.doit() == 3 * DiagMatrix(v) assert isinstance(dv.doit(), MatMul) a = MatrixSymbol("a", 3, 1).as_explicit() expr = DiagMatrix(a) result = Matrix([ [a[0, 0], 0, 0], [0, a[1, 0], 0], [0, 0, a[2, 0]], ]) assert expr.doit() == result expr = DiagMatrix(a.T) assert expr.doit() == result
def _eval_derivative_matrix_lines(self, x): from sympy import HadamardProduct, hadamard_product, Mul, MatMul, Identity, Transpose from sympy.matrices.expressions.diagonal import diagonalize_vector from sympy.matrices.expressions.matmul import validate as matmul_validate from sympy.core.expr import ExprBuilder d = Dummy("d") function = self.function(d) fdiff = function.fdiff() if isinstance(fdiff, Function): fdiff = type(fdiff) else: fdiff = Lambda(d, fdiff) lr = self.expr._eval_derivative_matrix_lines(x) ewdiff = ElementwiseApplyFunction(fdiff, self.expr) if 1 in x.shape: # Vector: iscolumn = self.shape[1] == 1 ewdiff = diagonalize_vector(ewdiff) # TODO: check which axis is not 1 for i in lr: if iscolumn: ptr1 = [i.first_pointer] ptr2 = [Identity(ewdiff.shape[0])] else: ptr1 = [Identity(ewdiff.shape[1])] ptr2 = [i.second_pointer] # TODO: check if pointers point to two different lines: def mul(*args): return Mul.fromiter(args) def hadamard_or_mul(arg1, arg2): if arg1.shape == arg2.shape: return hadamard_product(arg1, arg2) elif arg1.shape[1] == arg2.shape[0]: return MatMul(arg1, arg2).doit() elif arg1.shape[0] == arg2.shape[0]: return MatMul(arg2.T, arg1).doit() raise NotImplementedError i._lines = [[ hadamard_or_mul, [[mul, [ewdiff, ptr1[0]]], ptr2[0]] ]] i._first_pointer_parent = i._lines[0][1][0][1] i._first_pointer_index = 1 i._second_pointer_parent = i._lines[0][1] i._second_pointer_index = 1 else: # Matrix case: for i in lr: ptr1 = [i.first_pointer] ptr2 = [i.second_pointer] newptr1 = Identity(ptr1[0].shape[1]) newptr2 = Identity(ptr2[0].shape[1]) subexpr1 = ExprBuilder( MatMul, [ptr1[0], ExprBuilder(diagonalize_vector, [newptr1])], validator=matmul_validate, ) subexpr2 = ExprBuilder( Transpose, [ ExprBuilder( MatMul, [ ptr2[0], ExprBuilder(diagonalize_vector, [newptr2]), ], ) ], validator=matmul_validate, ) i.first_pointer = subexpr1 i.second_pointer = subexpr2 i._first_pointer_parent = subexpr1.args[1].args i._first_pointer_index = 0 i._second_pointer_parent = subexpr2.args[0].args[1].args i._second_pointer_index = 0 # TODO: check if pointers point to two different lines: # Unify lines: l = i._lines # TODO: check nested fucntions, e.g. log(sin(...)), the second function should be a scalar one. i._lines = [ ExprBuilder(MatMul, [l[0], ewdiff, l[1]], validator=matmul_validate) ] return lr