3 ms·
I like SymPy as a light-weight CAS. I don't have any heavy symbolic computational needs, but it fills a gap between "simple enough to work out with pen and pap
by Majromax 6y ago
I like SymPy as a light-weight CAS. I don't have any heavy symbolic computational needs, but it fills a gap between "simple enough to work out with pen and paper, without error" and "so complicated that it's best to stick to numerical simulation."
However, as a slightly-more-than-beginner user I have a frustrating time getting SymPy to take simplifications that I know are valid. As a result the generated answers are correct but so complicated that the "simple intuitive understanding" goal of the symbolic computation is lost.
This can come down to having implicit assumptions that I haven't told SymPy (such as variables being real-valued, or it being okay to take the principal roots of exp(I <stuff>)), but not always.
As a minimal example:
import sympy as sp # Import SymPy
# Define variables; note they're marked as real-valued
x = sp.Symbol('x', real=True);
t = sp.Symbol('t', real=True);
# Get our simple expression: 2*cos(t)*exp(x) but written in complex form
foo = sp.exp((x+sp.I*t)) + sp.exp((x-sp.I*t))
print(str(foo))
# Prints exp(-I*t + x) + exp(I*t + x)
print(str(foo.simplify()))
# Still prints exp(-I*t + x) + exp(I*t + x) -- SymPy thinks this is the simplest form?
print(str((foo/sp.exp(x)).simplify())) # Help it along
# Prints 2*cos(t)
Obviously, forcing SymPy to do the desired thing gets worse with more complicated expressions. Sometimes I can bash it into compliance with liberal use of `rewrite` or by demanding it simplify term-by-term, but if I'm deconstructing the expression only to reassemble it at the end then I'm not sure I'm still gaining much out of it as a computer algebra system.
- ogogmad 6y agoFor your particular example, try foo.rewrite(cos). If you work with trigonometric expressions, it often pays to randomly do foo.rewrite(cos) or foo.rewrite(exp) along with simplify(). Your larger point is true though, at least from my experience.
- Majromax 6y agoAlas, sp.rewrite doesn't quite do what I want for the slightly more complicated (with new symbol 'k' suitably defined): bar = sp.exp(sp.I*(x + k - t)) - sp.exp(sp.I*(x+k+t)) The desired output would be 2 cos(t) exp(I(x+k)), but rewrite and simplify works on an all-or-nothing basis, affecting exp(I(x+k)) as well. My mental framework is to come at this from something like a signal engineering perspective, looking at amplitude-modulated single frequencies. However, expressing that intent in a way that SymPy understands is for now beyond me. My problem may ultimately be one of documentation. The basic SymPy tutorials are quite nice, and the raw documentation for the functions... exists, but I have yet to find good examples of intermediate to advanced use discussing the "what and why" of accomplishing nontrivial goals.