コード例 #1
0
    def apply(self, expr, x, x0, evaluation, options={}):
        'Limit[expr_, x_->x0_, OptionsPattern[Limit]]'

        expr = expr.to_sympy()
        x = x.to_sympy()
        x0 = x0.to_sympy()

        direction = self.get_option(options, 'Direction', evaluation)
        value = direction.get_int_value()
        if value not in (-1, 1):
            evaluation.message('Limit', 'ldir', direction)
        if value > 0:
            dir_sympy = '-'
        else:
            dir_sympy = '+'

        try:
            result = sympy.limit(expr, x, x0, dir_sympy)
            return from_sympy(result)
        except sympy.PoleError:
            pass
        except RuntimeError:
            # Bug in Sympy: RuntimeError: maximum recursion depth exceeded while calling a Python object
            pass
        except NotImplementedError:
            pass
コード例 #2
0
ファイル: calculus.py プロジェクト: 0xffea/Mathics
 def apply(self, expr, x, x0, evaluation, options={}):
     'Limit[expr_, x_->x0_, OptionsPattern[Limit]]'
     
     expr = expr.to_sympy()
     x = x.to_sympy()
     x0 = x0.to_sympy()
     
     direction = self.get_option(options, 'Direction', evaluation)
     value = direction.get_int_value()
     if value not in (-1, 1):
         evaluation.message('Limit', 'ldir', direction)
     if value > 0:
         dir_sympy = '-'
     else:
         dir_sympy = '+'
     
     try:
         result = sympy.limit(expr, x, x0, dir_sympy)
         return from_sympy(result)
     except sympy.PoleError:
         pass
     except RuntimeError:
         # Bug in Sympy: RuntimeError: maximum recursion depth exceeded while calling a Python object
         pass
     except NotImplementedError:
         pass
コード例 #3
0
    def apply(self, expr, evaluation):
        'Together[expr_]'

        expr_sympy = expr.to_sympy()
        result = sympy.together(expr_sympy)
        result = from_sympy(result)
        result = cancel(result)
        return result
コード例 #4
0
ファイル: algebra.py プロジェクト: 0xffea/Mathics
 def apply(self, expr, evaluation):
     'Together[expr_]'
     
     expr_sympy = expr.to_sympy()
     result = sympy.together(expr_sympy)
     result = from_sympy(result)
     result = cancel(result)
     return result
コード例 #5
0
ファイル: algebra.py プロジェクト: mikexstudios/Mathics
 def apply(self, expr, var, evaluation):
     'Apart[expr_, var_Symbol]'
     
     expr_sympy = expr.to_sympy()
     var_sympy = var.to_sympy()
     result = sympy.apart(expr_sympy, var_sympy)
     result = from_sympy(result)
     return result
コード例 #6
0
ファイル: algebra.py プロジェクト: mikexstudios/Mathics
def cancel(expr):
    if expr.has_form('Plus', None):
        return Expression('Plus', *[cancel(leaf) for leaf in expr.leaves])
    else:
        result = expr.to_sympy()
        #result = sympy.powsimp(result, deep=True)
        result = sympy.cancel(result)
        result = sympy_factor(result)   # cancel factors out rationals, so we factor them again
        return from_sympy(result)
コード例 #7
0
    def apply(self, expr, evaluation):
        'Simplify[expr_]'

        expr_sympy = expr.to_sympy()
        result = expr_sympy
        result = sympy.simplify(result)
        result = sympy.trigsimp(result)
        result = sympy.together(result)
        result = sympy.cancel(result)
        result = from_sympy(result)
        return result
コード例 #8
0
ファイル: algebra.py プロジェクト: mikexstudios/Mathics
 def apply(self, expr, evaluation):
     'Simplify[expr_]'
     
     expr_sympy = expr.to_sympy()
     result = expr_sympy
     result = sympy.simplify(result)
     result = sympy.trigsimp(result)
     result = sympy.together(result)
     result = sympy.cancel(result)
     result = from_sympy(result)
     return result
コード例 #9
0
    def apply(self, expr, var, evaluation):
        'Apart[expr_, var_Symbol]'

        expr_sympy = expr.to_sympy()
        var_sympy = var.to_sympy()
        try:
            result = sympy.apart(expr_sympy, var_sympy)
            result = from_sympy(result)
            return result
        except sympy.PolynomialError:
            # raised e.g. for apart(sin(1/(x**2-y**2)))
            return expr
コード例 #10
0
ファイル: algebra.py プロジェクト: 0xffea/Mathics
 def apply(self, expr, var, evaluation):
     'Apart[expr_, var_Symbol]'
     
     expr_sympy = expr.to_sympy()
     var_sympy = var.to_sympy()
     try:
         result = sympy.apart(expr_sympy, var_sympy)
         result = from_sympy(result)
         return result
     except sympy.PolynomialError:
         # raised e.g. for apart(sin(1/(x**2-y**2)))
         return expr
コード例 #11
0
ファイル: algebra.py プロジェクト: 0xffea/Mathics
def cancel(expr):
    if expr.has_form('Plus', None):
        return Expression('Plus', *[cancel(leaf) for leaf in expr.leaves])
    else:
        try:
            result = expr.to_sympy()
            #result = sympy.powsimp(result, deep=True)
            result = sympy.cancel(result)
            result = sympy_factor(result)   # cancel factors out rationals, so we factor them again
            return from_sympy(result)
        except sympy.PolynomialError:
            # e.g. for non-commutative expressions
            return expr
コード例 #12
0
    def apply(self, expr, evaluation):
        'Factor[expr_]'

        expr_sympy = expr.to_sympy()
        try:
            result = sympy.together(expr_sympy)
            numer, denom = result.as_numer_denom()
            if denom == 1:
                result = sympy.factor(expr_sympy)
            else:
                result = sympy.factor(numer) / sympy.factor(denom)
        except sympy.PolynomialError:
            return expr
        return from_sympy(result)
コード例 #13
0
ファイル: algebra.py プロジェクト: 0xffea/Mathics
 def apply(self, expr, evaluation):
     'Factor[expr_]'
     
     expr_sympy = expr.to_sympy()
     try:
         result = sympy.together(expr_sympy)
         numer, denom = result.as_numer_denom()
         if denom == 1:
             result = sympy.factor(expr_sympy)
         else:
             result = sympy.factor(numer) / sympy.factor(denom)
     except sympy.PolynomialError:
         return expr
     return from_sympy(result)
コード例 #14
0
def cancel(expr):
    if expr.has_form('Plus', None):
        return Expression('Plus', *[cancel(leaf) for leaf in expr.leaves])
    else:
        try:
            result = expr.to_sympy()
            #result = sympy.powsimp(result, deep=True)
            result = sympy.cancel(result)
            result = sympy_factor(
                result
            )  # cancel factors out rationals, so we factor them again
            return from_sympy(result)
        except sympy.PolynomialError:
            # e.g. for non-commutative expressions
            return expr
コード例 #15
0
ファイル: algebra.py プロジェクト: 0xffea/Mathics
 def apply(self, expr, evaluation):
     'Simplify[expr_]'
     
     expr_sympy = expr.to_sympy()
     result = expr_sympy
     try:
         result = sympy.simplify(result)
     except TypeError:
         #XXX What's going on here?
         pass
     result = sympy.trigsimp(result)
     result = sympy.together(result)
     result = sympy.cancel(result)
     result = from_sympy(result)
     return result
コード例 #16
0
ファイル: algebra.py プロジェクト: proxy-sander/Mathics
    def apply(self, expr, evaluation):
        'Simplify[expr_]'

        expr_sympy = expr.to_sympy()
        result = expr_sympy
        try:
            result = sympy.simplify(result)
        except TypeError:
            #XXX What's going on here?
            pass
        result = sympy.trigsimp(result)
        result = sympy.together(result)
        result = sympy.cancel(result)
        result = from_sympy(result)
        return result
コード例 #17
0
ファイル: calculus.py プロジェクト: nonohry/Mathics
 def apply(self, f, xs, evaluation):
     'Integrate[f_, xs__]'
     
     f_sympy = f.to_sympy()
     if isinstance(f_sympy, SympyExpression):
         return
     xs = xs.get_sequence()
     vars = []
     prec = None
     for x in xs:
         if x.has_form('List', 3):
             x, a, b = x.leaves
             prec_a = a.get_precision()
             prec_b = b.get_precision()
             if prec_a is not None and prec_b is not None:
                 prec_new = min(prec_a, prec_b)
                 if prec is None or prec_new < prec:
                     prec = prec_new
             a = a.to_sympy()
             b = b.to_sympy()
         else:
             a = b = None
             a_mathics, b_mathics = a, b
         if not x.get_name():
             evaluation.message('Integrate', 'ilim')
             return
         x = x.to_sympy()
         if a is None or b is None:
             vars.append(x)
         else:
             vars.append((x, a, b))
     try:
         result = sympy.integrate(f_sympy, *vars)
     except sympy.PolynomialError:
         return
     except ValueError:
         # e.g. ValueError: can't raise polynomial to a negative power
         return
     except NotImplementedError:
         # e.g. NotImplementedError: Result depends on the sign of -sign(_Mathics_User_j)*sign(_Mathics_User_w)
         return
         
     if prec is not None:
         result = sympy.N(result)
     result = from_sympy(result)
     return result
コード例 #18
0
ファイル: calculus.py プロジェクト: chid/Mathics
    def apply(self, f, xs, evaluation):
        'Integrate[f_, xs__]'

        f_sympy = f.to_sympy()
        if isinstance(f_sympy, SympyExpression):
            return
        xs = xs.get_sequence()
        vars = []
        prec = None
        for x in xs:
            if x.has_form('List', 3):
                x, a, b = x.leaves
                prec_a = a.get_precision()
                prec_b = b.get_precision()
                if prec_a is not None and prec_b is not None:
                    prec_new = min(prec_a, prec_b)
                    if prec is None or prec_new < prec:
                        prec = prec_new
                a = a.to_sympy()
                b = b.to_sympy()
            else:
                a = b = None
                a_mathics, b_mathics = a, b
            if not x.get_name():
                evaluation.message('Integrate', 'ilim')
                return
            x = x.to_sympy()
            if a is None or b is None:
                vars.append(x)
            else:
                vars.append((x, a, b))
        try:
            result = sympy.integrate(f_sympy, *vars)
        except sympy.PolynomialError:
            return

        if prec is not None:
            result = sympy.N(result)
        result = from_sympy(result)
        return result
コード例 #19
0
ファイル: calculus.py プロジェクト: vpereira/Mathics
    def apply(self, f, xs, evaluation):
        "Integrate[f_, xs__]"

        f_sympy = f.to_sympy()
        if isinstance(f_sympy, SympyExpression):
            return
        xs = xs.get_sequence()
        vars = []
        prec = None
        for x in xs:
            if x.has_form("List", 3):
                x, a, b = x.leaves
                prec_a = a.get_precision()
                prec_b = b.get_precision()
                if prec_a is not None and prec_b is not None:
                    prec_new = min(prec_a, prec_b)
                    if prec is None or prec_new < prec:
                        prec = prec_new
                a = a.to_sympy()
                b = b.to_sympy()
            else:
                a = b = None
                a_mathics, b_mathics = a, b
            if not x.get_name():
                evaluation.message("Integrate", "ilim")
                return
            x = x.to_sympy()
            if a is None or b is None:
                vars.append(x)
            else:
                vars.append((x, a, b))
        try:
            result = sympy.integrate(f_sympy, *vars)
        except sympy.PolynomialError:
            return

        if prec is not None:
            result = sympy.N(result)
        result = from_sympy(result)
        return result
コード例 #20
0
ファイル: calculus.py プロジェクト: vpereira/Mathics
    def apply(self, expr, x, x0, evaluation, options={}):
        "Limit[expr_, x_->x0_, OptionsPattern[Limit]]"

        expr = expr.to_sympy()
        x = x.to_sympy()
        x0 = x0.to_sympy()

        direction = self.get_option(options, "Direction", evaluation)
        value = direction.get_int_value()
        if value not in (-1, 1):
            evaluation.message("Limit", "ldir", direction)
        if value > 0:
            dir_sympy = "-"
        else:
            dir_sympy = "+"

        try:
            result = sympy.limit(expr, x, x0, dir_sympy)
            return from_sympy(result)
        except sympy.PoleError:
            pass
        except NotImplementedError:
            pass
コード例 #21
0
ファイル: algebra.py プロジェクト: 0xffea/Mathics
 def apply(self, expr, evaluation):
     'Denominator[expr_]'
     
     sympy_expr = expr.to_sympy()
     numer, denom = sympy_expr.as_numer_denom()
     return from_sympy(denom)
コード例 #22
0
ファイル: calculus.py プロジェクト: cjiang/Mathics
 def apply(self, eqs, vars, evaluation):
     'Solve[eqs_, vars_]'
     
     vars_original = vars
     head_name = vars.get_head_name()
     if head_name == 'List':
         vars = vars.leaves
     else:
         vars = [vars]
     for var in vars:
         if (var.is_atom() and not var.is_symbol()) or head_name in ('Plus', 'Times', 'Power'):
             evaluation.message('Solve', 'ivar', vars_original)
             return
     eqs_original = eqs
     if eqs.get_head_name() in ('List', 'And'):
         eqs = eqs.leaves
     else:
         eqs = [eqs]
     sympy_eqs = []
     sympy_denoms = []
     for eq in eqs:
         symbol_name = eq.get_name()
         if symbol_name == 'True':
             #return Expression('List', Expression('List'))
             pass
         elif symbol_name == 'False':
             return Expression('List')
         elif not eq.has_form('Equal', 2):
             return evaluation.message('Solve', 'eqf', eqs_original)
         else:
             left, right = eq.leaves
             left = left.to_sympy()
             right = right.to_sympy()
             #vars_sympy = [var.to_sympy() for var in vars]
             eq = left - right
             eq = sympy.together(eq)
             eq = sympy.cancel(eq)                
             sympy_eqs.append(eq)
             numer, denom = eq.as_numer_denom()
             sympy_denoms.append(denom)
     #eqs = actual_eqs
     
     #left, right = eq.leaves
     
     vars_sympy = [var.to_sympy() for var in vars]
     
     # delete unused variables to avoid SymPy's
     # PolynomialError: Not a zero-dimensional system
     # in e.g. Solve[x^2==1&&z^2==-1,{x,y,z}]
     all_vars = vars[:]
     all_vars_sympy = vars_sympy[:]
     #for index, var in enumerate(all_vars):
     #    if eqs_original.is_free(var, evaluation):
     vars = []
     vars_sympy = []   
     for var, var_sympy in zip(all_vars, all_vars_sympy):
         pattern = Pattern.create(var)
         if not eqs_original.is_free(pattern, evaluation):
             vars.append(var)
             vars_sympy.append(var_sympy)
     
     def transform_dict(sols):
         #print "Transform %s" % sols
         if not sols:
             yield sols
         for var, sol in sols.iteritems():
             rest = sols.copy()
             del rest[var]
             rest = transform_dict(rest)
             if not isinstance(sol, (tuple, list)):
                 #print "Convert %s (type %s)" % (sol, type(sol))
                 sol = [sol]
             if not sol:
                 for r in rest:
                     #print "Yield %s" % r
                     yield r
             else:
                 for r in rest:
                     for item in sol:
                         #print "Yield %s with new %s" % (r, item)
                         new_sols = r.copy()
                         new_sols[var] = item
                         yield new_sols
             break
     
     def transform_solution(sol):
         #if isinstance(sol, (list, tuple)):
         if not isinstance(sol, dict):
             if not isinstance(sol, (list, tuple)):
                 sol = [sol]
             sol = dict(zip(vars_sympy, sol))
         #return sol
         return transform_dict(sol)
     
     if not sympy_eqs:
         sympy_eqs = True
     elif len(sympy_eqs) == 1:
         sympy_eqs = sympy_eqs[0]
         
     #eq = left - right
     #eq = sympy.together(eq)
     #eq = sympy.cancel(eq)   # otherwise Solve[f''[x]==0,x] for f[x_]:=4 x / (x ^ 2 + 3 x + 5) takes forever
     try:
         #print sympy_eqs
         result = sympy.solve(sympy_eqs, vars_sympy)
         #print result
         if not isinstance(result, list):
             result = [result]
         if result == [True]:
             return Expression('List', Expression('List'))
         if result == [None]:
             return Expression('List')
         #print result
         #result = [transform_solution(sol) for sol in result]
         results = []
         for sol in result:
             results.extend(transform_solution(sol))
         result = results
         #print result
         if any(sol and any(var not in sol for var in all_vars_sympy) for sol in result):
             evaluation.message('Solve', 'svars')
         #numer, denom = eq.as_numer_denom()
         #for sol in result:
         #    sol_denom = denom.subs({var_sympy: sol})
         result = [sol for sol in result if all(sympy.simplify(denom.subs(sol)) != 0 for denom in sympy_denoms)]   # filter out results for which denominator is 0
             # (SymPy should actually do that itself, but it doesn't!)
         return Expression('List', *(Expression('List', *(Expression('Rule', var, from_sympy(sol[var_sympy]))
             for var, var_sympy in zip(vars, vars_sympy) if var_sympy in sol)) for sol in result))
     #except TypeError:
         #evaluation.message('Solve', 'ivar', vars_original)
         #raise
     except sympy.PolynomialError:
         # raised for e.g. Solve[x^2==1&&z^2==-1,{x,y,z}] when not deleting unused variables beforehand
         pass
     except NotImplementedError:
         pass
コード例 #23
0
    def apply(self, eqs, vars, evaluation):
        'Solve[eqs_, vars_]'

        vars_original = vars
        head_name = vars.get_head_name()
        if head_name == 'List':
            vars = vars.leaves
        else:
            vars = [vars]
        for var in vars:
            if (var.is_atom()
                    and not var.is_symbol()) or head_name in ('Plus', 'Times',
                                                              'Power'):
                evaluation.message('Solve', 'ivar', vars_original)
                return
        eqs_original = eqs
        if eqs.get_head_name() in ('List', 'And'):
            eqs = eqs.leaves
        else:
            eqs = [eqs]
        sympy_eqs = []
        sympy_denoms = []
        for eq in eqs:
            symbol_name = eq.get_name()
            if symbol_name == 'True':
                #return Expression('List', Expression('List'))
                pass
            elif symbol_name == 'False':
                return Expression('List')
            elif not eq.has_form('Equal', 2):
                return evaluation.message('Solve', 'eqf', eqs_original)
            else:
                left, right = eq.leaves
                left = left.to_sympy()
                right = right.to_sympy()
                #vars_sympy = [var.to_sympy() for var in vars]
                eq = left - right
                eq = sympy.together(eq)
                eq = sympy.cancel(eq)
                sympy_eqs.append(eq)
                numer, denom = eq.as_numer_denom()
                sympy_denoms.append(denom)
        #eqs = actual_eqs

        #left, right = eq.leaves

        vars_sympy = [var.to_sympy() for var in vars]

        # delete unused variables to avoid SymPy's
        # PolynomialError: Not a zero-dimensional system
        # in e.g. Solve[x^2==1&&z^2==-1,{x,y,z}]
        all_vars = vars[:]
        all_vars_sympy = vars_sympy[:]
        #for index, var in enumerate(all_vars):
        #    if eqs_original.is_free(var, evaluation):
        vars = []
        vars_sympy = []
        for var, var_sympy in zip(all_vars, all_vars_sympy):
            pattern = Pattern.create(var)
            if not eqs_original.is_free(pattern, evaluation):
                vars.append(var)
                vars_sympy.append(var_sympy)

        def transform_dict(sols):
            #print "Transform %s" % sols
            if not sols:
                yield sols
            for var, sol in sols.iteritems():
                rest = sols.copy()
                del rest[var]
                rest = transform_dict(rest)
                if not isinstance(sol, (tuple, list)):
                    #print "Convert %s (type %s)" % (sol, type(sol))
                    sol = [sol]
                if not sol:
                    for r in rest:
                        #print "Yield %s" % r
                        yield r
                else:
                    for r in rest:
                        for item in sol:
                            #print "Yield %s with new %s" % (r, item)
                            new_sols = r.copy()
                            new_sols[var] = item
                            yield new_sols
                break

        def transform_solution(sol):
            #if isinstance(sol, (list, tuple)):
            if not isinstance(sol, dict):
                if not isinstance(sol, (list, tuple)):
                    sol = [sol]
                sol = dict(zip(vars_sympy, sol))
            #return sol
            return transform_dict(sol)

        if not sympy_eqs:
            sympy_eqs = True
        elif len(sympy_eqs) == 1:
            sympy_eqs = sympy_eqs[0]

        #eq = left - right
        #eq = sympy.together(eq)
        #eq = sympy.cancel(eq)   # otherwise Solve[f''[x]==0,x] for f[x_]:=4 x / (x ^ 2 + 3 x + 5) takes forever
        try:
            #print sympy_eqs
            result = sympy.solve(sympy_eqs, vars_sympy)
            #print result
            if not isinstance(result, list):
                result = [result]
            if result == [True]:
                return Expression('List', Expression('List'))
            if result == [None]:
                return Expression('List')
            #print result
            #result = [transform_solution(sol) for sol in result]
            results = []
            for sol in result:
                results.extend(transform_solution(sol))
            result = results
            #print result
            if any(sol and any(var not in sol for var in all_vars_sympy)
                   for sol in result):
                evaluation.message('Solve', 'svars')
            #numer, denom = eq.as_numer_denom()
            #for sol in result:
            #    sol_denom = denom.subs({var_sympy: sol})
            result = [
                sol for sol in result if all(
                    sympy.simplify(denom.subs(sol)) != 0
                    for denom in sympy_denoms)
            ]  # filter out results for which denominator is 0
            # (SymPy should actually do that itself, but it doesn't!)
            return Expression(
                'List',
                *(Expression(
                    'List',
                    *(Expression('Rule', var, from_sympy(sol[var_sympy]))
                      for var, var_sympy in zip(vars, vars_sympy)
                      if var_sympy in sol)) for sol in result))
        #except TypeError:
        #evaluation.message('Solve', 'ivar', vars_original)
        #raise
        except sympy.PolynomialError:
            # raised for e.g. Solve[x^2==1&&z^2==-1,{x,y,z}] when not deleting unused variables beforehand
            pass
        except NotImplementedError:
            pass
コード例 #24
0
    def apply(self, eqn, y, x, evaluation):
        'DSolve[eqn_, y_, x_]'

        if eqn.has_form('List', eqn):
            #TODO: Try and solve BVPs using Solve or something analagous OR add this functonality to sympy.
            evaluation.message('DSolve', 'symsys')
            return

        if eqn.get_head_name() != 'Equal':
            evaluation.message('DSolve', 'deqn', eqn)
            return

        if (x.is_atom() and not x.is_symbol()) or \
          x.get_head_name() in ('Plus', 'Times', 'Power') or \
          'Constant' in x.get_attributes(evaluation.definitions):
            evaluation.message('DSolve', 'dsvar')
            return

        # Fixes pathalogical DSolve[y''[x] == y[x], y, x]
        try:
            y.leaves
            function_form = None
            func = y
        except AttributeError:
            func = Expression(y, x)
            function_form = Expression('List', x)

        if func.is_atom():
            evaluation.message('DSolve', 'dsfun', y)
            return

        if len(func.leaves) != 1:
            evaluation.message('DSolve', 'symmua')
            return

        if x not in func.leaves:
            evaluation.message('DSolve', 'deqx')
            return

        left, right = eqn.leaves
        eqn = Expression('Plus', left, Expression('Times', -1, right)).evaluate(evaluation)

        sym_eq = eqn.to_sympy(converted_functions = set([func.get_head_name()]))
        sym_x = sympy.symbols(str(sympy_symbol_prefix + x.name))
        sym_func = sympy.Function(str(sympy_symbol_prefix + func.get_head_name())) (sym_x)

        try:
            sym_result = sympy.dsolve(sym_eq, sym_func)
            if not isinstance(sym_result, list):
                sym_result = [sym_result]
        except ValueError as e:
            evaluation.message('DSolve', 'symimp')
            return
        except NotImplementedError as e:
            evaluation.message('DSolve', 'symimp')
            return
        except AttributeError as e:
            evaluation.message('DSolve', 'litarg', eqn)
            return
        except KeyError:
            evaluation.message('DSolve', 'litarg', eqn)
            return

        if function_form is None:
            return Expression('List', *[Expression('List', 
                Expression('Rule', *from_sympy(soln).leaves)) for soln in sym_result])
        else:
            return Expression('List', *[Expression('List', Expression('Rule', y, 
                Expression('Function', function_form, *from_sympy(soln).leaves[1:]))) for soln in sym_result])
コード例 #25
0
    def apply(self, expr, evaluation):
        'Denominator[expr_]'

        sympy_expr = expr.to_sympy()
        numer, denom = sympy_expr.as_numer_denom()
        return from_sympy(denom)
コード例 #26
0
ファイル: recurrence.py プロジェクト: 0xffea/Mathics
    def apply(self, eqns, a, n, evaluation):
        'RSolve[eqns_, a_, n_]'

        #TODO: Do this with rules?
        if not eqns.has_form('List', None):
            eqns = Expression('List', eqns)

        if len(eqns.leaves) == 0:
            return

        for eqn in eqns.leaves:
            if eqn.get_head_name() != 'Equal':
                evaluation.message('RSolve', 'deqn', eqn)
                return

        if (n.is_atom() and not n.is_symbol()) or \
          n.get_head_name() in ('Plus', 'Times', 'Power') or \
          'Constant' in n.get_attributes(evaluation.definitions):
            evaluation.message('RSolve', 'dsvar')
            return

        try:
            a.leaves
            function_form = None
            func = a
        except AttributeError:
            func = Expression(a, n)
            function_form = Expression('List', n)

        if func.is_atom() or len(func.leaves) != 1:
            evaluation.message('RSolve', 'dsfun', a)

        if n not in func.leaves:
            evaluation.message('DSolve', 'deqx')

        # Seperate relations from conditions
        conditions = {}
        def is_relation(eqn):
            left, right = eqn.leaves
            for l,r in [(left, right), (right, left)]:
                if left.get_head_name() == func.get_head_name() and len(left.leaves) == 1 \
                  and isinstance(l.leaves[0].to_python(), int) and r.is_numeric():
                    conditions[l.leaves[0].to_python()] = r.to_sympy()
                    return False
            return True
        relation = filter(is_relation, eqns.leaves)[0]

        left, right = relation.leaves
        relation = Expression('Plus', left, Expression('Times', -1, right)).evaluate(evaluation)

        sym_eq = relation.to_sympy(converted_functions = set([func.get_head_name()]))
        sym_n = sympy.symbols(str(sympy_symbol_prefix + n.name))
        sym_func = sympy.Function(str(sympy_symbol_prefix + func.get_head_name())) (sym_n)

        sym_conds = {}
        for cond in conditions:
            sym_conds[sympy.Function(str(sympy_symbol_prefix + func.get_head_name()))(cond)] = conditions[cond]

        try:
            # Sympy raises error when given empty conditions. Fixed in upcomming sympy release.
            if sym_conds != {}:
                sym_result = sympy.rsolve(sym_eq, sym_func, sym_conds)
            else:
                sym_result = sympy.rsolve(sym_eq, sym_func)

            if not isinstance(sym_result, list):
                sym_result = [sym_result]
        except ValueError as ve:
            return

        if function_form is None:
            return Expression('List', *[Expression('List',
                Expression('Rule', a, from_sympy(soln))) for soln in sym_result])
        else:
            return Expression('List', *[Expression('List', Expression('Rule', a,
                Expression('Function', function_form, from_sympy(soln)))) for soln in sym_result])
コード例 #27
0
ファイル: recurrence.py プロジェクト: proxy-sander/Mathics
    def apply(self, eqns, a, n, evaluation):
        'RSolve[eqns_, a_, n_]'

        #TODO: Do this with rules?
        if not eqns.has_form('List', None):
            eqns = Expression('List', eqns)

        if len(eqns.leaves) == 0:
            return

        for eqn in eqns.leaves:
            if eqn.get_head_name() != 'Equal':
                evaluation.message('RSolve', 'deqn', eqn)
                return

        if (n.is_atom() and not n.is_symbol()) or \
          n.get_head_name() in ('Plus', 'Times', 'Power') or \
          'Constant' in n.get_attributes(evaluation.definitions):
            evaluation.message('RSolve', 'dsvar')
            return

        try:
            a.leaves
            function_form = None
            func = a
        except AttributeError:
            func = Expression(a, n)
            function_form = Expression('List', n)

        if func.is_atom() or len(func.leaves) != 1:
            evaluation.message('RSolve', 'dsfun', a)

        if n not in func.leaves:
            evaluation.message('DSolve', 'deqx')

        # Seperate relations from conditions
        conditions = {}

        def is_relation(eqn):
            left, right = eqn.leaves
            for l, r in [(left, right), (right, left)]:
                if left.get_head_name() == func.get_head_name() and len(left.leaves) == 1 \
                  and isinstance(l.leaves[0].to_python(), int) and r.is_numeric():
                    conditions[l.leaves[0].to_python()] = r.to_sympy()
                    return False
            return True

        relation = filter(is_relation, eqns.leaves)[0]

        left, right = relation.leaves
        relation = Expression('Plus', left,
                              Expression('Times', -1,
                                         right)).evaluate(evaluation)

        sym_eq = relation.to_sympy(
            converted_functions=set([func.get_head_name()]))
        sym_n = sympy.symbols(str(sympy_symbol_prefix + n.name))
        sym_func = sympy.Function(
            str(sympy_symbol_prefix + func.get_head_name()))(sym_n)

        sym_conds = {}
        for cond in conditions:
            sym_conds[sympy.Function(
                str(sympy_symbol_prefix +
                    func.get_head_name()))(cond)] = conditions[cond]

        try:
            # Sympy raises error when given empty conditions. Fixed in upcomming sympy release.
            if sym_conds != {}:
                sym_result = sympy.rsolve(sym_eq, sym_func, sym_conds)
            else:
                sym_result = sympy.rsolve(sym_eq, sym_func)

            if not isinstance(sym_result, list):
                sym_result = [sym_result]
        except ValueError as ve:
            return

        if function_form is None:
            return Expression(
                'List', *[
                    Expression('List', Expression('Rule', a, from_sympy(soln)))
                    for soln in sym_result
                ])
        else:
            return Expression(
                'List', *[
                    Expression(
                        'List',
                        Expression(
                            'Rule', a,
                            Expression('Function', function_form,
                                       from_sympy(soln))))
                    for soln in sym_result
                ])
コード例 #28
0
ファイル: calculus.py プロジェクト: nonohry/Mathics
 def apply(self, eqs, vars, evaluation):
     'Solve[eqs_, vars_]'
     
     vars_original = vars
     head_name = vars.get_head_name()
     if head_name == 'List':
         vars = vars.leaves
     else:
         vars = [vars]
     for var in vars:
         if (var.is_atom() and not var.is_symbol()) or \
             head_name in ('Plus', 'Times', 'Power') or \
             'Constant' in var.get_attributes(evaluation.definitions):
             evaluation.message('Solve', 'ivar', vars_original)
             return
     eqs_original = eqs
     if eqs.get_head_name() in ('List', 'And'):
         eqs = eqs.leaves
     else:
         eqs = [eqs]
     sympy_eqs = []
     sympy_denoms = []
     for eq in eqs:
         symbol_name = eq.get_name()
         if symbol_name == 'True':
             pass
         elif symbol_name == 'False':
             return Expression('List')
         elif not eq.has_form('Equal', 2):
             return evaluation.message('Solve', 'eqf', eqs_original)
         else:
             left, right = eq.leaves
             left = left.to_sympy()
             right = right.to_sympy()
             eq = left - right
             eq = sympy.together(eq)
             eq = sympy.cancel(eq)                
             sympy_eqs.append(eq)
             numer, denom = eq.as_numer_denom()
             sympy_denoms.append(denom)
     
     vars_sympy = [var.to_sympy() for var in vars]
     
     # delete unused variables to avoid SymPy's
     # PolynomialError: Not a zero-dimensional system
     # in e.g. Solve[x^2==1&&z^2==-1,{x,y,z}]
     all_vars = vars[:]
     all_vars_sympy = vars_sympy[:]
     vars = []
     vars_sympy = []   
     for var, var_sympy in zip(all_vars, all_vars_sympy):
         pattern = Pattern.create(var)
         if not eqs_original.is_free(pattern, evaluation):
             vars.append(var)
             vars_sympy.append(var_sympy)
     
     def transform_dict(sols):
         if not sols:
             yield sols
         for var, sol in sols.iteritems():
             rest = sols.copy()
             del rest[var]
             rest = transform_dict(rest)
             if not isinstance(sol, (tuple, list)):
                 sol = [sol]
             if not sol:
                 for r in rest:
                     yield r
             else:
                 for r in rest:
                     for item in sol:
                         new_sols = r.copy()
                         new_sols[var] = item
                         yield new_sols
             break
     
     def transform_solution(sol):
         if not isinstance(sol, dict):
             if not isinstance(sol, (list, tuple)):
                 sol = [sol]
             sol = dict(zip(vars_sympy, sol))
         return transform_dict(sol)
     
     if not sympy_eqs:
         sympy_eqs = True
     elif len(sympy_eqs) == 1:
         sympy_eqs = sympy_eqs[0]
         
     try:
         if isinstance(sympy_eqs, bool):
             result = sympy_eqs
         else:
             result = sympy.solve(sympy_eqs, vars_sympy)
         if not isinstance(result, list):
             result = [result]
         if result == [True]:
             return Expression('List', Expression('List'))
         if result == [None]:
             return Expression('List')
         results = []
         for sol in result:
             results.extend(transform_solution(sol))
         result = results
         if any(sol and any(var not in sol for var in all_vars_sympy) for sol in result):
             evaluation.message('Solve', 'svars')
         result = [sol for sol in result if all(sympy.simplify(denom.subs(sol)) != 0 for denom in sympy_denoms)]   # filter out results for which denominator is 0
             # (SymPy should actually do that itself, but it doesn't!)
         return Expression('List', *(Expression('List', *(Expression('Rule', var, from_sympy(sol[var_sympy]))
             for var, var_sympy in zip(vars, vars_sympy) if var_sympy in sol)) for sol in result))
     except sympy.PolynomialError:
         # raised for e.g. Solve[x^2==1&&z^2==-1,{x,y,z}] when not deleting unused variables beforehand
         pass
     except NotImplementedError:
         pass
     except TypeError, exc:
         if str(exc).startswith("expected Symbol, Function or Derivative"):
             evaluation.message('Solve', 'ivar', vars_original)