Additionally to Stefan's answer about sympy core , I introduce the
example how it may be implemented concretely.
There is the tested code in the atachment of it.
(I can create PR, but I don't know where will it be better to put in the
sympy modules)
And there is the '__call__' magic-method used instead of the implicit
multiplication as aplly-like method.
>>> Dx = DiffOperator(x)
>>> myD = (a*Dx + Dx**3) # construct diff operator
>>> myD(x**4) # apply this operator.
4*a*x**3 + 24*x
For matrices it is some more complicated
>>> I = Matrix([[0, -1], [1, 0]])
>>> myD = I*Dx # construct diff
>>> myD(x**2) # apply
Derivative([x**2, 0]
[ 0, x**2], x)
Here I don't know how Derivative can be automatically applied for the
Matrix expression.
--
Alexey Gudchenko
On 26.01.2013 02:49, ruoyu zhang wrote:
>>>> p = DifferentialOperator(t)
>>>> a * p * f(t)
> Derivative(f(t), t)*a
>
> p is a DifferentialOperator, when it multiply with some expression at
> right side, it calculates the derivative of the expression.
>
--
You received this message because you are subscribed to the Google Groups
"sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sympy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
"""
The module implemented diff operator.
"""
from sympy import Expr, Symbol, Eq, Mul, Add, Pow, expand, sympify, Tuple
from sympy.core.basic import Basic
from sympy.core.operations import AssocOp
from sympy.core.singleton import (Singleton, S)
from sympy.core.decorators import _sympifyit, call_highest_priority
from sympy.core.cache import cacheit
from sympy.core.function import diff
from sympy.series.order import Order
class DiffOperatorExpr(Expr):
_op_priority = 12.0
is_DiffOperator = True
is_Identity = False
# The following is adapted from the core Expr object
def __neg__(self):
return DOMul(S.NegativeOne, self)
def __abs__(self):
raise NotImplementedError
@_sympifyit('other', NotImplemented)
@call_highest_priority('__radd__')
def __add__(self, other):
return DOAdd(self, other)
@_sympifyit('other', NotImplemented)
@call_highest_priority('__add__')
def __radd__(self, other):
return DOAdd(other, self)
@_sympifyit('other', NotImplemented)
@call_highest_priority('__rsub__')
def __sub__(self, other):
return DOAdd(self, -other)
@_sympifyit('other', NotImplemented)
@call_highest_priority('__sub__')
def __rsub__(self, other):
return DOAdd(other, -self)
@_sympifyit('other', NotImplemented)
@call_highest_priority('__rmul__')
def __mul__(self, other):
return DOMul(self, other)
@_sympifyit('other', NotImplemented)
@call_highest_priority('__mul__')
def __rmul__(self, other):
return DOMul(other, self)
@_sympifyit('other', NotImplemented)
@call_highest_priority('__rpow__')
def __pow__(self, other):
return DOPow(self, other)
@_sympifyit('other', NotImplemented)
@call_highest_priority('__pow__')
def __rpow__(self, other):
raise NotImplementedError("DiffOperator Power is not defined")
@_sympifyit('other', NotImplemented)
@call_highest_priority('__rdiv__')
def __div__(self, other):
return DOMul(self, other**S.NegativeOne)
@_sympifyit('other', NotImplemented)
@call_highest_priority('__div__')
def __rdiv__(self, other):
return DOMul(other, self**S.NegativeOne)
class DiffOperatorOne(DiffOperatorExpr):
"""
Represents the identic operator ( DiffOperator**0).
"""
__metaclass__ = Singleton
is_Identity = True
class DiffOperator(DiffOperatorExpr):
"""
>>> from sympy.abc import x, a
>>> from sympy.core.function import Function
>>> from sympy.tensor.diff_operator import DiffOperator
>>> f = Function("f")
>>> Dx = DiffOperator(x)
>>> Dx + Dx
DiffOperator(x) + DiffOperator(x)
>>> Dx(f(x))
Derivative(f(x), x)
>>> Dx + Dx**2
DiffOperator(x) + DiffOperator(x)**2
>>> (Dx + Dx**2)(f(x))
Derivative(f(x), x) + Derivative(f(x), x, x)
>>> (a*Dx + Dx**3)(x**4)
4*a*x**3 + 24*x
"""
def __new__(cls, variable):
obj = DiffOperatorExpr.__new__(cls, variable)
return obj
@property
def variable(self):
return self._args[0]
def _hashable_content(self):
return tuple(sorted(self._args, key=hash))
def __call__(self, e):
return diff(e, self.variable)
def _eval_nseries(self, x, n, logx):
return self + Order(n)
def _latex(self, p):
return "\partial_{%s}" % (p._print(self.variable))
def _needs_brackets(self):
return False
class DOAdd(DiffOperatorExpr, Add):
"""
A Sum of the DiffOperator expressions.
"""
def __new__(cls, *args):
expr = Add.__new__(cls, *args)
if expr.is_Mul:
return DOMul(*expr.args)
return expr
def __call__(self, e):
return Add(*tuple(d(e) for d in self.args))
@classmethod
def flatten(cls, args):
new_seq = []
i = 0
while args:
o = args.pop()
if o.__class__ is cls:
args.extend(o.args)
else:
new_seq.append(o)
new_seq.reverse()
return new_seq, [], None
class DOMul(DiffOperatorExpr, Mul):
def __new__(cls, *args):
if any(arg.is_zero for arg in args):
return S.Zero
expr = Mul.__new__(cls, *args)
return expr
# is it needed?
@classmethod
def flatten(cls, args_seq):
return args_seq, [], None
def as_ordered_terms(self, order=None):
return self.args
@property
def variable(self):
for d in self.args:
if isinstance(d, DiffOperatorExpr):
return d.variable
def __call__(self, e):
for d in self.args:
if isinstance(d, DiffOperatorExpr):
e = d(e)
else:
e = e*d
return e
class DOPow(DiffOperatorExpr, Pow):
def __new__(cls, *args):
expr = Pow.__new__(cls, *args, evaluate=False)
return expr
def __call__(self, e):
base = self.base
if isinstance(base, DOMul):
parts = (arg for arg in base.args)
res = S.One
for part in parts:
if isinstance(part, DiffOperatorExpr):
res *= (part**self.exp)(e)
else:
res *= (part**self.exp)
return res
else:
return diff(e, self.base.variable, self.exp)
def _latex(self, p):
return "%s^{%s}" % (self.base._latex(p), self.exp)