Exemple #1
0
def rules_derivative(obj, v):
    if isinstance(obj.arg, Indexed):
        if isinstance(obj.wrt, Indexed):
            if obj.arg.base == obj.wrt.base:
                if v:
                    print('kroneckerDelta', obj.arg.indices, obj.wrt.indices)
                return Mul( *[ KroneckerDelta(ind0, ind1) for ind0, ind1 in zip(obj.arg.indices, obj.wrt.indices)] )

    if isinstance(obj.arg, AppliedIndexedFunction):
        if isinstance(obj.wrt, AppliedIndexedFunction):
            if obj.arg.base == obj.wrt.base:
                if v:
                    print('kroneckerDelta+dirac', obj.arg.indices, obj.wrt.indices)
                return Mul( *[ KroneckerDelta(ind0, ind1) for ind0, ind1 in zip(obj.arg.indices, obj.wrt.indices)], *[ DiracDelta(arg0 - arg1) for arg0, arg1 in zip(obj.arg.args, obj.wrt.args)] )
    
#     if isinstance(obj.arg, Neg):
#         if v: print('neg deriv')
#         return Neg( Derivative(obj.arg.arg, obj.wrt) )
#     if isinstance(obj.arg, Summation):
#         if v: print('sum deriv')
#         return Summation( Derivative(obj.arg.arg, obj.wrt), *obj.arg.lims )
#     if isinstance(obj.arg, Add):
#         if v: print('add deriv')
#         return Add( *[Derivative(arg, obj.wrt) for arg in obj.arg.args] )
    if isinstance(obj.arg, Mul):
        if v: print('mul deriv')        
        return Add( *[ 
            Mul(*[ 
                jarg if i!=j else Derivative(jarg, obj.wrt) for j, jarg in enumerate(obj.arg.args) 
            ] )
            for i, iarg in enumerate(obj.arg.args)
        ] )
    if isinstance(obj.arg, Pow):
        if v: print('pow deriv')
        return obj.arg.power * obj.arg.base**(obj.arg.power-1) * Derivative(obj.arg.base, obj.wrt)

    if isinstance(obj.arg, AppliedFunction):
        if v: print('func deriv')
        if isinstance(obj.wrt, AppliedFunction):
            if v: print('func deriv')
            if obj.arg.operator == obj.wrt.operator:
                if v: print('diracDelta deriv')
                return Mul( *[ DiracDelta( arg0 - arg1 ) for arg0, arg1 in zip(obj.arg.args, obj.wrt.args) ])
        return Add(*[ PartialDerivative(obj.arg.operator, i)(*obj.arg.args) * Derivative(arg, obj.wrt) for i, arg in enumerate(obj.arg.args) ])
    
    if v: print('nothing deriv')
    return obj
Exemple #2
0
class Derivative(Expr):
    @staticmethod
    def add_order():
        return Mul.add_order()-1
    @staticmethod
    def mul_order():
        return AppliedFunction.mul_order()+1
    
    rules = RuleList(
        Rule(
            'd(-...) -> -d(...)',
            lambda obj: isinstance(obj.arg, Neg),
            lambda obj, v: Neg( Derivative(obj.arg.arg, obj.wrt) )
        ),
        Rule(
            'd(sum(...)) -> sum(d(...))',
            lambda obj: isinstance(obj.arg, Summation),
            lambda obj, v: Summation( Derivative(obj.arg.arg, obj.wrt), *obj.arg.lims )
        ),
        Rule(
            'd(add(...)) -> add(d(...))',
            lambda obj: isinstance(obj.arg, Add),
            lambda obj, v: Add( *[Derivative(arg, obj.wrt) for arg in obj.arg.args] )
        ),
        Rule(
            'derivative rule',
            lambda obj: True,
            lambda obj, v: rules_derivative(obj, v)
        )
    )
    
    def __new__(cls, *args, **kwargs):
        arg, wrt, = args
        if isinstance(wrt, Number):
            raise Exception('trying to derivate with respect to a number')
        if isinstance(arg, Number):
            return Number(0)
        if arg == wrt:
            return Number(1)
        obj = super().__new__(cls, *args)
        if not hasattr(obj, 'wrt'):
            obj.arg = arg
            obj.wrt = wrt
        return obj

    def __init__(self, *args, **kwargs):
        pass
    
    def __str__(self):
        wrt = self.wrt
        if not isinstance(wrt, Symbol):
            wrt = delim(wrt)
        if isinstance(self.arg, Expr):
            return fr'\frac{{ {{\rm d}} }}{{ {{\rm d}}{self.wrt} }}{delim(self.arg)}'
        return fr'\frac{{ {{\rm d}}{self.arg} }}{{ {{\rm d}}{self.wrt} }}'
Exemple #3
0
def rules_summation(obj, v):
    if isinstance(obj.arg, Add):
        if v: print('add summation')
        inside_args = [
            arg for arg in obj.arg.args if hasindex(arg, obj.lims[0])
        ]
        outside_args = [arg for arg in obj.arg.args if not arg in inside_args]
        if len(inside_args) == 0:
            inside_args = [Number(1)]
        return Add(
            *[arg * Summation(Number(1), *obj.lims) for arg in outside_args],
            *[Summation(arg, *obj.lims) for arg in inside_args])

    if isinstance(obj.arg, Neg):
        if v: print('neg summation')
        return Neg(Summation(obj.arg.arg, *obj.lims))

    if isinstance(obj.arg, Mul):
        if v: print('mul summation')
        inside_args = [
            arg for arg in obj.arg.args if hasindex(arg, obj.lims[0])
        ]
        outside_args = [arg for arg in obj.arg.args if not arg in inside_args]
        if len(inside_args) == 0:
            inside_args = [Number(1)]
        if KroneckerDelta in list(map(lambda x: x.__class__, inside_args)):
            new_ind = [
                ind for delta in inside_args
                if isinstance(delta, KroneckerDelta) for ind in delta.indices
                if not ind == obj.lims[0]
            ][0]
            return Mul(
                *outside_args, *[
                    update_indices(arg, obj.lims[0], new_ind, v)
                    for arg in inside_args
                    if not isinstance(arg, KroneckerDelta)
                ])
        return Mul(*outside_args,
                   Summation(Mul(*[arg for arg in inside_args]), *obj.lims))

    if not hasindex(obj.arg, obj.lims[0]):
        if v: print('no index summation')
        return obj.arg * (obj.lims[2] - obj.lims[1])

    if v: print('nothing summation')
    return obj
Exemple #4
0
def rules_mul(obj, verbose=False):
    args = flatten_args(obj)    
    terms = Counter()
    numeric = 1
    for arg in args:
        if isinstance(arg, Add):
            return Add(*[ Mul(add_arg, *[ other for other in args if not other == arg ]) for add_arg in arg.args ])
        if isinstance(arg, Neg):
            iarg = arg.args[0]
            numeric *= -1
            if isinstance(iarg, Number):
                numeric *= iarg.value
            else:
                terms.update({iarg:1})
        elif isinstance(arg, Number):
            numeric *= arg.value
        elif isinstance(arg, Pow):
            if isinstance(arg.power, Neg):
                if isinstance(arg.power.arg, Number):
                    terms.update({arg.base: -arg.power.arg.value})
            elif isinstance(arg.power, Number):
                terms.update({arg.base: arg.power.value})
            else:
                terms.update({arg.base: arg.power})
        else:
            terms.update({arg:1})
    new_args = [ s**v if v != 1 else s for s, v in terms.items() if v != 0]
    if numeric == 0:
        return Zero
    if len(new_args) == 0:
        return Number(numeric)
    if len(args) == 1 and numeric == 1:
        return new_args[0]
    if len(args) == 1 and numeric == -1:
        return Neg(new_args[0])
    if numeric == 1:
        return Mul( *new_args )
    if numeric == -1:
        return Neg(Mul( *new_args ))
    ret = Mul( Number(numeric), *new_args )
    return ret
Exemple #5
0
 def mul_order():
     return Add.mul_order() - 1
Exemple #6
0
 def __rsub__(self, arg):
     return Add(translate(arg), Neg(self))
Exemple #7
0
 def __sub__(self, arg):
     return Add(self, Neg(translate(arg)))
Exemple #8
0
 def __radd__(self, arg):
     return Add(translate(arg), self)
Exemple #9
0
 def __add__(self, arg):
     return Add(self, translate(arg))