switching to high quality piper tts and added label translations
This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
from sympy.core.expr import ExprBuilder
|
||||
from sympy.core.function import (Function, FunctionClass, Lambda)
|
||||
from sympy.core.symbol import Dummy
|
||||
from sympy.core.sympify import sympify, _sympify
|
||||
from sympy.matrices.expressions import MatrixExpr
|
||||
from sympy.matrices.matrixbase import MatrixBase
|
||||
|
||||
|
||||
class ElementwiseApplyFunction(MatrixExpr):
|
||||
r"""
|
||||
Apply function to a matrix elementwise without evaluating.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
It can be created by calling ``.applyfunc(<function>)`` on a matrix
|
||||
expression:
|
||||
|
||||
>>> from sympy import MatrixSymbol
|
||||
>>> from sympy.matrices.expressions.applyfunc import ElementwiseApplyFunction
|
||||
>>> from sympy import exp
|
||||
>>> X = MatrixSymbol("X", 3, 3)
|
||||
>>> X.applyfunc(exp)
|
||||
Lambda(_d, exp(_d)).(X)
|
||||
|
||||
Otherwise using the class constructor:
|
||||
|
||||
>>> from sympy import eye
|
||||
>>> expr = ElementwiseApplyFunction(exp, eye(3))
|
||||
>>> expr
|
||||
Lambda(_d, exp(_d)).(Matrix([
|
||||
[1, 0, 0],
|
||||
[0, 1, 0],
|
||||
[0, 0, 1]]))
|
||||
>>> expr.doit()
|
||||
Matrix([
|
||||
[E, 1, 1],
|
||||
[1, E, 1],
|
||||
[1, 1, E]])
|
||||
|
||||
Notice the difference with the real mathematical functions:
|
||||
|
||||
>>> exp(eye(3))
|
||||
Matrix([
|
||||
[E, 0, 0],
|
||||
[0, E, 0],
|
||||
[0, 0, E]])
|
||||
"""
|
||||
|
||||
def __new__(cls, function, expr):
|
||||
expr = _sympify(expr)
|
||||
if not expr.is_Matrix:
|
||||
raise ValueError("{} must be a matrix instance.".format(expr))
|
||||
|
||||
if expr.shape == (1, 1):
|
||||
# Check if the function returns a matrix, in that case, just apply
|
||||
# the function instead of creating an ElementwiseApplyFunc object:
|
||||
ret = function(expr)
|
||||
if isinstance(ret, MatrixExpr):
|
||||
return ret
|
||||
|
||||
if not isinstance(function, (FunctionClass, Lambda)):
|
||||
d = Dummy('d')
|
||||
function = Lambda(d, function(d))
|
||||
|
||||
function = sympify(function)
|
||||
if not isinstance(function, (FunctionClass, Lambda)):
|
||||
raise ValueError(
|
||||
"{} should be compatible with SymPy function classes."
|
||||
.format(function))
|
||||
|
||||
if 1 not in function.nargs:
|
||||
raise ValueError(
|
||||
'{} should be able to accept 1 arguments.'.format(function))
|
||||
|
||||
if not isinstance(function, Lambda):
|
||||
d = Dummy('d')
|
||||
function = Lambda(d, function(d))
|
||||
|
||||
obj = MatrixExpr.__new__(cls, function, expr)
|
||||
return obj
|
||||
|
||||
@property
|
||||
def function(self):
|
||||
return self.args[0]
|
||||
|
||||
@property
|
||||
def expr(self):
|
||||
return self.args[1]
|
||||
|
||||
@property
|
||||
def shape(self):
|
||||
return self.expr.shape
|
||||
|
||||
def doit(self, **hints):
|
||||
deep = hints.get("deep", True)
|
||||
expr = self.expr
|
||||
if deep:
|
||||
expr = expr.doit(**hints)
|
||||
function = self.function
|
||||
if isinstance(function, Lambda) and function.is_identity:
|
||||
# This is a Lambda containing the identity function.
|
||||
return expr
|
||||
if isinstance(expr, MatrixBase):
|
||||
return expr.applyfunc(self.function)
|
||||
elif isinstance(expr, ElementwiseApplyFunction):
|
||||
return ElementwiseApplyFunction(
|
||||
lambda x: self.function(expr.function(x)),
|
||||
expr.expr
|
||||
).doit(**hints)
|
||||
else:
|
||||
return self
|
||||
|
||||
def _entry(self, i, j, **kwargs):
|
||||
return self.function(self.expr._entry(i, j, **kwargs))
|
||||
|
||||
def _get_function_fdiff(self):
|
||||
d = Dummy("d")
|
||||
function = self.function(d)
|
||||
fdiff = function.diff(d)
|
||||
if isinstance(fdiff, Function):
|
||||
fdiff = type(fdiff)
|
||||
else:
|
||||
fdiff = Lambda(d, fdiff)
|
||||
return fdiff
|
||||
|
||||
def _eval_derivative(self, x):
|
||||
from sympy.matrices.expressions.hadamard import hadamard_product
|
||||
dexpr = self.expr.diff(x)
|
||||
fdiff = self._get_function_fdiff()
|
||||
return hadamard_product(
|
||||
dexpr,
|
||||
ElementwiseApplyFunction(fdiff, self.expr)
|
||||
)
|
||||
|
||||
def _eval_derivative_matrix_lines(self, x):
|
||||
from sympy.matrices.expressions.special 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
|
||||
|
||||
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_transpose(self):
|
||||
from sympy.matrices.expressions.transpose import Transpose
|
||||
return self.func(self.function, Transpose(self.expr).doit())
|
||||
Reference in New Issue
Block a user