Python:Symbolic Computations

From PrattWiki
Revision as of 02:33, 30 September 2022 by DukeEgr93 (talk | contribs) (Defining Symbols)
Jump to navigation Jump to search

This is a sandbox for information on symbolic computation with Python. It is about as organized as one might expect...

Introduction

SymPy is a package that allows Python to perform symbolic calculations. The main English-language site is https://www.sympy.org/en/index.html

Getting Started

  • Tutorial (note - some of the internal links on SymPy do not get to the tutorial - this link does).
  • Anaconda comes with SymPy already installed so you can skip the installation part if you are using Anaconda.
  • Note that sometimes the tutorial imports SymPy as sympy and other times it imports all of SymPy. This does make it a little harder to keep track of which commands are SymPy-specific!

Useful Pages

Preamble

  • This page will be consistent with Python:Nicknames in terms of module imports. Note that there are several ways to get the SymPy package into Python:
    • import sympy as sym (what this page does)
    • import sympy as sp (this is more consistent with bringing in NumPy, but that's what we will use for SciPy)
    • from sympy import * (if you are sure nothing in SymPy will contradict anything in built-in Python)
    • from sympy import TUPLE OF THINGS (if you just have a few specific things you want to do with SymPy)
  • sym.init_session() will automatically bring in x, y, z, and t as symbols; k, m, n as integers; f, g, h as function names; and sym.init_printing HOWEVER it brings in all of sympy with from sympy import *!

Output

  • To make output prettier: sym.init_printing()
  • The display depends on if LaTeX is installed or not; the command above will try to make the output as pretty as possible given the circumstances.

Defining Symbols

  • There are a variety of different ways to define symbols; your choice will be based on how you are writing and running code (for example, Spyder versus Jupyter versus Trinket).
  • If the symbolic representation and variable names exactly match, it is most efficient to use sym.var('a b c') or sym.var('a, b, c')
    • Spyder's editor will not recognize that the variables are defined, meaning you will get error flags in the editor. If you want to explicitly demonstrate that the variables exist, you can use a, b, c = sym.var('a b c')
    • Alternatively, if you want to create a list with all the variables in it, you can use THING = sym.var('a b c')
    • Top choice - If you want the best of both worlds, use a, b, c = sym.var('a b c') and THING = a, b, c; once you make the string, it is easy enough to copy and paste it in front of the = on the first line and after the = on the second.
  • (This part is informational, but potentially not useful) The symbolic representation can be entirely different from the variable with something like v1, ib, pabsR3 = sym.var('v_1 i_b p_{{abs\,R_{3}}}}') or a, b, c = sym.var('let\'s go Duke'). When Python displays the variables, it will use the characters assigned to the variable in the string. This doesn't look pretty in all version of Python, though, and requires sym.init_printing() to have a chance at working.
  • sym.symbols() is similar to sym.var() except that you must explicitly list the names on the right of an = if you want things defined:
    • a, b, c = sym.var('a b c') is the same as a, b, c = sym.symbols('a b c')
    • sym.symbols('a b c') does not create variables while sym.var('a b c') does.
    • THING = sym.symbols('a b c') creates a single tuple called THING that has symbols in it, but does not actually create those symbols! That is to say, THING[0] will display as $$a$$, but you cannot use $$a$$ in an expression.
  • SymPy (with sym.init_printing()) will automatically subscript a trailing number when displaying - for instance, using blah = sym.var('x17') means if you type blah in the console it will display $$x_{17}$$.

Substitutions

  • If you have some symbolic object X that contains several other symbols, you can use X.subs(variable, value) for a single substitution or X.subs(iterable) where iterable has a collection of variables and values; for example, X.subs([(a, 10), (b, 20)])
  • If you have several variables and several values, it may be useful to have a list of each and "zip" them together:
> vars = ['a', 'b']
> vals = [10, 20]
> print(list(zip(vars, vals)))
[('a', 10), ('b', 20)]
> x = a + b
> print(x)
a + b
> x.subs(zip(vars, vals))
30

Solving

  • sym.solve(EQNS, VARS) for a system of equations
  • sym.dsolve(EQNS, VARS) for a system of differential equations

Interesting Things

  • sym.lambdify((variables), expression, "numpy") will return a function that performs the calculation in the expression
  • sym.simplify(expression) will work to simplify an expression
  • sym.Matrix() can have symbols and will calculate things symbolically

Philosophical Things =

References

Future Work

  • Determine good ways to collect equations and variables.
  • Clarify when to solve after numbers are in versus before.
  • Subscripts are...strange. Numbers coming at the end of a variable print as subscripts but letters end that behavior. One workaround is to define a variable with the xa = sym.Symbol('x_a') command but that will only take a single character superscript.
  • You can create a neat symbol like pdelvCC = sym.Symbol('p_{{del,v_{CC}}}}') and it will work great in a notebook or inline. Spyder has a display() function that will also work but creates a plot with the rendering. Displays really ugly on Trinket. Best to avoid for now.