mathics-core
mathics-core copied to clipboard
`Simplify`ing the result of `ReplaceAll` sometimes fails with `'SympyExpression' object has no attribute 'expr'`
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. :thinking:
It seems adding any digit to those names causes this issue.