>>> from sympy import *
>>> x, y, z = symbols('x y z')
>>> init_printing(use_unicode=True)
Recall from the gotchas section of this tutorial that symbolic equations in SymPy are not represented by = or ==, but by Eq.
>>> Eq(x, y)
x = y
However, there is an even easier way. In SymPy, any expression is not in an Eq is automatically assumed to equal 0 by the solving functions. Since \(a = b\) if and only if \(a - b = 0\), this means that instead of using x == y, you can just use x - y. For example
>>> solve(Eq(x**2, 1), x)
[-1, 1]
>>> solve(Eq(x**2 - 1, 0), x)
[-1, 1]
>>> solve(x**2 - 1, x)
[-1, 1]
This is particularly useful if the equation you wish to solve is already equal to 0. Instead of typing solve(Eq(expr, 0), x), you can just use solve(expr, x).
The main function for solving algebraic equations, as we saw above, is solve. The syntax is solve(equations, variables), where, as we saw above, equations may be in the form of Eq instances or expressions that are assumed to be equal to zero.
When solving a single equation, the output of solve is a list of the solutions.
>>> solve(x**2 - x, x)
[0, 1]
If no solutions are found, an empty list is returned, or NotImplementedError is raised.
>>> solve(exp(x), x)
[]
Note
If solve returns [] or raises NotImplementedError, it doesn’t mean that the equation has no solutions. It just means that it couldn’t find any. Often this means that the solutions cannot be represented symbolically. For example, the equation \(x = \cos(x)\) has a solution, but it cannot be represented symbolically using standard functions.
>>> solve(x - cos(x), x)
Traceback (most recent call last):
...
NotImplementedError: multiple generators [x, exp(I*x)]
No algorithms are implemented to solve equation exp(I*x)
In fact, solve makes no guarantees whatsoever about the completeness of the solutions it finds. Much of solve is heuristics, which may find some solutions to an equation or system of equations, but not all of them.
solve can also solve systems of equations. Pass a list of equations and a list of variables to solve for.
>>> solve([x - y + 2, x + y - 3], [x, y])
{x: 1/2, y: 5/2}
>>> solve([x*y - 7, x + y - 6], [x, y])
⎡⎛ ___ ___ ⎞ ⎛ ___ ___ ⎞⎤
⎣⎝- ╲╱ 2 + 3, ╲╱ 2 + 3⎠, ⎝╲╱ 2 + 3, - ╲╱ 2 + 3⎠⎦
Note
The type of the output of solve when solving systems of equations varies depending on the type of the input. If you want a consistent interface, pass dict=True.
>>> solve([x - y + 2, x + y - 3], [x, y], dict=True)
[{x: 1/2, y: 5/2}]
>>> solve([x*y - 7, x + y - 6], [x, y], dict=True)
⎡⎧ ___ ___ ⎫ ⎧ ___ ___ ⎫⎤
⎢⎨x: - ╲╱ 2 + 3, y: ╲╱ 2 + 3⎬, ⎨x: ╲╱ 2 + 3, y: - ╲╱ 2 + 3⎬⎥
⎣⎩ ⎭ ⎩ ⎭⎦
solve reports each solution only once. To get the solutions of a polynomial including multiplicity use roots.
>>> solve(x**3 - 6*x**2 + 9*x, x)
[0, 3]
>>> roots(x**3 - 6*x**2 + 9*x, x)
{0: 1, 3: 2}
The output {0: 1, 3: 2} of roots means that 0 is a root of multiplicity 1 and 3 is a root of multiplicity 2.
To solve differential equations, use dsolve. First, create an undefined function by passing cls=Function to the symbols function.
>>> f, g = symbols('f g', cls=Function)
f and g are now undefined functions. We can call f(x), and it will represent an unknown function.
>>> f(x)
f(x)
Derivatives of f(x) are unevaluated.
>>> f(x).diff(x)
d
──(f(x))
dx
(see the Derivatives section for more on derivatives).
To represent the differential equation \(f''(x) - 2f'(x) + f(x) = \sin(x)\), we would thus use
>>> diffeq = Eq(f(x).diff(x, x) - 2*f(x).diff(x) + f(x), sin(x))
>>> diffeq
2
d d
f(x) - 2⋅──(f(x)) + ───(f(x)) = sin(x)
dx 2
dx
To solve the ODE, pass it and the function to solve for to dsolve.
>>> dsolve(diffeq, f(x))
x cos(x)
f(x) = (C₁ + C₂⋅x)⋅ℯ + ──────
2
dsolve returns an instance of Eq. This is because in general, solutions to differential equations cannot be solved explicitly for the function.
>>> dsolve(f(x).diff(x)*(1 - sin(f(x))), f(x))
f(x) + cos(f(x)) = C₁
The arbitrary constants in the solutions from dsolve are symbols of the form C1, C2, C3, and so on.