def apply(self, expr, evaluation): 'Dimensions[expr_]' return Expression('List', *(Integer(dim) for dim in get_dimensions(expr)))
def apply_phi0(self, phi0, steps, evaluation): "AnglePath[phi0_, {steps___}]" return AnglePath._compute(Integer(0), Integer(0), phi0, steps.get_sequence(), evaluation)
def set_config_value(self, name, new_value): from mathics.core.expression import Integer self.definitions.set_ownvalue(name, Integer(new_value))
def apply(self, text, evaluation, options): 'WordCount[text_String, OptionsPattern[%(name)s]]' doc = self._nlp(text.get_string_value(), evaluation, options) if doc: punctuation = spacy.parts_of_speech.PUNCT return Integer(sum(1 for word in doc if word.pos != punctuation))
class Evaluation(object): def __init__(self, input=None, definitions=None, timeout=None, out_callback=None, format='text', catch_interrupt=True): from mathics.core.definitions import Definitions if definitions is None: definitions = Definitions() self.definitions = definitions self.recursion_depth = 0 self.timeout = False self.stopped = False self.out = [] self.out_callback = out_callback self.listeners = {} self.options = None self.quiet_all = False self.quiet_messages = set() self.format = format queries = [] last_parse_error = None if input is not None: from mathics.core.parser import parse, TranslateError lines = input.splitlines() query = '' for line in lines: if line: query += line try: expression = parse(query, self.definitions) if expression is not None: queries.append(expression) query = '' last_parse_error = None except TranslateError, exc: last_parse_error = exc else: query += ' ' self.results = [] for query in queries: self.recursion_depth = 0 self.timeout = False self.stopped = False from mathics.core.expression import Symbol, Expression, Integer from mathics.core.rules import Rule line_no = self.get_config_value('$Line', 0) line_no += 1 self.definitions.set_ownvalue('$Line', Integer(line_no)) history_length = self.get_config_value('$HistoryLength', 100) if history_length is None or history_length > 100: history_length = 100 def evaluate(): if history_length > 0: self.definitions.add_rule( 'In', Rule(Expression('In', line_no), query)) result = query.evaluate(self) if history_length > 0: stored_result = self.get_stored_result(result) self.definitions.add_rule( 'Out', Rule(Expression('Out', line_no), stored_result)) if result != Symbol('Null'): return self.format_output(result) else: return None try: result = None exc_result = None try: if timeout is None: result = evaluate() else: with interruptingcow.timeout(timeout, TimeoutInterrupt): result = evaluate() except KeyboardInterrupt: if catch_interrupt: exc_result = Symbol('$Aborted') else: raise except ValueError, exc: text = unicode(exc) if (text == 'mpz.pow outrageous exponent' or # noqa text == 'mpq.pow outrageous exp num'): self.message('General', 'ovfl') exc_result = Expression('Overflow') else: raise except OverflowError: self.message('General', 'ovfl') exc_result = Expression('Overflow') except BreakInterrupt: self.message('Break', 'nofdw') exc_result = Expression('Hold', Expression('Break')) except ContinueInterrupt: self.message('Continue', 'nofdw') exc_result = Expression('Hold', Expression('Continue')) except TimeoutInterrupt: self.stopped = False self.timeout = True self.message('General', 'timeout') exc_result = Symbol('$Aborted') except AbortInterrupt: # , error: exc_result = Symbol('$Aborted') if exc_result is not None: self.recursion_depth = 0 result = self.format_output(exc_result) self.results.append(Result(self.out, result, line_no)) self.out = [] finally:
def apply(self, expr, form, evaluation): 'Coefficient[expr_, form_]' return _coefficient(self.__class__.__name__, expr, form, Integer(1), evaluation)
SymbolUndefined, from_python, ) from mathics.core.convert import sympy_symbol_prefix, SympyExpression, from_sympy from mathics.core.rules import Pattern from mathics.core.numbers import dps from mathics.builtin.scoping import dynamic_scoping from mathics.builtin.numeric import apply_N from mathics import Symbol import sympy SymbolPlus = Symbol("Plus") SymbolTimes = Symbol("Times") SymbolPower = Symbol("Power") IntegerZero = Integer(0) IntegerMinusOne = Integer(-1) class D(SympyFunction): """ <dl> <dt>'D[$f$, $x$]' <dd>gives the partial derivative of $f$ with respect to $x$. <dt>'D[$f$, $x$, $y$, ...]' <dd>differentiates successively with respect to $x$, $y$, etc. <dt>'D[$f$, {$x$, $n$}]' <dd>gives the multiple derivative of order $n$. <dt>'D[$f$, {{$x1$, $x2$, ...}}]' <dd>gives the vector derivative of $f$ with respect to $x1$, $x2$, etc. </dl>
def main(): argparser = argparse.ArgumentParser( prog='mathics', usage='%(prog)s [options] [FILE]', add_help=False, description="Mathics is a general-purpose computer algebra system.", epilog="""Please feel encouraged to contribute to Mathics! Create your own fork, make the desired changes, commit, and make a pull request.""") argparser.add_argument('FILE', nargs='?', type=argparse.FileType('r'), help='execute commands from FILE') argparser.add_argument('--help', '-h', help='show this help message and exit', action='help') argparser.add_argument( '--persist', help='go to interactive shell after evaluating FILE or -e', action='store_true') argparser.add_argument('--quiet', '-q', help='don\'t print message at startup', action='store_true') argparser.add_argument('-script', help='run a mathics file in script mode', action='store_true') argparser.add_argument( '--execute', '-e', action='append', metavar='EXPR', help='evaluate EXPR before processing any input files (may be given ' 'multiple times)') argparser.add_argument('--colors', nargs='?', help='interactive shell colors') argparser.add_argument('--no-completion', help="disable tab completion", action='store_true') argparser.add_argument( '--no-readline', help="disable line editing (implies --no-completion)", action='store_true') argparser.add_argument('--version', '-v', action='version', version=get_version_string(False)) args = argparser.parse_args() quit_command = 'CTRL-BREAK' if sys.platform == 'win32' else 'CONTROL-D' definitions = Definitions(add_builtin=True) definitions.set_ownvalue('$Line', Integer(0)) # Reset the line number shell = TerminalShell(definitions, args.colors, want_readline=not (args.no_readline), want_completion=not (args.no_completion)) if not (args.quiet or args.script): print_version(is_server=False) print_license() print u"Quit by pressing {0}\n".format(quit_command) if args.execute: for expr in args.execute: total_input = expr.decode(shell.input_encoding) print shell.get_in_prompt() + total_input shell.evaluate(total_input) if not args.persist: return if args.FILE is not None: total_input = '' for line_no, line in enumerate(args.FILE): try: line = line.decode('utf-8') # TODO: other encodings if args.script and line_no == 0 and line.startswith('#!'): continue print shell.get_in_prompt(continued=total_input != '') + line, total_input += ' ' + line if line != "" and wait_for_line(total_input): continue shell.evaluate(total_input) total_input = "" except (KeyboardInterrupt): print '\nKeyboardInterrupt' except (SystemExit, EOFError): print "\n\nGood bye!\n" break if not args.persist: return total_input = "" while True: try: line = shell.read_line( shell.get_in_prompt(continued=total_input != '')) line = line.decode(shell.input_encoding) total_input += line if line != "" and wait_for_line(total_input): continue shell.evaluate(total_input) total_input = "" except (KeyboardInterrupt): print '\nKeyboardInterrupt' except (SystemExit, EOFError): print "\n\nGood bye!\n" break
def apply(self, expr, form, evaluation): 'CoefficientList[expr_, form_]' vars = [form] if not form.has_form('List', None) else [ v for v in form.leaves ] # check form is not a variable for v in vars: if not (isinstance(v, Symbol)) and not (isinstance(v, Expression)): return evaluation.message('CoefficientList', 'ivar', v) # special cases for expr and form e_null = expr == Symbol('Null') f_null = form == Symbol('Null') if expr == Integer(0): return Expression('List') elif e_null and f_null: return Expression('List', Integer(0), Integer(0)) elif e_null and not f_null: return Expression('List', Symbol('Null')) elif f_null: return Expression('List', expr) elif form.has_form('List', 0): return expr sympy_expr = expr.to_sympy() sympy_vars = [v.to_sympy() for v in vars] if not sympy_expr.is_polynomial(*[x for x in sympy_vars]): return evaluation.message('CoefficientList', 'poly', expr) try: sympy_poly, sympy_opt = sympy.poly_from_expr( sympy_expr, sympy_vars) dimensions = [ sympy_poly.degree(x) if x in sympy_poly.gens else 0 for x in sympy_vars ] # single & multiple variables cases if not form.has_form('List', None): return Expression( 'List', *[ _coefficient(self.__class__.__name__, expr, form, Integer(n), evaluation) for n in range(dimensions[0] + 1) ]) elif form.has_form('List', 1): form = form.leaves[0] return Expression( 'List', *[ _coefficient(self.__class__.__name__, expr, form, Integer(n), evaluation) for n in range(dimensions[0] + 1) ]) else: def _nth(poly, dims, exponents): if not dims: return from_sympy(poly.nth(*[i for i in exponents])) result = Expression('List') first_dim = dims[0] for i in range(first_dim + 1): exponents.append(i) subs = _nth(poly, dims[1:], exponents) result.leaves.append(subs) exponents.pop() return result return _nth(sympy_poly, dimensions, []) except sympy.PolificationFailed: return evaluation.message('CoefficientList', 'poly', expr)
def apply_novar(self, expr, evaluation): 'Exponent[expr_]' return evaluation.message('Exponent', 'argtu', Integer(1))
def to_sympy(self, expr, **kwargs): if len(expr.leaves) == 1: return Expression('ArcSinh', Expression('Power', expr.leaves[0], Integer(-1))).to_sympy()
def contribute(self, definitions, is_pymodule=False): from mathics.core.parser import parse_builtin_rule if is_pymodule: name = "PyMathics`" + self.get_name(short=True) else: name = self.get_name() options = {} option_syntax = "Warn" for option, value in self.options.items(): if option == "$OptionSyntax": option_syntax = value continue option = ensure_context(option) options[option] = parse_builtin_rule(value) if option.startswith("System`"): # Create a definition for the option's symbol. # Otherwise it'll be created in Global` when it's # used, so it won't work. if option not in definitions.builtin: definitions.builtin[option] = Definition(name=name, attributes=set()) # Check if the given options are actually supported by the Builtin. # If not, we might issue an optx error and abort. Using '$OptionSyntax' # in your Builtin's 'options', you can specify the exact behaviour # using one of the following values: # - 'Strict': warn and fail with unsupported options # - 'Warn': warn about unsupported options, but continue # - 'Ignore': allow unsupported options, do not warn if option_syntax in ("Strict", "Warn", "System`Strict", "System`Warn"): def check_options(options_to_check, evaluation): name = self.get_name() for key, value in options_to_check.items(): short_key = strip_context(key) if not has_option(options, short_key, evaluation): evaluation.message( name, "optx", Expression("Rule", short_key, value), strip_context(name), ) if option_syntax in ("Strict", "System`Strict"): return False return True elif option_syntax in ("Ignore", "System`Ignore"): check_options = None else: raise ValueError("illegal option mode %s; check $OptionSyntax." % option_syntax) rules = [] definition_class = (PyMathicsDefinitions() if is_pymodule else SystemDefinitions()) for pattern, function in self.get_functions(is_pymodule=is_pymodule): rules.append( BuiltinRule(name, pattern, function, check_options, system=not is_pymodule)) for pattern, replace in self.rules.items(): if not isinstance(pattern, BaseExpression): pattern = pattern % {"name": name} pattern = parse_builtin_rule(pattern, definition_class) replace = replace % {"name": name} # FIXME: Should system=True be system=not is_pymodule ? rules.append( Rule(pattern, parse_builtin_rule(replace), system=True)) box_rules = [] if name != "System`MakeBoxes": new_rules = [] for rule in rules: if rule.pattern.get_head_name() == "System`MakeBoxes": box_rules.append(rule) else: new_rules.append(rule) rules = new_rules def extract_forms(name, pattern): # Handle a tuple of (forms, pattern) as well as a pattern # on the left-hand side of a format rule. 'forms' can be # an empty string (=> the rule applies to all forms), or a # form name (like 'System`TraditionalForm'), or a sequence # of form names. def contextify_form_name(f): # Handle adding 'System`' to a form name, unless it's # '' (meaning the rule applies to all forms). return "" if f == "" else ensure_context(f) if isinstance(pattern, tuple): forms, pattern = pattern if isinstance(forms, str): forms = [contextify_form_name(forms)] else: forms = [contextify_form_name(f) for f in forms] else: forms = [""] return forms, pattern formatvalues = {"": []} for pattern, function in self.get_functions("format_"): forms, pattern = extract_forms(name, pattern) for form in forms: if form not in formatvalues: formatvalues[form] = [] formatvalues[form].append( BuiltinRule(name, pattern, function, None, system=True)) for pattern, replace in self.formats.items(): forms, pattern = extract_forms(name, pattern) for form in forms: if form not in formatvalues: formatvalues[form] = [] if not isinstance(pattern, BaseExpression): pattern = pattern % {"name": name} pattern = parse_builtin_rule(pattern) replace = replace % {"name": name} formatvalues[form].append( Rule(pattern, parse_builtin_rule(replace), system=True)) for form, formatrules in formatvalues.items(): formatrules.sort() messages = [ Rule( Expression("MessageName", Symbol(name), String(msg)), String(value), system=True, ) for msg, value in self.messages.items() ] messages.append( Rule( Expression("MessageName", Symbol(name), String("optx")), String("`1` is not a supported option for `2`[]."), system=True, )) if "Unprotected" in self.attributes: attributes = [] self.attributes = list(self.attributes) self.attributes.remove("Unprotected") else: attributes = ["System`Protected"] attributes += list(ensure_context(a) for a in self.attributes) options = {} for option, value in self.options.items(): option = ensure_context(option) options[option] = parse_builtin_rule(value) if option.startswith("System`"): # Create a definition for the option's symbol. # Otherwise it'll be created in Global` when it's # used, so it won't work. if option not in definitions.builtin: definitions.builtin[option] = Definition(name=name, attributes=set()) defaults = [] for spec, value in self.defaults.items(): value = parse_builtin_rule(value) pattern = None if spec is None: pattern = Expression("Default", Symbol(name)) elif isinstance(spec, int): pattern = Expression("Default", Symbol(name), Integer(spec)) if pattern is not None: defaults.append(Rule(pattern, value, system=True)) definition = Definition( name=name, rules=rules, formatvalues=formatvalues, messages=messages, attributes=attributes, options=options, defaultvalues=defaults, ) if is_pymodule: definitions.pymathics[name] = definition else: definitions.builtin[name] = definition makeboxes_def = definitions.builtin["System`MakeBoxes"] for rule in box_rules: makeboxes_def.add_rule(rule)
def prepare_sympy(self, leaves): if leaves[1] == Integer(0): return leaves[:1] + leaves[2:] return leaves
def apply(self, items, evaluation): 'Times[items___]' items = items.numerify(evaluation).get_sequence() leaves = [] numbers = [] prec = min_prec(*items) is_machine_precision = any(item.is_machine_precision() for item in items) # find numbers and simplify Times -> Power for item in items: if isinstance(item, Number): numbers.append(item) elif leaves and item == leaves[-1]: leaves[-1] = Expression('Power', leaves[-1], Integer(2)) elif (leaves and item.has_form('Power', 2) and leaves[-1].has_form('Power', 2) and item.leaves[0].same(leaves[-1].leaves[0])): leaves[-1].leaves[1] = Expression( 'Plus', item.leaves[1], leaves[-1].leaves[1]) elif (leaves and item.has_form('Power', 2) and item.leaves[0].same(leaves[-1])): leaves[-1] = Expression( 'Power', leaves[-1], Expression('Plus', item.leaves[1], Integer(1))) elif (leaves and leaves[-1].has_form('Power', 2) and leaves[-1].leaves[0].same(item)): leaves[-1] = Expression('Power', item, Expression( 'Plus', Integer(1), leaves[-1].leaves[1])) else: leaves.append(item) if numbers: if prec is not None: if is_machine_precision: numbers = [item.to_mpmath() for item in numbers] number = mpmath.fprod(numbers) number = Number.from_mpmath(number) else: with mpmath.workprec(prec): numbers = [item.to_mpmath() for item in numbers] number = mpmath.fprod(numbers) number = Number.from_mpmath(number, dps(prec)) else: number = sympy.Mul(*[item.to_sympy() for item in numbers]) number = from_sympy(number) else: number = Integer(1) if number.same(Integer(1)): number = None elif number.is_zero: return number elif number.same(Integer(-1)) and leaves and leaves[0].has_form('Plus', None): leaves[0].leaves = [Expression('Times', Integer(-1), leaf) for leaf in leaves[0].leaves] number = None for leaf in leaves: leaf.last_evaluated = None if number is not None: leaves.insert(0, number) if not leaves: return Integer(1) elif len(leaves) == 1: return leaves[0] else: return Expression('Times', *leaves)
def find_root_secant(f, x0, x, opts, evaluation) -> (Number, bool): region = opts.get("$$Region", None) if not type(region) is list: if x0.is_zero: region = (Real(-1), Real(1)) else: xmax = 2 * x0.to_python() xmin = -2 * x0.to_python() if xmin > xmax: region = (Real(xmax), Real(xmin)) else: region = (Real(xmin), Real(xmax)) maxit = opts["System`MaxIterations"] x_name = x.get_name() if maxit.sameQ(Symbol("Automatic")): maxit = 100 else: maxit = maxit.evaluate(evaluation).get_int_value() x0 = from_python(region[0]) x1 = from_python(region[1]) f0 = dynamic_scoping(lambda ev: f.evaluate(evaluation), {x_name: x0}, evaluation) f1 = dynamic_scoping(lambda ev: f.evaluate(evaluation), {x_name: x1}, evaluation) if not isinstance(f0, Number): return x0, False if not isinstance(f1, Number): return x0, False f0 = f0.to_python(n_evaluation=True) f1 = f1.to_python(n_evaluation=True) count = 0 while count < maxit: if f0 == f1: x1 = Expression( "Plus", x0, Expression( "Times", Real(0.75), Expression("Plus", x1, Expression("Times", Integer(-1), x0)), ), ) x1 = x1.evaluate(evaluation) f1 = dynamic_scoping(lambda ev: f.evaluate(evaluation), {x_name: x1}, evaluation) if not isinstance(f1, Number): return x0, False f1 = f1.to_python(n_evaluation=True) continue inv_deltaf = from_python(1.0 / (f1 - f0)) num = Expression( "Plus", Expression("Times", x0, f1), Expression("Times", x1, f0, Integer(-1)), ) x2 = Expression("Times", num, inv_deltaf) x2 = x2.evaluate(evaluation) f2 = dynamic_scoping(lambda ev: f.evaluate(evaluation), {x_name: x2}, evaluation) if not isinstance(f2, Number): return x0, False f2 = f2.to_python(n_evaluation=True) f1, f0 = f2, f1 x1, x0 = x2, x1 if x1 == x0 or abs(f2) == 0: break count = count + 1 else: evaluation.message("FindRoot", "maxiter") return x0, False return x0, True
def testNonAscii(self): self.check('z \\[Conjugate]', Expression('Conjugate', Symbol('Global`z'))) self.check('z \\[Transpose]', Expression('Transpose', Symbol('Global`z'))) self.check('z \\[ConjugateTranspose]', Expression('ConjugateTranspose', Symbol('Global`z'))) self.check('z \uf3c7 ', Expression('Transpose', Symbol('Global`z'))) self.check('z \uf3c8 ', Expression('Conjugate', Symbol('Global`z'))) self.check('z \uf3c9 ', Expression('ConjugateTranspose', Symbol('Global`z'))) self.check( '\\[Integral] x \\[DifferentialD] x', Expression('Integrate', Symbol('Global`x'), Symbol('Global`x'))) self.check('\\[Del] x', Expression('Del', Symbol('Global`x'))) self.check('\\[Square] x', Expression('Square', Symbol('Global`x'))) self.check('1 \\[SmallCircle] 2', Expression('SmallCircle', Integer(1), Integer(2))) self.check( '1 \\[SmallCircle] 2 \\[SmallCircle] 3', Expression('SmallCircle', Integer(1), Integer(2), Integer(3))) self.check('1 \u2218 2', Expression('SmallCircle', Integer(1), Integer(2))) self.check('1 \\[CircleDot] 2', Expression('CircleDot', Integer(1), Integer(2))) self.check('1 \u2299 2', Expression('CircleDot', Integer(1), Integer(2))) self.check('1 \\[Diamond] 2', Expression('Diamond', Integer(1), Integer(2))) self.check('1 \\[Wedge] 2', Expression('Wedge', Integer(1), Integer(2))) self.check('1 \\[Vee] 2', Expression('Vee', Integer(1), Integer(2))) self.check('1 \\[CircleTimes] 2', Expression('CircleTimes', Integer(1), Integer(2))) self.check('1 \\[CenterDot] 2', Expression('CenterDot', Integer(1), Integer(2))) self.check('1 \\[Star] 2', Expression('Star', Integer(1), Integer(2))) self.check('a \\[Cap] b', 'Cap[a,b]') self.check('a \\[Cup] b \\[Cup] c', 'Cup[a,b,c]') self.check('a \u2322 b \u2322 c', 'Cap[a,b,c]') self.check('a \u2323 b', 'Cup[a, b]') self.check('1 \u22C4 2', Expression('Diamond', Integer(1), Integer(2))) self.check('1 \u22C0 2', Expression('Wedge', Integer(1), Integer(2))) self.check('1 \u22c1 2', Expression('Vee', Integer(1), Integer(2))) self.check('1 \u2297 2', Expression('CircleTimes', Integer(1), Integer(2))) self.check('1 \u00B7 2', Expression('CenterDot', Integer(1), Integer(2))) self.check('1 \u22C6 2', Expression('Star', Integer(1), Integer(2))) self.check( 'expr1 ** expr2', Expression('NonCommutativeMultiply', Symbol('Global`expr1'), Symbol('Global`expr2'))) self.check( 'expr1 ** expr2 ** expr3', Expression('NonCommutativeMultiply', Symbol('Global`expr1'), Symbol('Global`expr2'), Symbol('Global`expr3'))) self.check('1 \\[Cross] 2', Expression('Cross', Integer(1), Integer(2))) self.check('1 \uf4a0 2', Expression('Cross', Integer(1), Integer(2))) self.check( '3\\[Divide]2', Expression('Times', Integer(3), Expression('Power', Integer(2), Integer(-1)))) self.check( '3 \u00f7 2', Expression('Times', Integer(3), Expression('Power', Integer(2), Integer(-1)))) self.check('3\\2', Expression('Backslash', Integer(3), Integer(2))) self.check('1 \\[Times] 2', Expression('Times', Integer(1), Integer(2))) self.check('1 \u00d7 2', Expression('Times', Integer(1), Integer(2))) self.check('1 \[PlusMinus] 2', Expression('PlusMinus', Integer(1), Integer(2))) self.check('1 \[MinusPlus] 2', Expression('MinusPlus', Integer(1), Integer(2))) self.check('\[PlusMinus] 1', Expression('PlusMinus', Integer(1))) self.check('\[MinusPlus] 1', Expression('MinusPlus', Integer(1))) self.check('\u00b1 1', Expression('PlusMinus', Integer(1))) self.check('\u2213 1', Expression('MinusPlus', Integer(1))) self.check('1 \\[And] 2', Expression('And', Integer(1), Integer(2))) self.check('1 \u2227 2', Expression('And', Integer(1), Integer(2))) self.check('1 \\[Or] 2', Expression('Or', Integer(1), Integer(2))) self.check('1 \u2228 2', Expression('Or', Integer(1), Integer(2))) self.check('a \\[Colon] b', Expression('Colon', Symbol('Global`a'), Symbol('Global`b'))) self.check('a \u2236 b', Expression('Colon', Symbol('Global`a'), Symbol('Global`b'))) self.check('x \\[Function] y', 'Function[{x}, y]') self.check('x \uf4a1 y', 'Function[{x}, y]') self.check('x1 \\[RightTee] x2', 'RightTee[x1, x2]') self.check('x1 \\[DoubleRightTee] x2', 'DoubleRightTee[x1, x2]') self.check('x1 \\[LeftTee] x2', 'LeftTee[x1, x2]') self.check('x1 \\[DoubleLeftTee] x2', 'DoubleLeftTee[x1, x2]')
def apply(self, f, x, evaluation): "D[f_, x_?NotListQ]" x_pattern = Pattern.create(x) if f.is_free(x_pattern, evaluation): return IntegerZero elif f == x: return Integer1 elif f.is_atom(): # Shouldn't happen 1 / 0 return # So, this is not an atom... head = f.get_head() if head == SymbolPlus: terms = [ Expression("D", term, x) for term in f.leaves if not term.is_free(x_pattern, evaluation) ] if len(terms) == 0: return IntegerZero return Expression(SymbolPlus, *terms) elif head == SymbolTimes: terms = [] for i, factor in enumerate(f.leaves): if factor.is_free(x_pattern, evaluation): continue factors = [leaf for j, leaf in enumerate(f.leaves) if j != i] factors.append(Expression("D", factor, x)) terms.append(Expression(SymbolTimes, *factors)) if len(terms) != 0: return Expression(SymbolPlus, *terms) else: return IntegerZero elif head == SymbolPower and len(f.leaves) == 2: base, exp = f.leaves terms = [] if not base.is_free(x_pattern, evaluation): terms.append( Expression( SymbolTimes, exp, Expression( SymbolPower, base, Expression(SymbolPlus, exp, IntegerMinusOne), ), Expression("D", base, x), )) if not exp.is_free(x_pattern, evaluation): if base.is_atom() and base.get_name() == "System`E": terms.append( Expression(SymbolTimes, f, Expression("D", exp, x))) else: terms.append( Expression( SymbolTimes, f, Expression("Log", base), Expression("D", exp, x), )) if len(terms) == 0: return IntegerZero elif len(terms) == 1: return terms[0] else: return Expression(SymbolPlus, *terms) elif len(f.leaves) == 1: if f.leaves[0] == x: return Expression( Expression(Expression("Derivative", Integer(1)), f.head), x) else: g = f.leaves[0] return Expression( SymbolTimes, Expression("D", Expression(f.head, g), g), Expression("D", g, x), ) else: # many leaves def summand(leaf, index): result = Expression( Expression( Expression( "Derivative", *([IntegerZero] * (index) + [Integer1] + [IntegerZero] * (len(f.leaves) - index - 1))), f.head, ), *f.leaves) if leaf.sameQ(x): return result else: return Expression("Times", result, Expression("D", leaf, x)) result = [ summand(leaf, index) for index, leaf in enumerate(f.leaves) if not leaf.is_free(x_pattern, evaluation) ] if len(result) == 1: return result[0] elif len(result) == 0: return IntegerZero else: return Expression("Plus", *result)
def apply_single(self, m, evaluation): 'Norm[m_]' return self.apply(m, Integer(2), evaluation)
def apply(self, n, evaluation): "BitLength[n_Integer]" n = n.get_int_value() if n < 0: n = -1 - n return Integer(n.bit_length())
def expand(expr, numer=True, denom=False, deep=False, **kwargs): if kwargs['modulus'] is not None and kwargs['modulus'] <= 0: return Integer(0) sub_exprs = [] def store_sub_expr(expr): sub_exprs.append(expr) result = sympy.Symbol(sympy_symbol_prefix + str(len(sub_exprs) - 1)) return result def get_sub_expr(expr): name = expr.get_name() assert isinstance(expr, Symbol) and name.startswith('System`') i = int(name[len('System`'):]) return sub_exprs[i] def convert_sympy(expr): "converts top-level to sympy" leaves = expr.get_leaves() if isinstance(expr, Integer): return sympy.Integer(expr.get_int_value()) if expr.has_form('Power', 2): # sympy won't expand `(a + b) / x` to `a / x + b / x` if denom is False # if denom is False we store negative powers to prevent this. n1 = leaves[1].get_int_value() if not denom and n1 is not None and n1 < 0: return store_sub_expr(expr) return sympy.Pow(*[convert_sympy(leaf) for leaf in leaves]) elif expr.has_form('Times', 2, None): return sympy.Mul(*[convert_sympy(leaf) for leaf in leaves]) elif expr.has_form('Plus', 2, None): return sympy.Add(*[convert_sympy(leaf) for leaf in leaves]) else: return store_sub_expr(expr) def unconvert_subexprs(expr): if expr.is_atom(): if isinstance(expr, Symbol): return get_sub_expr(expr) else: return expr else: return Expression(expr.head, *[unconvert_subexprs(leaf) for leaf in expr.get_leaves()]) sympy_expr = convert_sympy(expr) def _expand(expr): return expand(expr, numer=numer, denom=denom, deep=deep, **kwargs) if deep: # thread over everything for i, sub_expr,in enumerate(sub_exprs): if not sub_expr.is_atom(): head = _expand(sub_expr.head) # also expand head leaves = sub_expr.get_leaves() leaves = [_expand(leaf) for leaf in leaves] sub_exprs[i] = Expression(head, *leaves) else: # thread over Lists etc. threaded_heads = ('List', 'Rule') for i, sub_expr in enumerate(sub_exprs): for head in threaded_heads: if sub_expr.has_form(head, None): leaves = sub_expr.get_leaves() leaves = [_expand(leaf) for leaf in leaves] sub_exprs[i] = Expression(head, *leaves) break hints = { 'mul': True, 'multinomial': True, 'power_exp': False, 'power_base': False, 'basic': False, 'log': False, } hints.update(kwargs) if numer and denom: # don't expand fractions when modulus is True if hints['modulus'] is not None: hints['frac'] = True else: # setting both True doesn't expand denom hints['numer'] = numer hints['denom'] = denom sympy_expr = sympy_expr.expand(**hints) result = from_sympy(sympy_expr) result = unconvert_subexprs(result) return result
def callback(level, pos): return Expression(f, level, Expression('List', *(Integer(p) for p in pos)))
def evaluate(self, queries=[], timeout=None): 'evaluate a list of expressions' from mathics.core.expression import Symbol, Expression, Integer from mathics.core.rules import Rule results = [] for query in queries: self.recursion_depth = 0 self.timeout = False self.stopped = False line_no = self.get_config_value('$Line', 0) line_no += 1 self.definitions.set_ownvalue('$Line', Integer(line_no)) history_length = self.get_config_value('$HistoryLength', 100) if history_length is None or history_length > 100: history_length = 100 def evaluate(): if history_length > 0: self.definitions.add_rule( 'In', Rule(Expression('In', line_no), query)) result = query.evaluate(self) if history_length > 0: stored_result = self.get_stored_result(result) self.definitions.add_rule( 'Out', Rule(Expression('Out', line_no), stored_result)) if result != Symbol('Null'): return self.format_output(result) else: return None try: result = None exc_result = None try: result = run_with_timeout(evaluate, timeout) except KeyboardInterrupt: if self.catch_interrupt: exc_result = Symbol('$Aborted') else: raise except ValueError as exc: text = six.text_type(exc) if (text == 'mpz.pow outrageous exponent' or # noqa text == 'mpq.pow outrageous exp num'): self.message('General', 'ovfl') exc_result = Expression('Overflow') else: raise except OverflowError: self.message('General', 'ovfl') exc_result = Expression('Overflow') except BreakInterrupt: self.message('Break', 'nofdw') exc_result = Expression('Hold', Expression('Break')) except ContinueInterrupt: self.message('Continue', 'nofdw') exc_result = Expression('Hold', Expression('Continue')) except TimeoutInterrupt: self.stopped = False self.timeout = True self.message('General', 'timeout') exc_result = Symbol('$Aborted') except AbortInterrupt: # , error: exc_result = Symbol('$Aborted') if exc_result is not None: self.recursion_depth = 0 result = self.format_output(exc_result) results.append(Result(self.out, result, line_no)) self.out = [] finally: self.stop() history_length = self.get_config_value('$HistoryLength', 100) if history_length is None or history_length > 100: history_length = 100 line = line_no - history_length while line > 0: unset_in = self.definitions.unset('In', Expression('In', line)) unset_out = self.definitions.unset('Out', Expression('Out', line)) if not (unset_in or unset_out): break line -= 1 return results
def apply(self, m, n, evaluation): "%(name)s[n_Integer, m_Integer]" n_value = n.get_int_value() m_value = m.get_int_value() return Integer(stirling(n_value, m_value, kind=2))
def to_sympy(self, expr, **kwargs): if len(expr.leaves) == 1: return Expression("Power", Expression("Cosh", expr.leaves[0]), Integer(-1)).to_sympy()
def evaluate(self, evaluation): return Integer(self.value)
def from_sympy(expr): from mathics.builtin import sympy_to_mathics from mathics.core.expression import ( Symbol, Integer, Rational, Real, Complex, String, Expression, MachineReal, SymbolNull, ) from mathics.core.numbers import machine_precision if isinstance(expr, (tuple, list)): return Expression("List", *[from_sympy(item) for item in expr]) if isinstance(expr, int): return Integer(expr) if isinstance(expr, float): return Real(expr) if isinstance(expr, complex): return Complex(Real(expr.real), Real(expr.imag)) if isinstance(expr, str): return String(expr) if expr is None: return SymbolNull if isinstance(expr, sympy.Matrix) or isinstance(expr, sympy.ImmutableMatrix): if len(expr.shape) == 2 and (expr.shape[1] == 1): # This is a vector (only one column) # Transpose and select first row to get result equivalent to Mathematica return Expression( "List", *[from_sympy(item) for item in expr.T.tolist()[0]]) else: return Expression( "List", *[[from_sympy(item) for item in row] for row in expr.tolist()]) if isinstance(expr, sympy.MatPow): return Expression("MatrixPower", from_sympy(expr.base), from_sympy(expr.exp)) if expr.is_Atom: name = None if expr.is_Symbol: name = str(expr) if isinstance(expr, sympy.Dummy): name = name + ("__Dummy_%d" % expr.dummy_index) return Symbol(name, sympy_dummy=expr) if is_Cn_expr(name): return Expression("C", int(name[1:])) if name.startswith(sympy_symbol_prefix): name = name[len(sympy_symbol_prefix):] if name.startswith(sympy_slot_prefix): index = name[len(sympy_slot_prefix):] return Expression("Slot", int(index)) elif expr.is_NumberSymbol: name = str(expr) if name is not None: builtin = sympy_to_mathics.get(name) if builtin is not None: name = builtin.get_name() return Symbol(name) elif isinstance( expr, (sympy.core.numbers.Infinity, sympy.core.numbers.ComplexInfinity)): return Symbol(expr.__class__.__name__) elif isinstance(expr, sympy.core.numbers.NegativeInfinity): return Expression("Times", Integer(-1), Symbol("Infinity")) elif isinstance(expr, sympy.core.numbers.ImaginaryUnit): return Complex(Integer(0), Integer(1)) elif isinstance(expr, sympy.Integer): return Integer(int(expr)) elif isinstance(expr, sympy.Rational): numerator, denominator = map(int, expr.as_numer_denom()) if denominator == 0: if numerator > 0: return Symbol("Infinity") elif numerator < 0: return Expression("Times", Integer(-1), Symbol("Infinity")) else: assert numerator == 0 return Symbol("Indeterminate") return Rational(numerator, denominator) elif isinstance(expr, sympy.Float): if expr._prec == machine_precision: return MachineReal(float(expr)) return Real(expr) elif isinstance(expr, sympy.core.numbers.NaN): return Symbol("Indeterminate") elif isinstance(expr, sympy.core.function.FunctionClass): return Symbol(str(expr)) elif expr is sympy.true: return Symbol("True") elif expr is sympy.false: return Symbol("False") elif expr.is_number and all([x.is_Number for x in expr.as_real_imag()]): # Hack to convert 3 * I to Complex[0, 3] return Complex(*[from_sympy(arg) for arg in expr.as_real_imag()]) elif expr.is_Add: return Expression("Plus", *sorted([from_sympy(arg) for arg in expr.args])) elif expr.is_Mul: return Expression("Times", *sorted([from_sympy(arg) for arg in expr.args])) elif expr.is_Pow: return Expression("Power", *[from_sympy(arg) for arg in expr.args]) elif expr.is_Equality: return Expression("Equal", *[from_sympy(arg) for arg in expr.args]) elif isinstance(expr, SympyExpression): return expr.expr elif isinstance(expr, sympy.Piecewise): args = expr.args return Expression( "Piecewise", Expression( "List", *[ Expression("List", from_sympy(case), from_sympy(cond)) for case, cond in args ]), ) elif isinstance(expr, SympyPrime): return Expression("Prime", from_sympy(expr.args[0])) elif isinstance(expr, sympy.RootSum): return Expression("RootSum", from_sympy(expr.poly), from_sympy(expr.fun)) elif isinstance(expr, sympy.PurePoly): coeffs = expr.coeffs() monoms = expr.monoms() result = [] for coeff, monom in zip(coeffs, monoms): factors = [] if coeff != 1: factors.append(from_sympy(coeff)) for index, exp in enumerate(monom): if exp != 0: slot = Expression("Slot", index + 1) if exp == 1: factors.append(slot) else: factors.append( Expression("Power", slot, from_sympy(exp))) if factors: result.append(Expression("Times", *factors)) else: result.append(Integer(1)) return Expression("Function", Expression("Plus", *result)) elif isinstance(expr, sympy.CRootOf): try: e, i = expr.args except ValueError: return Expression("Null") try: e = sympy.PurePoly(e) except: pass return Expression("Root", from_sympy(e), i + 1) elif isinstance(expr, sympy.Lambda): vars = [ sympy.Symbol("%s%d" % (sympy_slot_prefix, index + 1)) for index in range(len(expr.variables)) ] return Expression("Function", from_sympy(expr(*vars))) elif expr.is_Function or isinstance( expr, (sympy.Integral, sympy.Derivative, sympy.Sum, sympy.Product)): if isinstance(expr, sympy.Integral): name = "Integral" elif isinstance(expr, sympy.Derivative): name = "Derivative" margs = [] for arg in expr.args: # parse (x, 1) ==> just x for test_conversion # IMHO this should be removed in future versions if isinstance(arg, sympy.Tuple): if arg[1] == 1: margs.append(from_sympy(arg[0])) else: margs.append(from_sympy(arg)) else: margs.append(from_sympy(arg)) builtin = sympy_to_mathics.get(name) return builtin.from_sympy(name, margs) elif isinstance(expr, sympy.sign): name = "Sign" else: name = expr.func.__name__ if is_Cn_expr(name): return Expression(Expression("C", int(name[1:])), *[from_sympy(arg) for arg in expr.args]) if name.startswith(sympy_symbol_prefix): name = name[len(sympy_symbol_prefix):] args = [from_sympy(arg) for arg in expr.args] builtin = sympy_to_mathics.get(name) if builtin is not None: return builtin.from_sympy(name, args) return Expression(Symbol(name), *args) elif isinstance(expr, sympy.Tuple): return Expression("List", *[from_sympy(arg) for arg in expr.args]) # elif isinstance(expr, sympy.Sum): # return Expression('Sum', ) elif isinstance(expr, sympy.LessThan): return Expression("LessEqual", *[from_sympy(arg) for arg in expr.args]) elif isinstance(expr, sympy.StrictLessThan): return Expression("Less", *[from_sympy(arg) for arg in expr.args]) elif isinstance(expr, sympy.GreaterThan): return Expression("GreaterEqual", *[from_sympy(arg) for arg in expr.args]) elif isinstance(expr, sympy.StrictGreaterThan): return Expression("Greater", *[from_sympy(arg) for arg in expr.args]) elif isinstance(expr, sympy.Unequality): return Expression("Unequal", *[from_sympy(arg) for arg in expr.args]) elif isinstance(expr, sympy.Equality): return Expression("Equal", *[from_sympy(arg) for arg in expr.args]) elif isinstance(expr, sympy.O): if expr.args[0].func == sympy.core.power.Pow: [var, power] = [from_sympy(arg) for arg in expr.args[0].args] o = Expression("O", var) return Expression("Power", o, power) else: return Expression("O", from_sympy(expr.args[0])) else: raise ValueError( "Unknown SymPy expression: {} (instance of {})".format( expr, str(expr.__class__)))
def apply(self, n, evaluation): "Divisors[n_Integer]" if n == Integer(0): return None return Expression( "List", *[from_sympy(i) for i in sympy.divisors(n.to_sympy())])
def apply(self, steps, evaluation): "AnglePath[{steps___}]" return AnglePath._compute(Integer(0), Integer(0), None, steps.get_sequence(), evaluation)
def testInteger(self): _test_group(Integer(5), Integer(3242), Integer(-1372))
def apply(self, items, evaluation): 'Plus[items___]' items = items.numerify(evaluation).get_sequence() leaves = [] last_item = last_count = None prec = min_prec(*items) is_machine_precision = any(item.is_machine_precision() for item in items) numbers = [] def append_last(): if last_item is not None: if last_count == 1: leaves.append(last_item) else: if last_item.has_form('Times', None): last_item.leaves.insert(0, from_sympy(last_count)) leaves.append(last_item) else: leaves.append(Expression( 'Times', from_sympy(last_count), last_item)) for item in items: if isinstance(item, Number): numbers.append(item) else: count = rest = None if item.has_form('Times', None): for leaf in item.leaves: if isinstance(leaf, Number): count = leaf.to_sympy() rest = item.leaves[:] rest.remove(leaf) if len(rest) == 1: rest = rest[0] else: rest.sort() rest = Expression('Times', *rest) break if count is None: count = sympy.Integer(1) rest = item if last_item is not None and last_item == rest: last_count = last_count + count else: append_last() last_item = rest last_count = count append_last() if numbers: if prec is not None: if is_machine_precision: numbers = [item.to_mpmath() for item in numbers] number = mpmath.fsum(numbers) number = Number.from_mpmath(number) else: with mpmath.workprec(prec): numbers = [item.to_mpmath() for item in numbers] number = mpmath.fsum(numbers) number = Number.from_mpmath(number, dps(prec)) else: number = from_sympy(sum(item.to_sympy() for item in numbers)) else: number = Integer(0) if not number.same(Integer(0)): leaves.insert(0, number) if not leaves: return Integer(0) elif len(leaves) == 1: return leaves[0] else: leaves.sort() return Expression('Plus', *leaves)
def testAcrossTypes(self): _test_group(Integer(1), Rational(1, 1), Real(1), Complex(Integer(1), Integer(1)), String('1'), Symbol('1'))
def t_number(self, t): r''' ( (?# Two possible forms depending on whether base is specified) (\d+\^\^([a-zA-Z0-9]+\.?[a-zA-Z0-9]*|[a-zA-Z0-9]*\.?[a-zA-Z0-9]+)) | (\d+\.?\d*|\d*\.?\d+) ) (``?(\+|-)?(\d+\.?\d*|\d*\.?\d+)|`)? (?# Precision / Accuracy) (\*\^(\+|-)?\d+)? (?# Exponent) ''' s = t.value # Look for base s = s.split('^^') if len(s) == 1: base, s = 10, s[0] else: assert len(s) == 2 base, s = int(s[0]), s[1] assert 2 <= base <= 36 # Look for mantissa s = s.split('*^') if len(s) == 1: n, s = 0, s[0] else: # TODO: modify regex and provide error message if n not an int n, s = int(s[1]), s[0] # Look at precision ` suffix to get precision/accuracy prec, acc = None, None s = s.split('`', 1) if len(s) == 1: suffix, s = None, s[0] else: suffix, s = s[1], s[0] if suffix == '': prec = machine_precision elif suffix.startswith('`'): acc = float(suffix[1:]) else: if re.match('0+$', s) is not None: t.value = Integer(0) return t prec = float(suffix) # Look for decimal point if s.count('.') == 0: if suffix is None: if n < 0: t.value = Rational(int(s, base), base ** abs(n)) else: t.value = Integer(int(s, base) * (base ** n)) return t else: s = s + '.' if base == 10: if n != 0: s = s + 'E' + str(n) # sympy handles this if acc is not None: if float(s) == 0: prec = 0. else: prec = acc + log10(float(s)) + n # XXX if prec is not None: prec = dps(prec) t.value = Real(s, prec) # t.value = Real(s, prec, acc) else: # Convert the base assert isinstance(base, int) and 2 <= base <= 36 # Put into standard form mantissa * base ^ n s = s.split('.') if len(s) == 1: man = s[0] else: n -= len(s[1]) man = s[0] + s[1] man = int(man, base) if n >= 0: result = Integer(man * base ** n) else: result = Rational(man, base ** -n) if acc is None and prec is None: acc = len(s[1]) acc10 = acc * log10(base) prec10 = acc10 + log10(result.to_python()) if prec10 < 18: prec10 = None elif acc is not None: acc10 = acc * log10(base) prec10 = acc10 + log10(result.to_python()) elif prec is not None: if prec == machine_precision: prec10 = machine_precision else: prec10 = prec * log10(base) # XXX if prec10 is None: prec10 = machine_precision else: prec10 = dps(prec10) t.value = result.round(prec10) return t
def testOut(self): self.check('%%', Expression('Out', Integer(-2))) self.check('%%%%', Expression('Out', Integer(-4))) self.check('%', Expression('Out'))