Introduction to Symbolic Computation
Most numerical libraries (like NumPy) work with floating-point numbers. While fast, floating-point numbers are always approximations. For example, in NumPy is represented as 1.4142135623730951. In symbolic mathematics, we want to keep it as to maintain exactness throughout our derivations.
SymPy is a Python library for symbolic mathematics. It aims to become a full-featured Computer Algebra System (CAS) while keeping the code as simple as possible in order to be comprehensible and easily extensible.
Symbols and Expressions
In SymPy, we must explicitly define variables as symbolic objects.
Interactive Lab
import sympy as sp
# Define symbols
x, y = sp.symbols('x y')
# Create an expression
expr = x**2 + 2*x + 1
print("Expression:", expr)
print("Substituted (x=2):", expr.subs(x, 2))
Expected output
Expression: x**2 + 2*x + 1
Substituted (x=2): 9
1
2import sympy as sp
3
4
5x, y = sp.symbols('x y')
6
7
8expr = x**2 + 2*x + 1
9
10print("Expression:", expr)
11print("Substituted (x=2):", expr.subs(x, 2))
12
Structural Manipulations
One of the most powerful features of SymPy is the ability to simplify, expand, and factor expressions automatically.
Expansion and Factoring
Interactive Lab
import sympy as sp
x = sp.symbols('x')
poly = (x + 1)**3
expanded = sp.expand(poly)
factored = sp.factor(expanded)
print(f"Original: {poly}")
print(f"Expanded: {expanded}")
print(f"Factored: {factored}")
Expected output
Original: (x + 1)**3
Expanded: x**3 + 3*x**2 + 3*x + 1
Factored: (x + 1)**3
1
2import sympy as sp
3x = sp.symbols('x')
4
5poly = (x + 1)**3
6expanded = sp.expand(poly)
7factored = sp.factor(expanded)
8
9print(f"Original: {poly}")
10print(f"Expanded: {expanded}")
11print(f"Factored: {factored}")
12
Simplification
SymPy has a general-purpose simplify() function that attempts to find the most compact form of an expression.
Interactive Lab
import sympy as sp
x = sp.symbols('x')
expr = (x**2 + x) / x
simplified = sp.simplify(expr)
print(f"Expression: {expr}")
print(f"Simplified: {simplified}")
# Trigonometric simplification
trig_expr = sp.sin(x)**2 + sp.cos(x)**2
print(f"sin^2 + cos^2 = {sp.simplify(trig_expr)}")
Expected output
Expression: (x**2 + x)/x
Simplified: x + 1
sin^2 + cos^2 = 1
1
2import sympy as sp
3x = sp.symbols('x')
4
5expr = (x**2 + x) / x
6simplified = sp.simplify(expr)
7
8print(f"Expression: {expr}")
9print(f"Simplified: {simplified}")
10
11
12trig_expr = sp.sin(x)**2 + sp.cos(x)**2
13print(f"sin^2 + cos^2 = {sp.simplify(trig_expr)}")
14
Calculus with SymPy
SymPy can perform various calculus operations exactly.
Differentiation
Interactive Lab
import sympy as sp
x = sp.symbols('x')
f = sp.sin(x) * sp.exp(x)
derivative = sp.diff(f, x)
print(f"f(x) = {f}")
print(f"f'(x) = {derivative}")
Expected output
f(x) = exp(x)*sin(x)
f'(x) = exp(x)*sin(x) + exp(x)*cos(x)
1
2import sympy as sp
3x = sp.symbols('x')
4
5f = sp.sin(x) * sp.exp(x)
6derivative = sp.diff(f, x)
7
8print(f"f(x) = {f}")
9print(f"f'(x) = {derivative}")
10
Integration
SymPy can handle both definite and indefinite integrals.
Interactive Lab
import sympy as sp
x = sp.symbols('x')
# Indefinite integral
indef = sp.integrate(sp.cos(x), x)
print(f"Integral of cos(x): {indef}")
# Definite integral from 0 to pi/2
def_int = sp.integrate(sp.exp(-x), (x, 0, sp.oo)) # oo is infinity
print(f"Integral of e^-x from 0 to infinity: {def_int}")
Expected output
Integral of cos(x): sin(x)
Integral of e^-x from 0 to infinity: 1
1
2import sympy as sp
3x = sp.symbols('x')
4
5
6indef = sp.integrate(sp.cos(x), x)
7print(f"Integral of cos(x): {indef}")
8
9
10def_int = sp.integrate(sp.exp(-x), (x, 0, sp.oo))
11print(f"Integral of e^-x from 0 to infinity: {def_int}")
12
Limits
Interactive Lab
import sympy as sp
x = sp.symbols('x')
limit_val = sp.limit(sp.sin(x)/x, x, 0)
print(f"Limit of sin(x)/x as x -> 0: {limit_val}")
Expected output
Limit of sin(x)/x as x -> 0: 1
1
2import sympy as sp
3x = sp.symbols('x')
4
5limit_val = sp.limit(sp.sin(x)/x, x, 0)
6print(f"Limit of sin(x)/x as x -> 0: {limit_val}")
7
Equation Solving
SymPy can solve equations and systems of equations symbolically.
Interactive Lab
import sympy as sp
x, y = sp.symbols('x y')
# Solve x^2 - 1 = 0
solutions = sp.solve(x**2 - 1, x)
print(f"Solutions for x^2 - 1 = 0: {solutions}")
# Solve system of linear equations
# x + y = 5
# x - y = 1
sol_system = sp.solve([x + y - 5, x - y - 1], [x, y])
print(f"System solution: {sol_system}")
Expected output
Solutions for x^2 - 1 = 0: [-1, 1]
System solution: {x: 3, y: 2}
1
2import sympy as sp
3x, y = sp.symbols('x y')
4
5
6solutions = sp.solve(x**2 - 1, x)
7print(f"Solutions for x^2 - 1 = 0: {solutions}")
8
9
10
11
12sol_system = sp.solve([x + y - 5, x - y - 1], [x, y])
13print(f"System solution: {sol_system}")
14
Pretty Printing and LaTeX
SymPy can output expressions in various formats, including LaTeX, which is beautiful for documentation and papers.
Interactive Lab
import sympy as sp
x = sp.symbols('x')
expr = sp.sqrt(x**2 + 1) / sp.sin(x)
print("Standard print:", expr)
print("LaTeX:", sp.latex(expr))
Expected output
Standard print: sqrt(x**2 + 1)/sin(x)
LaTeX: \\frac{\\sqrt{x^{2} + 1}}{\\sin{\\left(x \\right)}}
1
2import sympy as sp
3x = sp.symbols('x')
4expr = sp.sqrt(x**2 + 1) / sp.sin(x)
5
6print("Standard print:", expr)
7print("LaTeX:", sp.latex(expr))
8
Bridging SymPy and NumPy: lambdify
Often you derive an expression symbolically in SymPy but need to evaluate it numerically for thousands of points using NumPy. The lambdify function creates a fast numerical function from a SymPy expression.
Interactive Lab
import sympy as sp
import numpy as np
x = sp.symbols('x')
expr = sp.sin(x)**2
# Convert to a numpy-friendly function
f = sp.lambdify(x, expr, 'numpy')
# Now evaluate on a numpy array
data = np.linspace(0, 10, 5)
results = f(data)
print("Numerical results from symbolic expr:", results)
Expected output
Numerical results from symbolic expr: [0. 0.35816891 0.91953576 0.4265434 0.29562444]
1
2import sympy as sp
3import numpy as np
4
5x = sp.symbols('x')
6expr = sp.sin(x)**2
7
8
9f = sp.lambdify(x, expr, 'numpy')
10
11
12data = np.linspace(0, 10, 5)
13results = f(data)
14print("Numerical results from symbolic expr:", results)
15
In the next modules, we will dive deeper into Matrix algebra and structural mechanics applications.