gutow / Algebra_with_Sympy

Tools for doing stepwise algebra in an on paper like manner using SymPy.
https://gutow.github.io/Algebra_with_Sympy/
GNU General Public License v3.0
16 stars 3 forks source link

KeyError in simplify #23

Closed Firionus closed 9 months ago

Firionus commented 10 months ago

This call to simplify results in a KeyError:

from algebra_with_sympy import *
a,t = symbols('a t')
simplify(a*cos(t)+sin(t))
Full Error Output ```py --------------------------------------------------------------------------- KeyError Traceback (most recent call last) Cell In[7], line 5 1 from algebra_with_sympy import * 3 a ,t =symbols ('a t') ----> 5 simplify (a *cos (t )+sin (t )) File ~/.myrye/.venv/lib/python3.12/site-packages/sympy/simplify/simplify.py:699, in simplify(expr, ratio, measure, rational, inverse, doit, **kwargs) 696 expr = besselsimp(expr) 698 if expr.has(TrigonometricFunction, HyperbolicFunction): --> 699 expr = trigsimp(expr, deep=True) 701 if expr.has(log): 702 expr = shorter(expand_log(expr, deep=True), logcombine(expr)) File ~/.myrye/.venv/lib/python3.12/site-packages/sympy/simplify/trigsimp.py:564, in trigsimp(expr, inverse, **opts) 553 return trigsimp_groebner(new, **opts) 555 trigsimpfunc = { 556 'fu': (lambda x: fu(x, **opts)), 557 'matching': (lambda x: futrig(x)), (...) 561 'old': lambda x: trigsimp_old(x, **opts), 562 }[method] --> 564 expr_simplified = trigsimpfunc(expr) 565 if inverse: 566 expr_simplified = _trigsimp_inverse(expr_simplified) File ~/.myrye/.venv/lib/python3.12/site-packages/sympy/simplify/trigsimp.py:557, in trigsimp..(x) 552 return new 553 return trigsimp_groebner(new, **opts) 555 trigsimpfunc = { 556 'fu': (lambda x: fu(x, **opts)), --> 557 'matching': (lambda x: futrig(x)), 558 'groebner': (lambda x: groebnersimp(x, **opts)), 559 'combined': (lambda x: futrig(groebnersimp(x, 560 polynomial=True, hints=[2, tan]))), 561 'old': lambda x: trigsimp_old(x, **opts), 562 }[method] 564 expr_simplified = trigsimpfunc(expr) 565 if inverse: File ~/.myrye/.venv/lib/python3.12/site-packages/sympy/simplify/trigsimp.py:1158, in futrig(e, hyper, **kwargs) 1155 return e 1157 old = e -> 1158 e = bottom_up(e, _futrig) 1160 if hyper and e.has(HyperbolicFunction): 1161 e, f = hyper_as_trig(e) File ~/.myrye/.venv/lib/python3.12/site-packages/sympy/core/traversal.py:239, in bottom_up(rv, F, atoms, nonbasic) 237 if args != rv.args: 238 rv = rv.func(*args) --> 239 rv = F(rv) 240 elif atoms: 241 rv = F(rv) File ~/.myrye/.venv/lib/python3.12/site-packages/sympy/simplify/trigsimp.py:1225, in _futrig(e) 1186 trigs = lambda x: x.has(TrigonometricFunction) 1188 tree = [identity, 1189 ( 1190 TR3, # canonical angles (...) 1223 factor_terms, TR12(x), trigs)], # expand tan of sum 1224 )] -> 1225 e = greedy(tree, objective=Lops)(e) 1227 if coeff is not None: 1228 e = coeff * e File ~/.myrye/.venv/lib/python3.12/site-packages/sympy/strategies/core.py:150, in minimize..minrule(expr) 149 def minrule(expr: _S) -> _T: --> 150 return min([rule(expr) for rule in rules], key=objective) File ~/.myrye/.venv/lib/python3.12/site-packages/sympy/strategies/core.py:64, in chain..chain_rl(expr) 62 def chain_rl(expr: _T) -> _T: 63 for rule in rules: ---> 64 expr = rule(expr) 65 return expr File ~/.myrye/.venv/lib/python3.12/site-packages/sympy/simplify/fu.py:1220, in TRmorrie(rv) 1215 rv = Mul(*(new + other + [ 1216 cos(k*a, evaluate=False) for a in args for k in args[a]])) 1218 return rv -> 1220 return bottom_up(rv, f) File ~/.myrye/.venv/lib/python3.12/site-packages/sympy/core/traversal.py:236, in bottom_up(rv, F, atoms, nonbasic) 234 if args is not None: 235 if args: --> 236 args = tuple([bottom_up(a, F, atoms, nonbasic) for a in args]) 237 if args != rv.args: 238 rv = rv.func(*args) File ~/.myrye/.venv/lib/python3.12/site-packages/sympy/core/traversal.py:239, in bottom_up(rv, F, atoms, nonbasic) 237 if args != rv.args: 238 rv = rv.func(*args) --> 239 rv = F(rv) 240 elif atoms: 241 rv = F(rv) File ~/.myrye/.venv/lib/python3.12/site-packages/sympy/simplify/fu.py:1168, in TRmorrie..f(rv, first) 1166 if first: 1167 n, d = rv.as_numer_denom() -> 1168 return f(n, 0)/f(d, 0) 1170 args = defaultdict(list) 1171 coss = {} File ~/.myrye/.venv/lib/python3.12/site-packages/sympy/simplify/fu.py:1212, in TRmorrie..f(rv, first) 1210 else: 1211 b = cos(c.pop(0)*a) -> 1212 other.append(b**coss[b]) 1214 if new: 1215 rv = Mul(*(new + other + [ 1216 cos(k*a, evaluate=False) for a in args for k in args[a]])) KeyError: cos(t) ```

Without Algebra_with_Sympy it works:

from sympy import *
a,t = symbols('a t')
simplify(a*cos(t)+sin(t))

Output:

a*cos(t) + sin(t)

Tested on Algebra_with_Sympy 0.12, SymPy 1.12, CPython 3.12 from indygreg, Ubuntu 22.04.

Detailed Environment Info ```console $ rye show project: myrye path: /home/johannes/.myrye venv: /home/johannes/.myrye/.venv target python: 3.8 venv python: cpython@3.12.0 $ rye show --installed-deps Algebra-with-SymPy==0.12.0 anyio==4.0.0 argon2-cffi==23.1.0 argon2-cffi-bindings==21.2.0 arrow==1.3.0 asttokens==2.4.1 async-lru==2.0.4 attrs==23.1.0 Babel==2.13.1 beautifulsoup4==4.12.2 bleach==6.1.0 certifi==2023.11.17 cffi==1.16.0 charset-normalizer==3.3.2 comm==0.2.0 contourpy==1.2.0 cowsay==6.1 cycler==0.12.1 debugpy==1.8.0 decorator==5.1.1 defusedxml==0.7.1 executing==2.0.1 fastjsonschema==2.19.0 fonttools==4.44.3 fqdn==1.5.1 idna==3.4 ipykernel==6.26.0 ipython==8.17.2 ipywidgets==8.1.1 isoduration==20.11.0 jedi==0.19.1 Jinja2==3.1.2 json5==0.9.14 jsonpointer==2.4 jsonschema==4.20.0 jsonschema-specifications==2023.11.1 jupyter==1.0.0 jupyter-console==6.6.3 jupyter-events==0.9.0 jupyter-lsp==2.2.0 jupyter_client==8.6.0 jupyter_core==5.5.0 jupyter_server==2.10.1 jupyter_server_terminals==0.4.4 jupyterlab==4.0.9 jupyterlab-pygments==0.2.2 jupyterlab-widgets==3.0.9 jupyterlab_server==2.25.2 kiwisolver==1.4.5 MarkupSafe==2.1.3 matplotlib==3.8.1 matplotlib-inline==0.1.6 mistune==3.0.2 mpmath==1.3.0 # Editable Git install with no remote (myrye==0.1.0) -e /home/johannes/.myrye nbclient==0.9.0 nbconvert==7.11.0 nbformat==5.9.2 nest-asyncio==1.5.8 notebook==7.0.6 notebook_shim==0.2.3 numpy==1.26.2 overrides==7.4.0 packaging==23.2 pandocfilters==1.5.0 parso==0.8.3 pexpect==4.8.0 Pillow==10.1.0 platformdirs==4.0.0 prometheus-client==0.18.0 prompt-toolkit==3.0.41 psutil==5.9.6 ptyprocess==0.7.0 pure-eval==0.2.2 pycairo==1.25.1 pycparser==2.21 Pygments==2.16.1 PyGObject==3.46.0 pyparsing==3.1.1 python-dateutil==2.8.2 python-json-logger==2.0.7 PyYAML==6.0.1 pyzmq==25.1.1 qtconsole==5.5.1 QtPy==2.4.1 referencing==0.31.0 requests==2.31.0 rfc3339-validator==0.1.4 rfc3986-validator==0.1.1 rpds-py==0.13.1 Send2Trash==1.8.2 six==1.16.0 sniffio==1.3.0 soupsieve==2.5 stack-data==0.6.3 sympy==1.12 terminado==0.18.0 tinycss2==1.2.1 tornado==6.3.3 traitlets==5.13.0 types-python-dateutil==2.8.19.14 uri-template==1.3.0 urllib3==2.1.0 wcwidth==0.2.10 webcolors==1.13 webencodings==0.5.1 websocket-client==1.6.4 widgetsnbextension==4.0.9 $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04.3 LTS Release: 22.04 Codename: jammy ```
gutow commented 10 months ago

Thank you for the report. If the problem is what I suspect, I may get to it this weekend. If it is more complicated, I will not be able to do much about it for 3 weeks or so.

Firionus commented 10 months ago

Thanks for the quick triage response, and no worries, for now I can just use stock SymPy when the error pops up 👍

gutow commented 10 months ago

May be a typo at line 1212 in sympy.simplify.fu. Will need to track the array coss. The problem does not occur if sin and cos are swapped.

gutow commented 9 months ago

There appears to be some cases where Sympy reverts to definitions of functions as embedded in the original pip installed code. This means that sometimes interactive functions that have been modified (e.g. to understand what an equation is) are not identical to what Solve is trying to work with. The only solutions seems to be creating a custom fork of Sympy with the fundamental Function class defined to be Equation aware.

I am working on a way of doing this that should not be difficult to update at each Sympy release. Thus, Algebra_with_Sympy would not be easily usable with arbitrary releases of Sympy.