Mathics3 / mathics-core

An open-source Mathematica. This repository contains the Python modules for WL Built-in functions, variables, core primitives, e.g. Symbol, a parser to create Expressions, and an evaluator to execute them.

Home Page:https://mathics.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`Simplify`ing the result of `ReplaceAll` sometimes fails with `'SympyExpression' object has no attribute 'expr'`

HolyBlackCat opened this issue · comments

Description

How to Reproduce

Type following expressions:

eq = {X[a],Y[a]}*x+{X[b],Y[b]}=={X[c],Y[c]}*y
sol = Simplify[Solve[Thread[eq], {x,y}]] (* Simplify works here *)
Simplify[X0*x+Y0*y //. sol] (* And doesn't work after replacement *)

Output Given

In[1]:= eq = {X[a],Y[a]}*x+{X[b],Y[b]}=={X[c],Y[c]}*y
Out[1]= {x X[a] + X[b], x Y[a] + Y[b]} ⩵ {y X[c], y Y[c]}

In[2]:= sol = Simplify[Solve[Thread[eq], {x,y}]] (* Simplify works here *)
Out[2]= {{x → (X[c] Y[b] - X[b] Y[c]) / (X[a] Y[c] - X[c] Y[a]), y → (X[a] Y[b] - X[b] Y[a]) / (X[a] Y[c] - X[c] Y[a])}}

In[3]:= Simplify[X0*x+Y0*y //. sol] (* And doesn't work after replacement *)

Then it crashes:

Traceback (most recent call last):
  File "/usr/local/bin/mathicsscript", line 33, in <module>
    sys.exit(load_entry_point('mathicsscript', 'console_scripts', 'mathicsscript')())
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
  File "/usr/src/app/src/mathicsscript/mathicsscript/__main__.py", line 428, in main
    result = evaluation.evaluate(
  File "/usr/src/app/mathics-core/mathics/core/evaluation.py", line 294, in evaluate
    result = run_with_timeout_and_stack(evaluate, timeout, self)
  File "/usr/src/app/mathics-core/mathics/core/evaluation.py", line 110, in run_with_timeout_and_stack
    return request()
  File "/usr/src/app/mathics-core/mathics/core/evaluation.py", line 267, in evaluate
    self.last_eval = query.evaluate(self)
  File "/usr/src/app/mathics-core/mathics/core/expression.py", line 507, in evaluate
    expr, reevaluate = expr.rewrite_apply_eval_step(evaluation)
  File "/usr/src/app/mathics-core/mathics/core/list.py", line 154, in rewrite_apply_eval_step
    new = new.evaluate_elements(evaluation)
  File "/usr/src/app/mathics-core/mathics/core/list.py", line 103, in evaluate_elements
    new_value = element.evaluate(evaluation)
  File "/usr/src/app/mathics-core/mathics/core/expression.py", line 507, in evaluate
    expr, reevaluate = expr.rewrite_apply_eval_step(evaluation)
  File "/usr/src/app/mathics-core/mathics/core/expression.py", line 1313, in rewrite_apply_eval_step
    result = rule.apply(new, evaluation, fully=False)
  File "/usr/src/app/mathics-core/mathics/core/rules.py", line 106, in apply
    self.pattern.match(yield_match, expression, {}, evaluation, fully=fully)
  File "/usr/src/app/mathics-core/mathics/core/pattern.py", line 467, in match
    self.head.match(yield_head, expression.get_head(), vars, evaluation)
  File "/usr/src/app/mathics-core/mathics/core/pattern.py", line 305, in match_symbol
    yield_func(vars, None)
  File "/usr/src/app/mathics-core/mathics/core/pattern.py", line 457, in yield_head
    self.get_pre_choices(
  File "/usr/src/app/mathics-core/mathics/core/pattern.py", line 648, in get_pre_choices
    yield_choice(vars)
  File "/usr/src/app/mathics-core/mathics/core/pattern.py", line 435, in yield_choice
    self.match_element(
  File "/usr/src/app/mathics-core/mathics/core/pattern.py", line 864, in match_element
    self.get_wrappings(
  File "/usr/src/app/mathics-core/mathics/core/pattern.py", line 681, in get_wrappings
    yield_func(items[0])
  File "/usr/src/app/mathics-core/mathics/core/pattern.py", line 853, in yield_wrapping
    element.match(
  File "/usr/src/app/mathics-core/mathics/builtin/patterns.py", line 1036, in match
    self.pattern.match(yield_func, expression, new_vars, evaluation)
  File "/usr/src/app/mathics-core/mathics/builtin/patterns.py", line 1262, in match
    yield_func(vars, None)
  File "/usr/src/app/mathics-core/mathics/core/pattern.py", line 834, in match_yield
    self.match_element(
  File "/usr/src/app/mathics-core/mathics/core/pattern.py", line 864, in match_element
    self.get_wrappings(
  File "/usr/src/app/mathics-core/mathics/core/pattern.py", line 692, in get_wrappings
    yield_func(sequence)
  File "/usr/src/app/mathics-core/mathics/core/pattern.py", line 853, in yield_wrapping
    element.match(
  File "/usr/src/app/mathics-core/mathics/builtin/patterns.py", line 1742, in match
    yield_func(new_vars, None)
  File "/usr/src/app/mathics-core/mathics/core/pattern.py", line 850, in match_yield
    yield_func(new_vars, items_rest)
  File "/usr/src/app/mathics-core/mathics/core/pattern.py", line 827, in element_yield
    yield_func(
  File "/usr/src/app/mathics-core/mathics/core/rules.py", line 78, in yield_match
    new_expression = self.do_replace(expression, vars, options, evaluation)
  File "/usr/src/app/mathics-core/mathics/core/rules.py", line 267, in do_replace
    return self.function(evaluation=evaluation, options=options, **vars_noctx)
  File "/usr/src/app/mathics-core/mathics/builtin/numbers/algebra.py", line 1672, in eval
    return self.do_apply(expr, evaluation, options)
  File "/usr/src/app/mathics-core/mathics/builtin/numbers/algebra.py", line 1726, in do_apply
    sympy_result = sympy.simplify(sympy_expr, measure=complexity_function)
  File "/usr/local/lib/python3.10/dist-packages/sympy/simplify/simplify.py", line 725, in simplify
    short = shorter(powsimp(expr, combine='exp', deep=True), powsimp(expr), expr)
  File "/usr/local/lib/python3.10/dist-packages/sympy/simplify/powsimp.py", line 117, in powsimp
    expr = expr.func(*[recurse(w) for w in expr.args])
  File "/usr/local/lib/python3.10/dist-packages/sympy/simplify/powsimp.py", line 117, in <listcomp>
    expr = expr.func(*[recurse(w) for w in expr.args])
  File "/usr/local/lib/python3.10/dist-packages/sympy/simplify/powsimp.py", line 108, in recurse
    return powsimp(arg, _deep, _combine, _force, _measure)
  File "/usr/local/lib/python3.10/dist-packages/sympy/simplify/powsimp.py", line 117, in powsimp
    expr = expr.func(*[recurse(w) for w in expr.args])
  File "/usr/local/lib/python3.10/dist-packages/sympy/simplify/powsimp.py", line 117, in <listcomp>
    expr = expr.func(*[recurse(w) for w in expr.args])
  File "/usr/local/lib/python3.10/dist-packages/sympy/simplify/powsimp.py", line 108, in recurse
    return powsimp(arg, _deep, _combine, _force, _measure)
  File "/usr/local/lib/python3.10/dist-packages/sympy/simplify/powsimp.py", line 142, in powsimp
    b, e = [recurse(i) for i in [b, e]]
  File "/usr/local/lib/python3.10/dist-packages/sympy/simplify/powsimp.py", line 142, in <listcomp>
    b, e = [recurse(i) for i in [b, e]]
  File "/usr/local/lib/python3.10/dist-packages/sympy/simplify/powsimp.py", line 108, in recurse
    return powsimp(arg, _deep, _combine, _force, _measure)
  File "/usr/local/lib/python3.10/dist-packages/sympy/simplify/powsimp.py", line 117, in powsimp
    expr = expr.func(*[recurse(w) for w in expr.args])
  File "/usr/src/app/mathics-core/mathics/core/convert/sympy.py", line 168, in __new__
    return SympyExpression(self.expr)
AttributeError: 'SympyExpression' object has no attribute 'expr'

Expected behavior

No crash, correct simplification.

Your Environment

Docker:

Mathicscript: 7.0.0.dev0, Mathics 7.0.0dev0
on CPython 3.10.6 (main, May 29 2023, 11:10:38) [GCC 11.3.0]

Using:
SymPy 1.12, mpmath 1.3.0, numpy 1.25.0
cython 3.0.0, matplotlib 3.7.2,
Asymptote version 2.78

Additional context

This has something to do with using X[a],Y[a] instead of e.g. xa,xa; the latter does work.

I expected X[a] to be treated as an opaque variable, but perhaps, I misunderstand something about the language.

This has something to do with the names X0, Y0. If I use other names, such as XX, YY, it doesn't crash. 🤔

It seems adding any digit to those names causes this issue.