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