The integrals module in SymPy implements methods to calculate definite and indefinite integrals of expressions.
Principal method in this module is integrate()
- integrate(f, x) returns the indefinite integral \(\int f\,dx\)
- integrate(f, (x, a, b)) returns the definite integral \(\int_{a}^{b} f\,dx\)
SymPy can integrate a vast array of functions. It can integrate polynomial functions:
>>> from sympy import *
>>> init_printing(use_unicode=False, wrap_line=False, no_global=True)
>>> x = Symbol('x')
>>> integrate(x**2 + x + 1, x)
3 2
x x
-- + -- + x
3 2
Rational functions:
>>> integrate(x/(x**2+2*x+1), x)
1
log(x + 1) + -----
x + 1
Exponential-polynomial functions. Multiplicative combinations of polynomials and the functions exp, cos and sin can be integrated by hand using repeated integration by parts, which is an extremely tedious process. Happily, SymPy will deal with these integrals.
>>> integrate(x**2 * exp(x) * cos(x), x)
2 x 2 x x x
x *e *sin(x) x *e *cos(x) x e *sin(x) e *cos(x)
------------ + ------------ - x*e *sin(x) + --------- - ---------
2 2 2 2
even a few nonelementary integrals (in particular, some integrals involving the error function) can be evaluated:
>>> integrate(exp(-x**2)*erf(x), x)
____ 2
\/ pi *erf (x)
--------------
4
SymPy has special support for definite integrals, and integral transforms.
Compute the Mellin transform \(F(s)\) of \(f(x)\),
The Mellin transform is related via change of variables to the Fourier transform, and also to the (bilateral) Laplace transform.
This function returns (F, (a, b), cond) where \(F\) is the Mellin transform of \(f\), \((a, b)\) is the fundamental strip (as above), and cond are auxiliary convergence conditions.
If the integral cannot be computed in closed form, this function returns an unevaluated MellinTransform object.
For a description of possible hints, refer to the docstring of sympy.integrals.transforms.IntegralTransform.doit(). If noconds=False, then only \(F\) will be returned (i.e. not cond, and also not the strip (a, b)).
>>> from sympy.integrals.transforms import mellin_transform
>>> from sympy import exp
>>> from sympy.abc import x, s
>>> mellin_transform(exp(-x), x, s)
(gamma(s), (0, oo), True)
Compute the inverse Mellin transform of \(F(s)\) over the fundamental strip given by strip=(a, b).
This can be defined as
for any \(c\) in the fundamental strip. Under certain regularity conditions on \(F\) and/or \(f\), this recovers \(f\) from its Mellin transform \(F\) (and vice versa), for positive real \(x\).
One of \(a\) or \(b\) may be passed as None; a suitable \(c\) will be inferred.
If the integral cannot be computed in closed form, this function returns an unevaluated InverseMellinTransform object.
Note that this function will assume x to be positive and real, regardless of the sympy assumptions!
For a description of possible hints, refer to the docstring of sympy.integrals.transforms.IntegralTransform.doit().
>>> from sympy.integrals.transforms import inverse_mellin_transform
>>> from sympy import oo, gamma
>>> from sympy.abc import x, s
>>> inverse_mellin_transform(gamma(s), s, x, (0, oo))
exp(-x)
The fundamental strip matters:
>>> f = 1/(s**2 - 1)
>>> inverse_mellin_transform(f, s, x, (-oo, -1))
x*(1 - 1/x**2)*Heaviside(x - 1)/2
>>> inverse_mellin_transform(f, s, x, (-1, 1))
-x*Heaviside(-x + 1)/2 - Heaviside(x - 1)/(2*x)
>>> inverse_mellin_transform(f, s, x, (1, oo))
(-x**2/2 + 1/2)*Heaviside(-x + 1)/x
Compute the Laplace Transform \(F(s)\) of \(f(t)\),
For all “sensible” functions, this converges absolutely in a half plane \(a < Re(s)\).
This function returns (F, a, cond) where \(F\) is the Laplace transform of \(f\), \(Re(s) > a\) is the half-plane of convergence, and cond are auxiliary convergence conditions.
If the integral cannot be computed in closed form, this function returns an unevaluated LaplaceTransform object.
For a description of possible hints, refer to the docstring of sympy.integrals.transforms.IntegralTransform.doit(). If noconds=True, only \(F\) will be returned (i.e. not cond, and also not the plane a).
>>> from sympy.integrals import laplace_transform
>>> from sympy.abc import t, s, a
>>> laplace_transform(t**a, t, s)
(s**(-a - 1)*gamma(a + 1), 0, -re(a) < 1)
Compute the inverse Laplace transform of \(F(s)\), defined as
for \(c\) so large that \(F(s)\) has no singularites in the half-plane \(Re(s) > c-\epsilon\).
The plane can be specified by argument plane, but will be inferred if passed as None.
Under certain regularity conditions, this recovers \(f(t)\) from its Laplace Transform \(F(s)\), for non-negative \(t\), and vice versa.
If the integral cannot be computed in closed form, this function returns an unevaluated InverseLaplaceTransform object.
Note that this function will always assume \(t\) to be real, regardless of the sympy assumption on \(t\).
For a description of possible hints, refer to the docstring of sympy.integrals.transforms.IntegralTransform.doit().
>>> from sympy.integrals.transforms import inverse_laplace_transform
>>> from sympy import exp, Symbol
>>> from sympy.abc import s, t
>>> a = Symbol('a', positive=True)
>>> inverse_laplace_transform(exp(-a*s)/s, s, t)
Heaviside(-a + t)
Compute the unitary, ordinary-frequency Fourier transform of \(f\), defined as
If the transform cannot be computed in closed form, this function returns an unevaluated FourierTransform object.
For other Fourier transform conventions, see the function sympy.integrals.transforms._fourier_transform().
For a description of possible hints, refer to the docstring of sympy.integrals.transforms.IntegralTransform.doit(). Note that for this transform, by default noconds=True.
>>> from sympy import fourier_transform, exp
>>> from sympy.abc import x, k
>>> fourier_transform(exp(-x**2), x, k)
sqrt(pi)*exp(-pi**2*k**2)
>>> fourier_transform(exp(-x**2), x, k, noconds=False)
(sqrt(pi)*exp(-pi**2*k**2), True)
Compute the unitary, ordinary-frequency inverse Fourier transform of \(F\), defined as
If the transform cannot be computed in closed form, this function returns an unevaluated InverseFourierTransform object.
For other Fourier transform conventions, see the function sympy.integrals.transforms._fourier_transform().
For a description of possible hints, refer to the docstring of sympy.integrals.transforms.IntegralTransform.doit(). Note that for this transform, by default noconds=True.
>>> from sympy import inverse_fourier_transform, exp, sqrt, pi
>>> from sympy.abc import x, k
>>> inverse_fourier_transform(sqrt(pi)*exp(-(pi*k)**2), k, x)
exp(-x**2)
>>> inverse_fourier_transform(sqrt(pi)*exp(-(pi*k)**2), k, x, noconds=False)
(exp(-x**2), True)
Compute the unitary, ordinary-frequency sine transform of \(f\), defined as
If the transform cannot be computed in closed form, this function returns an unevaluated SineTransform object.
For a description of possible hints, refer to the docstring of sympy.integrals.transforms.IntegralTransform.doit(). Note that for this transform, by default noconds=True.
>>> from sympy import sine_transform, exp
>>> from sympy.abc import x, k, a
>>> sine_transform(x*exp(-a*x**2), x, k)
sqrt(2)*k*exp(-k**2/(4*a))/(4*a**(3/2))
>>> sine_transform(x**(-a), x, k)
2**(-a + 1/2)*k**(a - 1)*gamma(-a/2 + 1)/gamma(a/2 + 1/2)
Compute the unitary, ordinary-frequency inverse sine transform of \(F\), defined as
If the transform cannot be computed in closed form, this function returns an unevaluated InverseSineTransform object.
For a description of possible hints, refer to the docstring of sympy.integrals.transforms.IntegralTransform.doit(). Note that for this transform, by default noconds=True.
>>> from sympy import inverse_sine_transform, exp, sqrt, gamma, pi
>>> from sympy.abc import x, k, a
>>> inverse_sine_transform(2**((1-2*a)/2)*k**(a - 1)*gamma(-a/2 + 1)/gamma((a+1)/2), k, x)
x**(-a)
>>> inverse_sine_transform(sqrt(2)*k*exp(-k**2/(4*a))/(4*sqrt(a)**3), k, x)
x*exp(-a*x**2)
Compute the unitary, ordinary-frequency cosine transform of \(f\), defined as
If the transform cannot be computed in closed form, this function returns an unevaluated CosineTransform object.
For a description of possible hints, refer to the docstring of sympy.integrals.transforms.IntegralTransform.doit(). Note that for this transform, by default noconds=True.
>>> from sympy import cosine_transform, exp, sqrt, cos
>>> from sympy.abc import x, k, a
>>> cosine_transform(exp(-a*x), x, k)
sqrt(2)*a/(sqrt(pi)*(a**2 + k**2))
>>> cosine_transform(exp(-a*sqrt(x))*cos(a*sqrt(x)), x, k)
a*(-sinh(a**2/(2*k)) + cosh(a**2/(2*k)))/(2*k**(3/2))
Compute the unitary, ordinary-frequency inverse cosine transform of \(F\), defined as
If the transform cannot be computed in closed form, this function returns an unevaluated InverseCosineTransform object.
For a description of possible hints, refer to the docstring of sympy.integrals.transforms.IntegralTransform.doit(). Note that for this transform, by default noconds=True.
>>> from sympy import inverse_cosine_transform, exp, sqrt, pi
>>> from sympy.abc import x, k, a
>>> inverse_cosine_transform(sqrt(2)*a/(sqrt(pi)*(a**2 + k**2)), k, x)
-sinh(a*x) + cosh(a*x)
>>> inverse_cosine_transform(1/sqrt(k), k, x)
1/sqrt(x)
Compute the Hankel transform of \(f\), defined as
If the transform cannot be computed in closed form, this function returns an unevaluated HankelTransform object.
For a description of possible hints, refer to the docstring of sympy.integrals.transforms.IntegralTransform.doit(). Note that for this transform, by default noconds=True.
>>> from sympy import hankel_transform, inverse_hankel_transform
>>> from sympy import gamma, exp, sinh, cosh
>>> from sympy.abc import r, k, m, nu, a
>>> ht = hankel_transform(1/r**m, r, k, nu)
>>> ht
2**(-m + 1)*k**(m - 2)*gamma(-m/2 + nu/2 + 1)/gamma(m/2 + nu/2)
>>> inverse_hankel_transform(ht, k, r, nu)
r**(-m)
>>> ht = hankel_transform(exp(-a*r), r, k, 0)
>>> ht
a/(k**3*(a**2/k**2 + 1)**(3/2))
>>> inverse_hankel_transform(ht, k, r, 0)
-sinh(a*r) + cosh(a*r)
Compute the inverse Hankel transform of \(F\) defined as
If the transform cannot be computed in closed form, this function returns an unevaluated InverseHankelTransform object.
For a description of possible hints, refer to the docstring of sympy.integrals.transforms.IntegralTransform.doit(). Note that for this transform, by default noconds=True.
>>> from sympy import hankel_transform, inverse_hankel_transform, gamma
>>> from sympy import gamma, exp, sinh, cosh
>>> from sympy.abc import r, k, m, nu, a
>>> ht = hankel_transform(1/r**m, r, k, nu)
>>> ht
2**(-m + 1)*k**(m - 2)*gamma(-m/2 + nu/2 + 1)/gamma(m/2 + nu/2)
>>> inverse_hankel_transform(ht, k, r, nu)
r**(-m)
>>> ht = hankel_transform(exp(-a*r), r, k, 0)
>>> ht
a/(k**3*(a**2/k**2 + 1)**(3/2))
>>> inverse_hankel_transform(ht, k, r, 0)
-sinh(a*r) + cosh(a*r)
There is a general method for calculating antiderivatives of elementary functions, called the Risch algorithm. The Risch algorithm is a decision procedure that can determine whether an elementary solution exists, and in that case calculate it. It can be extended to handle many nonelementary functions in addition to the elementary ones.
SymPy currently uses a simplified version of the Risch algorithm, called the Risch-Norman algorithm. This algorithm is much faster, but may fail to find an antiderivative, although it is still very powerful. SymPy also uses pattern matching and heuristics to speed up evaluation of some types of integrals, e.g. polynomials.
For non-elementary definite integrals, sympy uses so-called Meijer G-functions. Details are described here:
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
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 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. There is also a (very successful, albeit somewhat slow) general implementation of the heuristic risch algorithm. See the docstring of Integral._eval_integral() for more details on computing the antiderivative using algebraic methods.
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).
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:
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.
See also
Integral, Integral.doit
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)
Compute the line integral.
See also
integrate, Integral
Examples
>>> from sympy import Curve, line_integrate, E, ln
>>> from sympy.abc import x, y, t
>>> C = Curve([E**t + 1, E**t - 1], (t, 0, ln(2)))
>>> line_integrate(x + y, C, [x, y])
3*sqrt(2)
The idea for integration is the following:
If we are dealing with a DiracDelta expression, i.e. DiracDelta(g(x)), we try to simplify it.
If we could simplify it, then we integrate the resulting expression. We already know we can integrate a simplified expression, because only simple DiracDelta expressions are involved.
If we couldn’t simplify it, there are two cases:
If the node is a multiplication node having a DiracDelta term:
First we expand it.
If the expansion did work, the we try to integrate the expansion.
If not, we try to extract a simple DiracDelta term, then we have two cases:
See also
sympy.functions.special.delta_functions.DiracDelta, sympy.integrals.integrals.Integral
Examples
>>> from sympy.abc import x, y, z
>>> from sympy.integrals.deltafunctions import deltaintegrate
>>> from sympy import sin, cos, DiracDelta, Heaviside
>>> deltaintegrate(x*sin(x)*cos(x)*DiracDelta(x - 1), x)
sin(1)*cos(1)*Heaviside(x - 1)
>>> deltaintegrate(y**2*DiracDelta(x - z)*DiracDelta(y - z), y)
z**2*DiracDelta(x - z)*Heaviside(y - z)
Performs indefinite integration of rational functions.
Given a field \(K\) and a rational function \(f = p/q\), where \(p\) and \(q\) are polynomials in \(K[x]\), returns a function \(g\) such that \(f = g'\).
>>> from sympy.integrals.rationaltools import ratint
>>> from sympy.abc import x
>>> ratint(36/(x**5 - 2*x**4 - 2*x**3 + 4*x**2 + x - 2), x)
(12*x + 6)/(x**2 - 1) + 4*log(x - 2) - 4*log(x + 1)
See also
sympy.integrals.integrals.Integral.doit, ratint_logpart, ratint_ratpart
References
[Bro05] | M. Bronstein, Symbolic Integration I: Transcendental Functions, Second Edition, Springer-Verlag, 2005, pp. 35-70 |
Compute indefinite integral using heuristic Risch algorithm.
This is a heuristic approach to indefinite integration in finite terms using the extended heuristic (parallel) Risch algorithm, based on Manuel Bronstein’s “Poor Man’s Integrator”.
The algorithm supports various classes of functions including transcendental elementary or special functions like Airy, Bessel, Whittaker and Lambert.
Note that this algorithm is not a decision procedure. If it isn’t able to compute the antiderivative for a given function, then this is not a proof that such a functions does not exist. One should use recursive Risch algorithm in such case. It’s an open question if this algorithm can be made a full decision procedure.
This is an internal integrator procedure. You should use toplevel ‘_integrate’ function in most cases, as this procedure needs some preprocessing steps and otherwise may fail.
Specification
heurisch(f, x, rewrite=False, hints=None)
- where
f : expression x : symbol
rewrite -> force rewrite ‘f’ in terms of ‘tan’ and ‘tanh’ hints -> a list of functions that may appear in anti-derivate
- hints = None –> no suggestions at all
- hints = [ ] –> try to figure out
- hints = [f1, ..., fn] –> we know better
See also
sympy.integrals.integrals.Integral.doit, sympy.integrals.integrals.Integral, components
Examples
>>> from sympy import tan
>>> from sympy.integrals.risch import heurisch
>>> from sympy.abc import x, y
>>> heurisch(y*tan(x), x)
y*log(tan(x)**2 + 1)/2
See Manuel Bronstein’s “Poor Man’s Integrator”:
[1] http://www-sop.inria.fr/cafe/Manuel.Bronstein/pmint/index.html
For more information on the implemented algorithm refer to:
Integrate f = Mul(trig) over x
>>> from sympy import Symbol, sin, cos, tan, sec, csc, cot >>> from sympy.integrals.trigonometry import trigintegrate >>> from sympy.abc import x>>> trigintegrate(sin(x)*cos(x), x) sin(x)**2/2>>> trigintegrate(sin(x)**2, x) x/2 - sin(x)*cos(x)/2>>> trigintegrate(tan(x)*sec(x), x) 1/cos(x)>>> trigintegrate(sin(x)*tan(x), x) -log(sin(x) - 1)/2 + log(sin(x) + 1)/2 - sin(x)http://en.wikibooks.org/wiki/Calculus/Further_integration_techniques
See also
sympy.integrals.integrals.Integral.doit, sympy.integrals.integrals.Integral
Class Integral represents an unevaluated integral and has some methods that help in the integration of an expression.
Represents unevaluated integral.
Returns whether all the free symbols in the integral are commutative.
Replace instances of the integration variables with their dummy counterparts to make clear what are dummy variables and what are real-world symbols in an Integral.
>>> from sympy import Integral
>>> from sympy.abc import x, y
>>> Integral(x, (x, x, y), (y, x, y)).as_dummy()
Integral(_x, (_x, x, _y), (_y, x, y))
The “integral at” limit that has a length of 1 is not treated as though the integration symbol is a dummy, but the explicit form of length 2 does treat the integration variable as a dummy.
>>> Integral(x, x).as_dummy()
Integral(x, x)
>>> Integral(x, (x, x)).as_dummy()
Integral(_x, (_x, x))
If there were no dummies in the original expression, then the output of this function will show which symbols cannot be changed by subs(), those with an underscore prefix.
See also
Approximates the integral by a sum.
method ... one of: left, right, midpoint
This is basically just the rectangle method [1], the only difference is where the function value is taken in each interval.
[1] http://en.wikipedia.org/wiki/Rectangle_method
method = midpoint:
Uses the n-order midpoint rule to evaluate the integral.
Midpoint rule uses rectangles approximation for the given area (e.g. definite integral) of the function with heights equal to the point on the curve exactly in the middle of each interval (thus midpoint method). See [1] for more information.
See also
Examples
>>> from sympy import sqrt
>>> from sympy.abc import x
>>> e = Integral(sqrt(x**3+1), (x, 2, 10))
>>> e
Integral(sqrt(x**3 + 1), (x, 2, 10))
>>> e.as_sum(4, method="left")
6 + 2*sqrt(65) + 2*sqrt(217) + 6*sqrt(57)
>>> e.as_sum(4, method="left").n()
96.8853618335341
>>> e.n()
124.616199194723
Perform the integration using any hints given.
See also
sympy.integrals.trigonometry.trigintegrate, sympy.integrals.risch.heurisch, sympy.integrals.rationaltools.ratint
Examples
>>> from sympy import Integral
>>> from sympy.abc import x, i
>>> Integral(x**i, (i, 1, 3)).doit()
x**3/log(x) - x/log(x)
This method returns the symbols that will exist when the integral is evaluated. This is useful if one is trying to determine whether an integral depends on a certain symbol or not.
See also
function, limits, variables
Examples
>>> from sympy import Integral
>>> from sympy.abc import x, y
>>> Integral(x, (x, y, 1)).free_symbols
set([y])
Return the function to be integrated.
See also
limits, variables, free_symbols
Examples
>>> from sympy import Integral
>>> from sympy.abc import x
>>> Integral(x**2, (x,)).function
x**2
Return True if the Integral will result in a number, else False.
sympy considers anything that will result in a number to have is_number == True.
>>> from sympy import log
>>> log(2).is_number
True
Integrals are a special case since they contain symbols that can be replaced with numbers. Whether the integral can be done or not is another issue. But answering whether the final result is a number is not difficult.
>>> from sympy import Integral
>>> from sympy.abc import x, y
>>> Integral(x).is_number
False
>>> Integral(x, y).is_number
False
>>> Integral(x, (y, 1, x)).is_number
False
>>> Integral(x, (y, 1, 2)).is_number
False
>>> Integral(x, (y, 1, 1)).is_number
True
>>> Integral(x, (x, 1, 2)).is_number
True
>>> Integral(x*y, (x, 1, 2), (y, 1, 3)).is_number
True
>>> Integral(1, x, (x, 1, 2)).is_number
True
See also
is_zero
Since Integral doesn’t autosimplify it it useful to see if it would simplify to zero or not in a trivial manner, i.e. when the function is 0 or two limits of a definite integral are the same.
This is a very naive and quick test, not intended to check for special patterns like Integral(sin(m*x)*cos(n*x), (x, 0, 2*pi)) == 0.
See also
is_number
Examples
>>> from sympy import Integral
>>> from sympy.abc import x, y, z
>>> Integral(1, (x, 1, 1)).is_zero
True
>>> Integral(0, (x, y, z)).is_zero
True
>>> Integral(1, (x, 1, 2)).is_zero
False
Return the limits of integration.
See also
function, variables, free_symbols
Examples
>>> from sympy import Integral
>>> from sympy.abc import x, i
>>> Integral(x**i, (i, 1, 3)).limits
((i, 1, 3),)
Performs a change of variables from \(x\) to \(u\) using the relationship given by \(x\) and \(u\) which will define the transformations \(f\) and \(F\) (which are inverses of each other) as follows:
The \(inverse\) option will reverse \(x\) and \(u\). It is a deprecated option since \(x\) and \(u\) can just be passed in reverse order.
Once f and F have been identified, the transformation is made as follows:
where \(F(x)\) is the inverse of \(f(x)\) and the limits and integrand have been corrected so as to retain the same value after integration.
See also
Notes
The mappings, F(x) or f(u), must lead to a unique integral. Linear or rational linear expression, \(2*x\), \(1/x\) and \(sqrt(x)\), will always work; quadratic expressions like \(x**2 - 1\) are acceptable as long as the resulting integrand does not depend on the sign of the solutions (see examples).
The integral will be returned unchanged if \(x\) is not a variable of integration.
\(x\) must be (or contain) only one of of the integration variables. If \(u\) has more than one free symbol then it should be sent as a tuple (\(u\), \(uvar\)) where \(uvar\) identifies which variable is replacing the integration variable. XXX can it contain another integration variable?
Examples
>>> from sympy.abc import a, b, c, d, x, u, y
>>> from sympy import Integral, S, cos, sqrt
>>> i = Integral(x*cos(x**2 - 1), (x, 0, 1))
transform can change the variable of integration
>>> i.transform(x, u)
Integral(u*cos(u**2 - 1), (u, 0, 1))
transform can perform u-substitution as long as a unique integrand is obtained:
>>> i.transform(x**2 - 1, u)
Integral(cos(u)/2, (u, -1, 0))
This attempt fails because x = +/-sqrt(u + 1) and the sign does not cancel out of the integrand:
>>> Integral(cos(x**2 - 1), (x, 0, 1)).transform(x**2 - 1, u)
Traceback (most recent call last):
...
ValueError:
The mapping between F(x) and f(u) did not give a unique integrand.
transform can do a substitution. Here, the previous result is transformed back into the original expression using “u-substitution”:
>>> ui = _
>>> _.transform(sqrt(u + 1), x) == i
True
We can accomplish the same with a regular substitution:
>>> ui.transform(u, x**2 - 1) == i
True
If the \(x\) does not contain a symbol of integration then the integral will be returned unchanged. Integral \(i\) does not have an integration variable \(a\) so no change is made:
>>> i.transform(a, x) == i
True
When \(u\) has more than one free symbol the symbol that is replacing \(x\) must be identified by passing \(u\) as a tuple:
>>> Integral(x, (x, 0, 1)).transform(x, (u + a, u))
Integral(a + u, (u, -a, -a + 1))
>>> Integral(x, (x, 0, 1)).transform(x, (u + a, a))
Integral(a + u, (a, -u, -u + 1))
Return a list of the integration variables.
See also
function, limits, free_symbols
Examples
>>> from sympy import Integral
>>> from sympy.abc import x, i
>>> Integral(x**i, (i, 1, 3)).variables
[i]
There are still lots of functions that sympy does not know how to integrate. For bugs related to this module, see http://code.google.com/p/sympy/issues/list?q=label:Integration