예제 #1
0
def rules_add(obj, verbose=False):
    args = flatten_args(obj)
    terms = Counter()
    numeric = 0
    for arg in args:
        if isinstance(arg, Neg):
            arg0 = arg.args[0]
            if isinstance(arg0, Number):
                numeric += -arg0.value
            else:
                terms.update({Mul(arg0): -1})
        elif isinstance(arg, Number):
            numeric += arg.value
        elif isinstance(arg, Mul):
            arg0 = arg.args[0]
            if isinstance(arg0, Neg):
                if isinstance(arg0.args[0], Number):
                    terms.update({Mul(*arg.args[1:]): -arg0.args[0].value})
            elif isinstance(arg0, Number):
                terms.update({Mul(*arg.args[1:]): arg0.value})
            else:
                terms.update({arg: 1})
        else:
            terms.update({arg: 1})
    new_args = [v * s if v != 1 else s for s, v in terms.items() if v != 0]
    if len(new_args) == 0:
        return Number(numeric)
    if len(new_args) == 1 and numeric == 0:
        return new_args[0]
    if numeric == 0:
        return Add(*new_args)
    return Add(*new_args, Number(numeric))
예제 #2
0
파일: diracdelta.py 프로젝트: PhMota/sph
 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
예제 #3
0
파일: operable.py 프로젝트: PhMota/sph
def translate(arg):
    if isinstance(arg, Operable):
        return arg
    if isinstance(arg, (int, float)):
        if arg < 0:
            return Neg(Number(abs(arg)))
        return Number(arg)
    if isinstance(arg, str):
        return Symbol(arg)
    raise Exception('translate not implemented for', arg.__class__)
예제 #4
0
파일: derivative.py 프로젝트: PhMota/sph
 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
예제 #5
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
예제 #6
0
파일: diracdelta.py 프로젝트: PhMota/sph
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
예제 #7
0
파일: pow.py 프로젝트: PhMota/sph
 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} }}'
예제 #8
0
파일: mul.py 프로젝트: PhMota/sph
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
예제 #9
0
 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
예제 #10
0
파일: pow.py 프로젝트: PhMota/sph
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} }}'
예제 #11
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
예제 #12
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('+-', '-')
예제 #13
0
 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
예제 #14
0
 def add_order():
     return Number.add_order() + 1
예제 #15
0
파일: diracdelta.py 프로젝트: PhMota/sph
def rules_diracdelta(obj, v):
    if obj.arg == Number(0):
        return Number(1)
    return obj