def testInverseConversions(self): # check that a conversion A -> B -> A restores the original # components. this tests color space transformations and their # inverse transformations. def space_to_head(name): if name == "HSB": return "System`Hue" else: return "System`%sColor" % name spaces = ("CMYK", "HSB", "LAB", "LCH", "LUV", "RGB", "XYZ") places = 3 for original in ((0.5, 0.1, 0.2), (0.9, 0.1, 0.1)): for i, from_space in enumerate(spaces): for to_space in spaces[i + 1:]: try: construct_name = space_to_head(from_space) source_color = Expression(construct_name, *original) # now calculate from_space -> to_space -> from_space target_color = Expression("ColorConvert", source_color, to_space).evaluate( self.evaluation) self.assertEqual(target_color.get_head_name(), space_to_head(to_space)) checked_color = Expression( "ColorConvert", target_color, from_space).evaluate(self.evaluation) self.assertEqual(checked_color.get_head_name(), source_color.get_head_name()) checked_components = [ c.to_python() for c in checked_color.leaves ] if from_space == "CMYK": # if cmyk, cmyk -> cmy k = checked_components[3] checked_components = [ c * (1 - k) + k for c in checked_components[:3] ] self.assertEqual(len(original), len(checked_components)) for x, y in zip(original, checked_components): self.assertAlmostEqual(x, y, places) except: print("test failed for %s -> %s -> %s" % ( _color_string(from_space, original), to_space, from_space, )) raise
def init(self, graphics, style, item): if len(item.leaves) == 3: arc_expr = item.leaves[2] if arc_expr.get_head_name() != "System`List": raise BoxConstructError arc = arc_expr.leaves pi2 = 2 * pi start_angle = arc[0].round_to_float() end_angle = arc[1].round_to_float() if start_angle is None or end_angle is None: raise BoxConstructError elif end_angle >= start_angle + pi2: # full circle? self.arc = None else: if end_angle <= start_angle: self.arc = (end_angle, start_angle) else: self.arc = (start_angle, end_angle) item = Expression(item.get_head_name(), *item.leaves[:2]) else: self.arc = None super(_ArcBox, self).init(graphics, style, item)
def get_results(tmp_function): if function_channels == Expression('List', String('FileNames')): joined_options = list(chain(stream_options, custom_options)) tmp = Expression(tmp_function, findfile, *joined_options).evaluate(evaluation) elif function_channels == Expression('List', String('Streams')): stream = Expression('OpenRead', findfile, *stream_options).evaluate(evaluation) if stream.get_head_name() != 'System`InputStream': evaluation.message('Import', 'nffil') return None tmp = Expression(tmp_function, stream, *custom_options).evaluate(evaluation) Expression('Close', stream).evaluate(evaluation) else: # TODO message return Symbol('$Failed') tmp = tmp.get_leaves() if not all(expr.has_form('Rule', None) for expr in tmp): return None # return {a.get_string_value() : b for (a,b) in map(lambda x: # x.get_leaves(), tmp)} return dict((a.get_string_value(), b) for (a, b) in [x.get_leaves() for x in tmp])
def apply_any(self, args, evaluation, options): "DateObject[args_, OptionsPattern[]]" datelist = None tz = None if isinstance(args, Expression): if args.get_head_name() in ("System`Rule", "System`DelayedRule"): options[args.leaves[0].get_name()] = args.leaves[1] args = Expression("AbsoluteTime").evaluate(evaluation) elif args.get_head_name() == "System`DateObject": datelist = args._leaves[0] tz = args._leaves[3] if datelist is None: datelist = self.to_datelist(args, evaluation) tz = Real(-time.timezone / 3600.0) if datelist is None: return fmt = None if options["System`TimeZone"].sameQ(Symbol("Automatic")): timezone = Real(-time.timezone / 3600.0) else: timezone = options["System`TimeZone"].evaluate(evaluation) if not timezone.is_numeric(evaluation): evaluation.message("DateObject", "notz", timezone) # TODO: if tz != timezone, shift the datetime list. if not tz == timezone: dt = timezone.to_python() - tz.to_python() if len(datelist) > 3: newhour = datelist[3] + dt datelist = datelist[:3] + [newhour] + datelist[4:] epoch = Symbol("Eternity") if datelist[-1] == 0: for i in range(len(datelist)): if datelist[-1 - i] != 0: datelist = datelist[:-i] epoch = self.granularities[-i - 1] break else: epoch = Symbol("Instant") fmt = options["System`DateFormat"] if len(datelist) < 6: datelist = [Integer(d) for d in datelist] else: datelist = [Integer(d) for d in datelist[:5]] + [Real(datelist[5])] return Expression( "DateObject", datelist, epoch, Symbol("Gregorian"), timezone, fmt, )
def testInverseConversions(self): # check that a conversion A -> B -> A restores the original # components. this tests color space transformations and their # inverse transformations. def space_to_head(name): if name == 'HSB': return 'System`Hue' else: return 'System`%sColor' % name spaces = ("CMYK", "HSB", "LAB", "LCH", "LUV", "RGB", "XYZ") places = 3 for original in ((0.5, 0.1, 0.2), (0.9, 0.1, 0.1)): for i, from_space in enumerate(spaces): for to_space in spaces[i + 1:]: try: construct_name = space_to_head(from_space) source_color = Expression(construct_name, *original) # now calculate from_space -> to_space -> from_space target_color = Expression('ColorConvert', source_color, to_space).evaluate(self.evaluation) self.assertEqual(target_color.get_head_name(), space_to_head(to_space)) checked_color = Expression('ColorConvert', target_color, from_space).evaluate(self.evaluation) self.assertEqual(checked_color.get_head_name(), source_color.get_head_name()) checked_components = [c.to_python() for c in checked_color.leaves] if from_space == 'CMYK': # if cmyk, cmyk -> cmy k = checked_components[3] checked_components = [c * (1 - k) + k for c in checked_components[:3]] self.assertEqual(len(original), len(checked_components)) for x, y in zip(original, checked_components): self.assertAlmostEqual(x, y, places) except: print('test failed for %s -> %s -> %s' % (_color_string(from_space, original), to_space, from_space)) raise
def apply_3(self, f, optvals, optname, evaluation): "OptionValue[f_, optvals_, optname_]" if type(optname) is String: name = optname.to_python()[1:-1] else: name = optname.get_name() if not name: name = optname.get_string_value() if name: name = ensure_context(name) if not name: evaluation.message("OptionValue", "sym", optname, 1) return # Look first in the explicit list if optvals: val = get_option(optvals.get_option_values(evaluation), name, evaluation) else: val = None # then, if not found, look at $f$. It could be a symbol, or a list of symbols, rules, and list of rules... if val is None: if f.is_symbol(): val = get_option( evaluation.definitions.get_options(f.get_name()), name, evaluation) else: if f.get_head_name() in ("System`Rule", "System`RuleDelayed"): f = Expression("List", f) if f.get_head_name() == "System`List": for leave in f.get_leaves(): if leave.is_symbol(): val = get_option( evaluation.definitions.get_options( leave.get_name()), name, evaluation, ) if val: break else: values = leave.get_option_values(evaluation) val = get_option(values, name, evaluation) if val: break if val is None and evaluation.options: val = get_option(evaluation.options, name, evaluation) if val is None: evaluation.message("OptionValue", "optnf", optname) return Symbol(name) return val
def add(self, expression, evaluation): expr = Expression('System`Private`ManipulateParameter', expression).evaluate(evaluation) if expr.get_head_name() != 'System`List': # if everything was parsed ok, we get a List return False # convert the rules given us by ManipulateParameter[] into a dict. note: duplicate keys # will be overwritten, the latest one wins. kwargs = {'evaluation': evaluation} for rule in expr.leaves: if rule.get_head_name() != 'System`Rule' or len(rule.leaves) != 2: return False kwargs[strip_context(rule.leaves[0].to_python()).lower()] = rule.leaves[1] widget = kwargs['type'].get_string_value() del kwargs['type'] getattr(self, '_add_%s_widget' % widget.lower())(**kwargs) # create the widget return True
def get_results(tmp_function, findfile): if function_channels == Expression('List', String('FileNames')): joined_options = list(chain(stream_options, custom_options)) tmpfile = False if findfile is None: tmpfile = True stream = Expression('OpenWrite').evaluate(evaluation) findfile = stream.leaves[0] if not data is None: Expression('WriteString', data).evaluate(evaluation) else: Expression('WriteString', String("")).evaluate(evaluation) Expression('Close', stream).evaluate(evaluation) stream = None tmp = Expression(tmp_function, findfile, *joined_options).evaluate(evaluation) if tmpfile: Expression("DeleteFile", findfile).evaluate(evaluation) elif function_channels == Expression('List', String('Streams')): if findfile is None: stream = Expression('StringToStream', data).evaluate(evaluation) else: stream = Expression('OpenRead', findfile, *stream_options).evaluate(evaluation) if stream.get_head_name() != 'System`InputStream': evaluation.message('Import', 'nffil') evaluation.predetermined_out = current_predetermined_out return None tmp = Expression(tmp_function, stream, *custom_options).evaluate(evaluation) Expression('Close', stream).evaluate(evaluation) else: # TODO message evaluation.predetermined_out = current_predetermined_out return Symbol('$Failed') tmp = tmp.get_leaves() if not all(expr.has_form('Rule', None) for expr in tmp): evaluation.predetermined_out = current_predetermined_out return None # return {a.get_string_value() : b for (a,b) in map(lambda x: # x.get_leaves(), tmp)} evaluation.predetermined_out = current_predetermined_out return dict((a.get_string_value(), b) for (a, b) in [x.get_leaves() for x in tmp])
def get_results(tmp_function): if function_channels == Expression('List', String('FileNames')): tmp = Expression(tmp_function, findfile).evaluate(evaluation) elif function_channels == Expression('List', String('Streams')): stream = Expression('OpenRead', findfile).evaluate(evaluation) if stream.get_head_name() != 'InputStream': evaluation.message('Import', 'nffil') return None tmp = Expression(tmp_function, stream).evaluate(evaluation) Expression('Close', stream).evaluate(evaluation) else: #TODO print appropriate error message raise NotImplementedError tmp = tmp.get_leaves() if not all(expr.has_form('Rule', None) for expr in tmp): return None # return {a.get_string_value() : b for (a,b) in map(lambda x: x.get_leaves(), tmp)} return dict((a.get_string_value(), b) for (a,b) in map(lambda x: x.get_leaves(), tmp))
def apply(self, l, f, evaluation): "SortBy[l_, f_]" if l.is_atom(): return evaluation.message("Sort", "normal") elif l.get_head_name() != "System`List": expr = Expression("SortBy", l, f) return evaluation.message(self.get_name(), "list", expr, 1) else: keys_expr = Expression("Map", f, l).evaluate(evaluation) # precompute: # even though our sort function has only (n log n) comparisons, we should # compute f no more than n times. if ( keys_expr is None or keys_expr.get_head_name() != "System`List" or len(keys_expr.leaves) != len(l.leaves) ): expr = Expression("SortBy", l, f) return evaluation.message("SortBy", "func", expr, 2) keys = keys_expr.leaves raw_keys = l.leaves class Key(object): def __init__(self, index): self.index = index def __gt__(self, other): kx, ky = keys[self.index], keys[other.index] if kx > ky: return True elif kx < ky: return False else: # if f(x) == f(y), resort to x < y? return raw_keys[self.index] > raw_keys[other.index] # we sort a list of indices. after sorting, we reorder the leaves. new_indices = sorted(list(range(len(raw_keys))), key=Key) new_leaves = [raw_keys[i] for i in new_indices] # reorder leaves return l.restructure(l.head, new_leaves, evaluation)
def get_results(tmp_function): if function_channels == Expression('List', String('FileNames')): tmp = Expression(tmp_function, findfile).evaluate(evaluation) elif function_channels == Expression('List', String('Streams')): stream = Expression('OpenRead', findfile).evaluate(evaluation) if stream.get_head_name() != 'System`InputStream': evaluation.message('Import', 'nffil') return None tmp = Expression(tmp_function, stream).evaluate(evaluation) Expression('Close', stream).evaluate(evaluation) else: # TODO message return Symbol('$Failed') tmp = tmp.get_leaves() if not all(expr.has_form('Rule', None) for expr in tmp): return None # return {a.get_string_value() : b for (a,b) in map(lambda x: # x.get_leaves(), tmp)} return dict((a.get_string_value(), b) for (a, b) in [x.get_leaves() for x in tmp])
def apply(self, l, f, evaluation): 'SortBy[l_, f_]' if l.is_atom(): return evaluation.message('Sort', 'normal') elif l.get_head_name() != 'System`List': expr = Expression('SortBy', l, f) return evaluation.message(self.get_name(), 'list', expr, 1) else: keys_expr = Expression('Map', f, l).evaluate(evaluation) # precompute: # even though our sort function has only (n log n) comparisons, we should # compute f no more than n times. if keys_expr is None or keys_expr.get_head_name() != 'System`List'\ or len(keys_expr.leaves) != len(l.leaves): expr = Expression('SortBy', l, f) return evaluation.message('SortBy', 'func', expr, 2) keys = keys_expr.leaves raw_keys = l.leaves class Key(object): def __init__(self, index): self.index = index def __gt__(self, other): kx, ky = keys[self.index], keys[other.index] if kx > ky: return True elif kx < ky: return False else: # if f(x) == f(y), resort to x < y? return raw_keys[self.index] > raw_keys[other.index] # we sort a list of indices. after sorting, we reorder the leaves. new_indices = sorted(list(range(len(raw_keys))), key=Key) new_leaves = [raw_keys[i] for i in new_indices] # reorder leaves return Expression(l.head, *new_leaves)
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, 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_elements(self, filename, expr, elems, evaluation, options={}): "Export[filename_, expr_, elems_List?(AllTrue[#, NotOptionQ]&), OptionsPattern[]]" # Check filename if not self._check_filename(filename, evaluation): return Symbol('$Failed') # Process elems {comp* format?, elem1*} leaves = elems.get_leaves() format_spec, elems_spec = [], [] found_form = False for leaf in leaves[::-1]: leaf_str = leaf.get_string_value() if not found_form and leaf_str in EXPORTERS: found_form = True if found_form: format_spec.append(leaf_str) else: elems_spec.append(leaf) # Just to be sure that the following calls do not change the state of this property current_predetermined_out = evaluation.predetermined_out # Infer format if not present if not found_form: assert format_spec == [] format_spec = self._infer_form(filename, evaluation) if format_spec is None: evaluation.message('Export', 'infer', filename) evaluation.predetermined_out = current_predetermined_out return Symbol('$Failed') format_spec = [format_spec] else: assert format_spec != [] # First item in format_spec is the explicit format. # The other elements (if present) are compression formats if elems_spec != []: # FIXME: support elems evaluation.message('Export', 'noelem', elems, String(format_spec[0])) evaluation.predetermined_out = current_predetermined_out return Symbol('$Failed') # Load the exporter exporter_symbol, exporter_options = EXPORTERS[format_spec[0]] function_channels = exporter_options.get("System`FunctionChannels") stream_options, custom_options = _importer_exporter_options( exporter_options.get("System`Options"), options, evaluation) if function_channels is None: evaluation.message('Export', 'emptyfch') evaluation.predetermined_out = current_predetermined_out return Symbol('$Failed') elif function_channels == Expression('List', String('FileNames')): exporter_function = Expression( exporter_symbol, filename, expr, *list(chain(stream_options, custom_options))) res = exporter_function.evaluate(evaluation) elif function_channels == Expression('List', String('Streams')): stream = Expression('OpenWrite', filename, *stream_options).evaluate(evaluation) if stream.get_head_name() != 'System`OutputStream': evaluation.message('Export', 'nffil') evaluation.predetermined_out = current_predetermined_out return Symbol("$Failed") exporter_function = Expression( exporter_symbol, stream, expr, *list(chain(stream_options, custom_options))) res = exporter_function.evaluate(evaluation) Expression('Close', stream).evaluate(evaluation) if res == Symbol('Null'): evaluation.predetermined_out = current_predetermined_out return filename evaluation.predetermined_out = current_predetermined_out return Symbol('$Failed')
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])