예제 #1
0
    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() != 'System`Equal':
                evaluation.message('RSolve', 'deqn', eqn)
                return

        if (n.is_atom() and not n.is_symbol()) or \
            n.get_head_name() in ('System`Plus', 'System`Times',
                                  'System`Power') or \
                'System`Constant' in n.get_attributes(evaluation.definitions):
            # TODO: Factor out this check for dsvar into a separate
            # function. DSolve uses this too.
            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  # noqa
                        len(left.leaves) == 1 and isinstance(
                            l.leaves[0].to_python(), int) and r.is_numeric()):

                    r_sympy = r.to_sympy()
                    if r_sympy is None:
                        raise ValueError
                    conditions[l.leaves[0].to_python()] = r_sympy
                    return False
            return True

        # evaluate is_relation on all leaves to store conditions
        try:
            relations = [leaf for leaf in eqns.leaves if is_relation(leaf)]
        except ValueError:
            return
        relation = relations[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()]))
        if sym_eq is None:
            return
        sym_n = sympy.core.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:
            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
                ])
예제 #2
0
    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() != 'System`Equal':
                evaluation.message('RSolve', 'deqn', eqn)
                return

        if (n.is_atom() and not n.is_symbol()) or \
            n.get_head_name() in ('System`Plus', 'System`Times',
                                  'System`Power') or \
                'System`Constant' in n.get_attributes(evaluation.definitions):
            # TODO: Factor out this check for dsvar into a separate
            # function. DSolve uses this too.
            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    # noqa
                    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:
            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])
예제 #3
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])
예제 #4
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")  # nopep8
            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:
            evaluation.message("DSolve", "symimp")
            return
        except NotImplementedError:
            evaluation.message("DSolve", "symimp")
            return
        except AttributeError:
            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
                ]
            )
예제 #5
0
파일: diffeqns.py 프로젝트: raulcd/Mathics
    def apply(self, eqn, y, x, evaluation):
        'DSolve[eqn_, y_, x_]'

        if eqn.has_form('List', None):
            # 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() != 'System`Equal':
            evaluation.message('DSolve', 'deqn', eqn)
            return

        if x.is_symbol():
            syms = [x]
        elif x.has_form('List', 1, None):
            syms = sorted(x.get_leaves())
        else:
            return evaluation.message('DSolve', 'dsvar', x)

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

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

        if set(func.leaves) != set(syms):
            evaluation.message('DSolve', 'deqx')
            return

        f_name = func.get_head_name()

        conversion_args = {'converted_functions': set([f_name])}
        sym_func = func.to_sympy(**conversion_args)
        sym_eq = eqn.to_sympy(**conversion_args)

        # XXX when sympy adds support for higher-order PDE we will have to
        # change this to a tuple of solvefuns
        kwargs = {'solvefun': sympy.Function(str('C1'))}

        try:
            if len(syms) > 1:
                sym_result = sympy.pdsolve(sym_eq, sym_func, **kwargs)
            else:
                sym_result = sympy.dsolve(sym_eq, sym_func)
        except ValueError:
            evaluation.message('DSolve', 'symimp')
            return
        except NotImplementedError:
            evaluation.message('DSolve', 'symimp')
            return
        except TypeError:
            # Sympy bug #9446
            evaluation.message('DSolve', 'litarg', eqn)
            return
        except AttributeError:
            evaluation.message('DSolve', 'litarg', eqn)
            return
        except KeyError:
            evaluation.message('DSolve', 'litarg', eqn)
            return
        else:
            if not isinstance(sym_result, list):
                sym_result = [sym_result]

        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
                ])
예제 #6
0
    def apply(self, eqn, y, x, evaluation):
        'DSolve[eqn_, y_, x_]'

        if eqn.has_form('List', None):
            # 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() != 'System`Equal':
            evaluation.message('DSolve', 'deqn', eqn)
            return

        if x.is_symbol():
            syms = [x]
        elif x.has_form('List', 1, None):
            syms = x.get_leaves()
        else:
            return evaluation.message('DSolve', 'dsvar', x)

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

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

        if set(func.leaves) != set(syms):
            evaluation.message('DSolve', 'deqx')
            return

        # Workaround sympy bug #11669.
        # https://github.com/sympy/sympy/issues/11669https://github.com/sympy/sympy/issues/11669
        f_name = func.get_head_name()
        if six.PY2:
            try:
                f_name = str(f_name)
            except UnicodeEncodeError:
                return evaluation.message('DSolve', 'sym11669', func.get_head_name())

        conversion_args = {'converted_functions': set([f_name])}
        sym_func = func.to_sympy(**conversion_args)
        sym_eq = eqn.to_sympy(**conversion_args)

        # XXX when sympy adds support for higher-order PDE we will have to
        # change this to a tuple of solvefuns
        kwargs = {'solvefun': sympy.Function(str('C1'))}

        try:
            if len(syms) > 1:
                sym_result = sympy.pdsolve(sym_eq, sym_func, **kwargs)
            else:
                sym_result = sympy.dsolve(sym_eq, sym_func)
        except ValueError:
            evaluation.message('DSolve', 'symimp')
            return
        except NotImplementedError:
            evaluation.message('DSolve', 'symimp')
            return
        except TypeError:
            # Sympy bug #9446
            evaluation.message('DSolve', 'litarg', eqn)
            return
        except AttributeError:
            evaluation.message('DSolve', 'litarg', eqn)
            return
        except KeyError:
            evaluation.message('DSolve', 'litarg', eqn)
            return
        else:
            if not isinstance(sym_result, list):
                sym_result = [sym_result]

        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])