Importing Sympy¶

In [1]:
from sympy import *   ## Use functionname()

Will load the entire sympy library to your workspace, use with caution as this may make it difficult to determine which function is being called. See the style guide for more info: https://peps.python.org/pep-0008/#imports

In [2]:
import sympy    ## Use sympy.functionname()

This option keeps imported functions separate

In [3]:
import sympy as sp ## Use sp.functionname()

This option also keeps imported functions separate

Basics¶

SymPy (Symbolic Python) is a Python library that deals with symbolic, not numeric, objects. You can only call SymPy functions on SymPy objects.

In [4]:
import sympy as sp
import numpy as np

A = sp.Matrix([1, 2, 3])
print(type(A))      # <class 'sympy.matrices.dense.MutableDenseMatrix'> : SymPy object

theta_deg = 45
print(type(theta_deg))  # <class 'int'> : native to Python

theta_rad = sp.rad(theta_deg)

# NumPy function returns a 64bit floating point number
print(type(np.deg2rad(theta_deg))) # <class 'numpy.float64'> 

# The equivalent SymPy function returns a symbolic object, not a floating point number
print(type(theta_rad))  # <class 'sympy.core.mul.Mul'>

x = sp.cos(theta_rad)
print(type(x))      # <class 'sympy.core.mul.Mul'>

# NumPy expects the input to be a floating point number, not a SymPy symbolic object
# x = np.cos(theta_rad)   # error

sqrt5 = sp.sqrt(5)
print(type(sqrt5))  # <class 'sympy.core.power.Pow'>

x, y, z = sp.symbols('x, y, z')
print(type(x))      # <class 'sympy.core.symbol.Symbol'>

f = x**2*y*z**3
print(type(f))      # <class 'sympy.core.mul.Mul'>

# You can't convert a sympy symbolic expression to a floating point number
# without substituting numeric values for the variables
# print(float(f))     # error

# Substituting in numeric values for each SymPy object allows us
# to convert our expression to a float
f_sub = f.subs({x: 1, y: 2, z: 3})
print(type(f_sub)) # <class 'sympy.core.numbers.Integer'>

f_sub_float = float(f_sub)
print(type(f_sub_float)) # <class 'float'>
<class 'sympy.matrices.dense.MutableDenseMatrix'>
<class 'int'>
<class 'numpy.float64'>
<class 'sympy.core.mul.Mul'>
<class 'sympy.core.mul.Mul'>
<class 'sympy.core.power.Pow'>
<class 'sympy.core.symbol.Symbol'>
<class 'sympy.core.mul.Mul'>
<class 'sympy.core.numbers.Integer'>
<class 'float'>

Matrices¶

Creating Matrices¶

In [5]:
A = sp.Matrix([1, 2, 3])   # Returns a 1 × n matrix.

A = sp.Matrix([[1, 2, 3],  # Returns an m × n matrix.
               [4, 5, 6],
               [7, 8, 9]])

Matrix Indexing¶

In [6]:
i, j = 0, 2

print(A[i])     # Returns the i-th value of A (0-indexed).

print(A[i, j])  # Returns the value in the i-th row and j-th column of A.
1
3

Matrix Operations¶

In [7]:
B = A

print(A * B)   # Returns the result of matrix multiplication of matrices 
               # A and B. (# of columns in A must match the # of rows in B.)

print(A.norm()) # Returns the magnitude (length) of matrix A.
Matrix([[30, 36, 42], [66, 81, 96], [102, 126, 150]])
sqrt(285)

Vector Operations¶

In [8]:
u = sp.Matrix([1, 2, 3])
v = sp.Matrix([4, 5, 6])

print(u.dot(v))      # Returns the dot product of u and v
print(u.cross(v))    # Returns the cross product of u and v
print(u.project(v))  # Returns the projection of u onto v
32
Matrix([[-3], [6], [-3]])
Matrix([[128/77], [160/77], [192/77]])

Trigonometry¶

In [9]:
theta = 45
print(sp.rad(theta))  # Converts theta from degrees to radians: (pi/180)(theta)

theta = sp.pi / 4
print(sp.deg(theta))  # Converts theta from radians to degrees: (180/pi)(theta)
pi/4
45

Trigonometric Functions¶

In [10]:
print(sp.sin(theta))  # Returns sin(theta) (theta must be in radians)

print(sp.cos(theta))  # Returns cos(theta) (theta must be in radians)

print(sp.tan(theta))  # Returns tan(theta) (theta must be in radians)
sqrt(2)/2
sqrt(2)/2
1

Inverse Trigonometric Functions¶

In [11]:
x, y, r = 3, 4, 5

print(sp.asin(y/r))   # Returns theta between -pi/2 and pi/2 such that sin(theta) = y/r
             
print(sp.acos(x/r))    # Returns theta between 0 and pi such that cos(theta) = x/r

print(sp.atan2(y, x))  # Returns theta such that tan(theta) = y/x

## sp.atan(y/x) only returns angles between -pi/2 and pi/2, so always use atan2(y, x)

## note that in numpy, this is np.arctan2(y,x)
0.927295218001612
0.927295218001612
atan(4/3)

Symbols and Substitutions¶

In [12]:
x, y, z = sp.symbols('x y z')  # Defines x, y, and z as symbolic variables
## real=True to avoid imaginary answers
x_0, y_0, z_0 = 1, 2, 3

f = x**2
print(f)

print(f.subs(x, x_0))  # Returns f with x_0 substituted for x

f = sp.sqrt(x) + y**4 + z / 3
print(f.subs({x: x_0, y: y_0, z: z_0})) # Multiple substitutions
x**2
1
18

Calculus¶

Derivatives¶

In [13]:
f = x**2 * y**4

n = 1
print(f.diff(x, n))  # Returns the nth derivative of f w.r.t. x (default n=1)

print(f.diff(x, 2))  # Equivalent to f.diff(x, x) = sp.diff(f, x, x)

print(f.diff(x, 2, y, 3))  # Equivalent to sp.diff(f, x, x, y, y, y)
2*x*y**4
2*y**4
48*y
48*y

Integrals¶

In [14]:
f = x**2 * y**4
x_0, x_1, y_0, y_1 = 0, 1, 0, 4

print(f.integrate(x))  # Returns the indefinite integral of f w.r.t. x

print(f.integrate([x, x_0, x_1]))  # Returns the definite integral of f from x_0 to x_1

print(f.integrate([x, x_0, x_1], [y, y_0, y_1]))  # Returns area integral
x**3*y**4/3
y**4/3
1024/15

Mathematical Functions¶

In [15]:
n = -1
print(abs(n))      # Returns the absolute value of n

n = 4
print(sp.sqrt(n))  # Returns the square root of n

f = sp.sqrt(2)
print(f.evalf(n))  # Returns a numerical approximation of f to n sig. figures
1
2
1.414

Solving Equations¶

In [16]:
LHS1, RHS1 = x**2 + 5 , y + 8
eq1 = sp.Eq(LHS1, RHS1)  # Creates an equation equating LHS to RHS

LHS2, RHS2 = y**2 + 5 , x + 8
eq2 = sp.Eq(LHS2, RHS2)

print(sp.solve([eq1, eq2], dict=True))  # Returns solution to system of equations
## manual=True to avoid long-running code
[{x: -2, y: 1}, {x: 1, y: -2}, {x: -3 + (1/2 - sqrt(13)/2)**2, y: 1/2 - sqrt(13)/2}, {x: -3 + (1/2 + sqrt(13)/2)**2, y: 1/2 + sqrt(13)/2}]

Notes and Warnings¶

You can use SymPy functions on Numpy obejcts - e.g. sp.cos(np.pi) - but you cannot use NumPy functions on SymPy objects - e.g. np.cos(sp.pi)

To access documentation for any function, run the code with question mark after the function name:

In [17]:
integrate?
Signature:
integrate(
    *args,
    meijerg=None,
    conds='piecewise',
    risch=None,
    heurisch=None,
    manual=None,
    **kwargs,
)
Docstring:
integrate(f, var, ...)

.. deprecated:: 1.6

   Using ``integrate()`` with :class:`~.Poly` is deprecated. Use
   :meth:`.Poly.integrate` instead. See :ref:`deprecated-integrate-poly`.

Explanation
===========

Compute definite or indefinite integral of one or more variables
using Risch-Norman algorithm and table lookup. This procedure is
able to handle elementary algebraic and transcendental functions
and also a huge class of special functions, including Airy,
Bessel, Whittaker and Lambert.

var can be:

- a symbol                   -- indefinite integration
- a tuple (symbol, a)        -- indefinite integration with result
                                given with ``a`` replacing ``symbol``
- a tuple (symbol, a, b)     -- definite integration

Several variables can be specified, in which case the result is
multiple integration. (If var is omitted and the integrand is
univariate, the indefinite integral in that variable will be performed.)

Indefinite integrals are returned without terms that are independent
of the integration variables. (see examples)

Definite improper integrals often entail delicate convergence
conditions. Pass conds='piecewise', 'separate' or 'none' to have
these returned, respectively, as a Piecewise function, as a separate
result (i.e. result will be a tuple), or not at all (default is
'piecewise').

**Strategy**

SymPy uses various approaches to definite integration. One method is to
find an antiderivative for the integrand, and then use the fundamental
theorem of calculus. Various functions are implemented to integrate
polynomial, rational and trigonometric functions, and integrands
containing DiracDelta terms.

SymPy also implements the part of the Risch algorithm, which is a decision
procedure for integrating elementary functions, i.e., the algorithm can
either find an elementary antiderivative, or prove that one does not
exist.  There is also a (very successful, albeit somewhat slow) general
implementation of the heuristic Risch algorithm.  This algorithm will
eventually be phased out as more of the full Risch algorithm is
implemented. See the docstring of Integral._eval_integral() for more
details on computing the antiderivative using algebraic methods.

The option risch=True can be used to use only the (full) Risch algorithm.
This is useful if you want to know if an elementary function has an
elementary antiderivative.  If the indefinite Integral returned by this
function is an instance of NonElementaryIntegral, that means that the
Risch algorithm has proven that integral to be non-elementary.  Note that
by default, additional methods (such as the Meijer G method outlined
below) are tried on these integrals, as they may be expressible in terms
of special functions, so if you only care about elementary answers, use
risch=True.  Also note that an unevaluated Integral returned by this
function is not necessarily a NonElementaryIntegral, even with risch=True,
as it may just be an indication that the particular part of the Risch
algorithm needed to integrate that function is not yet implemented.

Another family of strategies comes from re-writing the integrand in
terms of so-called Meijer G-functions. Indefinite integrals of a
single G-function can always be computed, and the definite integral
of a product of two G-functions can be computed from zero to
infinity. Various strategies are implemented to rewrite integrands
as G-functions, and use this information to compute integrals (see
the ``meijerint`` module).

The option manual=True can be used to use only an algorithm that tries
to mimic integration by hand. This algorithm does not handle as many
integrands as the other algorithms implemented but may return results in
a more familiar form. The ``manualintegrate`` module has functions that
return the steps used (see the module docstring for more information).

In general, the algebraic methods work best for computing
antiderivatives of (possibly complicated) combinations of elementary
functions. The G-function methods work best for computing definite
integrals from zero to infinity of moderately complicated
combinations of special functions, or indefinite integrals of very
simple combinations of special functions.

The strategy employed by the integration code is as follows:

- If computing a definite integral, and both limits are real,
  and at least one limit is +- oo, try the G-function method of
  definite integration first.

- Try to find an antiderivative, using all available methods, ordered
  by performance (that is try fastest method first, slowest last; in
  particular polynomial integration is tried first, Meijer
  G-functions second to last, and heuristic Risch last).

- If still not successful, try G-functions irrespective of the
  limits.

The option meijerg=True, False, None can be used to, respectively:
always use G-function methods and no others, never use G-function
methods, or use all available methods (in order as described above).
It defaults to None.

Examples
========

>>> from sympy import integrate, log, exp, oo
>>> from sympy.abc import a, x, y

>>> integrate(x*y, x)
x**2*y/2

>>> integrate(log(x), x)
x*log(x) - x

>>> integrate(log(x), (x, 1, a))
a*log(a) - a + 1

>>> integrate(x)
x**2/2

Terms that are independent of x are dropped by indefinite integration:

>>> from sympy import sqrt
>>> integrate(sqrt(1 + x), (x, 0, x))
2*(x + 1)**(3/2)/3 - 2/3
>>> integrate(sqrt(1 + x), x)
2*(x + 1)**(3/2)/3

>>> integrate(x*y)
Traceback (most recent call last):
...
ValueError: specify integration variables to integrate x*y

Note that ``integrate(x)`` syntax is meant only for convenience
in interactive sessions and should be avoided in library code.

>>> integrate(x**a*exp(-x), (x, 0, oo)) # same as conds='piecewise'
Piecewise((gamma(a + 1), re(a) > -1),
    (Integral(x**a*exp(-x), (x, 0, oo)), True))

>>> integrate(x**a*exp(-x), (x, 0, oo), conds='none')
gamma(a + 1)

>>> integrate(x**a*exp(-x), (x, 0, oo), conds='separate')
(gamma(a + 1), re(a) > -1)

See Also
========

Integral, Integral.doit
File:      c:\users\16302\appdata\local\programs\python\python312\lib\site-packages\sympy\integrals\integrals.py
Type:      function