Exemple #1
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 #2
0
class Neg(Expr):
    def add_order(self):
        return self.arg.add_order() + .1

    def mul_order(self):
        return self.arg.mul_order()

    rules = RuleList(
        #         Rule(
        #             r'negative number',
        #             lambda obj: isinstance(obj.arg, Number),
        #             lambda obj, v: NegNumber(obj.arg.value)
        #         ),
        Rule(r'double negative', lambda obj: isinstance(obj.arg, Neg),
             lambda obj, v: obj.arg.arg))

    def __new__(cls, arg):
        obj = super().__new__(cls, arg)
        if not hasattr(obj, 'arg'):
            obj.arg = arg
        return obj

    def __init__(self, *args, **kwargs):
        pass

    def __str__(self):
        arg = self.arg
        s = str(arg)
        if not isinstance(arg, Symbol):
            if not hasattr(arg, 'base'):
                s = delim(s)
        return fr'-{s}'
Exemple #3
0
class Pow(Expr):
    @staticmethod
    def add_order():
        return Mul.add_order() - 1

    @staticmethod
    def mul_order():
        return Add.mul_order() - 1

    rules = RuleList(
        Rule('(x!=0)^0 -> 1',
             lambda obj: obj.base == Number(0) and not obj.power == Number(0),
             lambda obj, v: Number(1)),
        Rule('0^{x!=0} -> 0',
             lambda obj: obj.power == Number(0) and not obj.base == Number(0),
             lambda obj, v: Number(0)),
        Rule('x^1 -> x', lambda obj: obj.power == Number(1),
             lambda obj, v: obj.base),
        Rule('1^x -> 1', lambda obj: obj.base == Number(1),
             lambda obj, v: Number(1)),
        Rule('(x^a)^b -> x^{a*b}', lambda obj: isinstance(obj.base, Pow),
             lambda obj, v: obj.base.base**(obj.base.power * obj.power)),
    )

    def __new__(cls, *args, **kwargs):
        obj = super().__new__(cls, *args)
        if not hasattr(obj, 'base'):
            obj.base = args[0]
            obj.power = args[1]
        return obj

    def __init__(self, *args, **kwargs):
        pass

    def __str__(self):
        base = self.base
        if not isinstance(base, (Symbol, Indexed)):
            base = delim(base)
        power = self.power
        if isinstance(power, Neg):
            if power == -Number(1):
                return fr'\frac{{1}}{{{base}}}'
            return fr'\frac{{1}}{{{base}^{{{power.arg}}} }}'
        return fr'{base}^{{ {power} }}'
Exemple #4
0
class Add(Expr):
    @staticmethod
    def add_order():
        return Symbol.add_order() - 1

    @staticmethod
    def mul_order():
        return Symbol.mul_order() + 2

    rules = RuleList(
        Rule(r'flatten args', lambda obj: any(areinstance(obj.args, Add)),
             lambda obj, v: Add(*flatten_args(obj))),
        Rule(
            r'add numbers', lambda obj: any(areinstance(obj.args, Number)),
            lambda obj, v: Add(Number(sum(getnumbervalues(
                obj))), *[arg for arg in obj.args if not isnumber(arg)])),
        Rule(r'add rules', lambda obj: True, lambda obj, v: rules_add(obj, v)),
    )

    def __new__(cls, *args, **kwargs):
        if len(args) == 0:
            return Zero
        if len(args) == 1:
            return args[0]
        if Zero in args:
            return Add(*[arg for arg in args if not arg == Zero])
        args = sorted(args, key=lambda x: x.add_order())
        obj = super().__new__(cls, *args)
        return obj

    def __init__(self, *args, **kwargs):
        pass

    def __str__(self):
        s = '+'.join([
            str(arg) if not isinstance(arg, Add) else delim(str(arg))
            for arg in self.args
        ])
        return s.replace('+-', '-')
Exemple #5
0
    def __lshift__(self, arg):
        def _(obj, v):
            print(arg.label)
            print(self.args[0].label)
            print(obj.args[0].label)
            string = arg.label.replace(self.args[0].label, obj.args[0].label)
            print('string', string)
            return eval(
                arg.label.replace(self.args[0].label, obj.args[0].label))

        rule = Rule(fr'{self} := {arg}',
                    lambda obj: obj.operator == self.operator,
                    lambda obj, v: _(obj, v))
        self.__class__.rules.append(rule)
        return
Exemple #6
0
class DiracDelta(AppliedFunction):
    rules = RuleList(
        Rule(
            'delta dirac zero',
            lambda obj: obj.arg == Number(0),
            lambda obj, v: Number(1)
        )
    )
    
    def __new__(cls, arg, **kwargs):
        if arg == Number(0):
            return Number(1)
        symbol = Symbol(r'{\delta}')
        obj = super().__new__(cls, symbol, arg)
        if not hasattr(obj, 'arg'):
            obj.arg = arg
        return obj
Exemple #7
0
class KroneckerDelta(Indexed):
    @staticmethod
    def add_order():
        return Mul.add_order() - 1

    @staticmethod
    def mul_order():
        return AppliedFunction.mul_order() + 2

    rules = RuleList(
        Rule('KroneckerDelta rule',
             lambda obj: obj.indices[0] == obj.indices[1],
             lambda obj, v: Number(1)))

    def __new__(cls, ind0, ind1, **kwargs):
        if ind0 == ind1:
            return Number(1)
        symbol = Symbol(r'{\delta}')
        obj = super().__new__(cls, symbol, [ind0, ind1])
        return obj
Exemple #8
0
class Mul(Expr):
    @staticmethod
    def add_order():
        return Symbol.add_order()+2
    @staticmethod
    def mul_order():
        return Symbol.mul_order()+1
    
    rules = RuleList(
        Rule(
            r'mul rules',
            lambda obj: True,
            lambda obj, v: rules_mul(obj, v)
        ),
    )

    def __new__(cls, *args, **kwargs):
        if len(args) == 0:
            return Zero
        if len(args) == 1:
            return args[0]
        if Zero in args:
            return Zero
        if One in args:
            return Mul(*[arg for arg in args if not arg == One])
        args = sorted( args, key=lambda x: x.mul_order() )
        obj = super().__new__(cls, *args )
        return obj
    
    def __init__(self, *args, **kwargs):
        pass
    
    def __str__(self):
        s = ''
        for arg in self.args:
            if isinstance(arg, (Add, Neg, Mul)):
                s += delim(str(arg))
            else:
                s += str(arg)
        return s
Exemple #9
0
class Summation(Expr):
    @staticmethod
    def add_order():
        return Number.add_order() + 1

    @staticmethod
    def mul_order():
        return AppliedFunction.mul_order() + 1

    rules = RuleList(
        Rule('summation rule', lambda obj: True,
             lambda obj, v: rules_summation(obj, v)))

    def __new__(cls, arg, *lims, **kwargs):
        lims = list(map(translate, lims))
        if len(lims) < 2:
            lims = (lims[0], -Infinity, Infinity)
        if len(lims) < 3:
            lims = (lims[0], lims[1], Infinity)
        if arg == Number(1):
            return lims[2] - lims[1]
        obj = super().__new__(cls, arg, *lims)
        if not hasattr(obj, 'name'):
            obj.arg = arg
            obj.lims = lims
        return obj

    def __init__(self, *args, **kwargs):
        pass

    def __str__(self):
        lims = self.lims
        arg = self.arg
        if isinstance(arg, Add):
            arg = delim(arg)
        return fr'\sum_{{{lims[0]}={lims[1]}}}^{{{lims[2]}}}{arg}'