def _eval_derivative_matrix_lines(self, x): from sympy.tensor.array.expressions.array_expressions import ArrayTensorProduct from sympy.tensor.array.expressions.array_expressions import ArrayDiagonal from sympy.matrices.expressions.matexpr import _make_matrix lr = self.base._eval_derivative_matrix_lines(x) for i in lr: diagonal = [(1, 2), (3, 4)] diagonal = [e for j, e in enumerate(diagonal) if self.base.shape[j] != 1] l1 = i._lines[i._first_line_index] l2 = i._lines[i._second_line_index] subexpr = ExprBuilder( ArrayDiagonal, [ ExprBuilder( ArrayTensorProduct, [ ExprBuilder(_make_matrix, [l1]), self.exp*hadamard_power(self.base, self.exp-1), ExprBuilder(_make_matrix, [l2]), ] ), *diagonal], validator=ArrayDiagonal._validate ) i._first_pointer_parent = subexpr.args[0].args[0].args i._first_pointer_index = 0 i._first_line_index = 0 i._second_pointer_parent = subexpr.args[0].args[2].args i._second_pointer_index = 0 i._second_line_index = 0 i._lines = [subexpr] return lr
def _eval_derivative_matrix_lines(self, x): from sympy.codegen.array_utils import CodegenArrayTensorProduct from sympy.codegen.array_utils import CodegenArrayContraction, CodegenArrayDiagonal from sympy.core.expr import ExprBuilder from sympy.matrices.expressions.matexpr import _make_matrix lr = self.base._eval_derivative_matrix_lines(x) for i in lr: diagonal = [(1, 2), (3, 4)] diagonal = [e for j, e in enumerate(diagonal) if self.base.shape[j] != 1] l1 = i._lines[i._first_line_index] l2 = i._lines[i._second_line_index] subexpr = ExprBuilder( CodegenArrayDiagonal, [ ExprBuilder( CodegenArrayTensorProduct, [ ExprBuilder(_make_matrix, [l1]), self.exp*hadamard_power(self.base, self.exp-1), ExprBuilder(_make_matrix, [l2]), ] ), ] + diagonal, # turn into *diagonal after dropping Python 2.7 validator=CodegenArrayDiagonal._validate ) i._first_pointer_parent = subexpr.args[0].args[0].args i._first_pointer_index = 0 i._first_line_index = 0 i._second_pointer_parent = subexpr.args[0].args[2].args i._second_pointer_index = 0 i._second_line_index = 0 i._lines = [subexpr] return lr
def _eval_derivative_matrix_lines(self, x): from sympy.codegen.array_utils import CodegenArrayContraction, CodegenArrayTensorProduct from sympy.core.expr import ExprBuilder r = self.args[0]._eval_derivative_matrix_lines(x) for lr in r: if lr.higher == 1: lr.higher = ExprBuilder( CodegenArrayContraction, [ ExprBuilder(CodegenArrayTensorProduct, [ lr._lines[0], lr._lines[1], ]), (1, 3), ], validator=CodegenArrayContraction._validate) else: # This is not a matrix line: lr.higher = ExprBuilder(CodegenArrayContraction, [ ExprBuilder(CodegenArrayTensorProduct, [ lr._lines[0], lr._lines[1], lr.higher, ]), (1, 3), (0, 2) ]) lr._lines = [S.One, S.One] lr._first_pointer_parent = lr._lines lr._second_pointer_parent = lr._lines lr._first_pointer_index = 0 lr._second_pointer_index = 1 return r
def _eval_derivative_matrix_lines(self, x): from sympy import Identity from sympy.codegen.array_utils import CodegenArrayContraction, CodegenArrayTensorProduct, CodegenArrayDiagonal from sympy.core.expr import ExprBuilder d = Dummy("d") function = self.function(d) fdiff = function.diff(d) 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 for i in lr: if iscolumn: ptr1 = i.first_pointer ptr2 = Identity(self.shape[1]) else: ptr1 = Identity(self.shape[0]) ptr2 = i.second_pointer subexpr = ExprBuilder(CodegenArrayDiagonal, [ ExprBuilder(CodegenArrayTensorProduct, [ ewdiff, ptr1, ptr2, ]), (0, 2) if iscolumn else (1, 4) ], validator=CodegenArrayDiagonal._validate) i._lines = [subexpr] i._first_pointer_parent = subexpr.args[0].args i._first_pointer_index = 1 i._second_pointer_parent = subexpr.args[0].args i._second_pointer_index = 2 else: # Matrix case: for i in lr: ptr1 = i.first_pointer ptr2 = i.second_pointer newptr1 = Identity(ptr1.shape[1]) newptr2 = Identity(ptr2.shape[1]) subexpr = ExprBuilder( CodegenArrayContraction, [ ExprBuilder(CodegenArrayTensorProduct, [ptr1, newptr1, ewdiff, ptr2, newptr2]), (1, 2, 4), (5, 7, 8), ], validator=CodegenArrayContraction._validate) i._first_pointer_parent = subexpr.args[0].args i._first_pointer_index = 1 i._second_pointer_parent = subexpr.args[0].args i._second_pointer_index = 4 i._lines = [subexpr] return lr
def _multiply_pointer(self, pointer, other): from sympy.core.expr import ExprBuilder from sympy.codegen.array_utils import CodegenArrayContraction, CodegenArrayTensorProduct subexpr = ExprBuilder( CodegenArrayContraction, [ExprBuilder(CodegenArrayTensorProduct, [pointer, other]), (1, 2)], validator=CodegenArrayContraction._validate) return subexpr
def _multiply_pointer(self, pointer, other): from ...tensor.array.expressions.array_expressions import ArrayTensorProduct from ...tensor.array.expressions.array_expressions import ArrayContraction subexpr = ExprBuilder( ArrayContraction, [ExprBuilder(ArrayTensorProduct, [pointer, other]), (1, 2)], validator=ArrayContraction._validate) return subexpr
def _eval_derivative_matrix_lines(self, x): from sympy import Identity from sympy.tensor.array.expressions.array_expressions import ArrayContraction from sympy.tensor.array.expressions.array_expressions import ArrayDiagonal from sympy.tensor.array.expressions.array_expressions import ArrayTensorProduct from sympy.core.expr import ExprBuilder fdiff = self._get_function_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 for i in lr: if iscolumn: ptr1 = i.first_pointer ptr2 = Identity(self.shape[1]) else: ptr1 = Identity(self.shape[0]) ptr2 = i.second_pointer subexpr = ExprBuilder(ArrayDiagonal, [ ExprBuilder(ArrayTensorProduct, [ ewdiff, ptr1, ptr2, ]), (0, 2) if iscolumn else (1, 4) ], validator=ArrayDiagonal._validate) i._lines = [subexpr] i._first_pointer_parent = subexpr.args[0].args i._first_pointer_index = 1 i._second_pointer_parent = subexpr.args[0].args i._second_pointer_index = 2 else: # Matrix case: for i in lr: ptr1 = i.first_pointer ptr2 = i.second_pointer newptr1 = Identity(ptr1.shape[1]) newptr2 = Identity(ptr2.shape[1]) subexpr = ExprBuilder(ArrayContraction, [ ExprBuilder(ArrayTensorProduct, [ptr1, newptr1, ewdiff, ptr2, newptr2]), (1, 2, 4), (5, 7, 8), ], validator=ArrayContraction._validate) i._first_pointer_parent = subexpr.args[0].args i._first_pointer_index = 1 i._second_pointer_parent = subexpr.args[0].args i._second_pointer_index = 4 i._lines = [subexpr] return lr
def _eval_derivative_matrix_lines(self, x): from sympy.core.expr import ExprBuilder from sympy.codegen.array_utils import ( CodegenArrayContraction, CodegenArrayTensorProduct, ) from .matmul import MatMul from .inverse import Inverse exp = self.exp if self.base.shape == (1, 1) and not exp.has(x): lr = self.base._eval_derivative_matrix_lines(x) for i in lr: subexpr = ExprBuilder( CodegenArrayContraction, [ ExprBuilder( CodegenArrayTensorProduct, [ Identity(1), i._lines[0], exp * self.base**(exp - 1), i._lines[1], Identity(1), ], ), (0, 3, 4), (5, 7, 8), ], validator=CodegenArrayContraction._validate, ) i._first_pointer_parent = subexpr.args[0].args i._first_pointer_index = 0 i._second_pointer_parent = subexpr.args[0].args i._second_pointer_index = 4 i._lines = [subexpr] return lr if (exp > 0) == True: newexpr = MatMul.fromiter([self.base for i in range(exp)]) elif (exp == -1) == True: return Inverse(self.base)._eval_derivative_matrix_lines(x) elif (exp < 0) == True: newexpr = MatMul.fromiter( [Inverse(self.base) for i in range(-exp)]) elif (exp == 0) == True: return self.doit()._eval_derivative_matrix_lines(x) else: raise NotImplementedError("cannot evaluate %s derived by %s" % (self, x)) return newexpr._eval_derivative_matrix_lines(x)
def _eval_derivative_matrix_lines(self, x): from sympy.core.expr import ExprBuilder from sympy.codegen.array_utils import ( CodegenArrayDiagonal, CodegenArrayTensorProduct, ) from sympy.matrices.expressions.matexpr import _make_matrix with_x_ind = [i for i, arg in enumerate(self.args) if arg.has(x)] lines = [] for ind in with_x_ind: left_args = self.args[:ind] right_args = self.args[ind + 1 :] d = self.args[ind]._eval_derivative_matrix_lines(x) hadam = hadamard_product(*(right_args + left_args)) diagonal = [(0, 2), (3, 4)] diagonal = [e for j, e in enumerate(diagonal) if self.shape[j] != 1] for i in d: l1 = i._lines[i._first_line_index] l2 = i._lines[i._second_line_index] subexpr = ExprBuilder( CodegenArrayDiagonal, [ ExprBuilder( CodegenArrayTensorProduct, [ ExprBuilder(_make_matrix, [l1]), hadam, ExprBuilder(_make_matrix, [l2]), ], ), *diagonal, ], ) i._first_pointer_parent = subexpr.args[0].args[0].args i._first_pointer_index = 0 i._second_pointer_parent = subexpr.args[0].args[2].args i._second_pointer_index = 0 i._lines = [subexpr] lines.append(i) return lines
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