Calculus¶
Calculus-related methods.
This module implements a method to find Euler-Lagrange Equations for given Lagrangian.
-
sympy.calculus.euler.
euler_equations
(L, funcs=(), vars=())[source]¶ Find the Euler-Lagrange equations [R22] for a given Lagrangian.
- Parameters
L : Expr
The Lagrangian that should be a function of the functions listed in the second argument and their derivatives.
For example, in the case of two functions \(f(x,y)\), \(g(x,y)\) and two independent variables \(x\), \(y\) the Lagrangian would have the form:
\[L\left(f(x,y),g(x,y),\frac{\partial f(x,y)}{\partial x}, \frac{\partial f(x,y)}{\partial y}, \frac{\partial g(x,y)}{\partial x}, \frac{\partial g(x,y)}{\partial y},x,y\right)\]In many cases it is not necessary to provide anything, except the Lagrangian, it will be auto-detected (and an error raised if this couldn’t be done).
funcs : Function or an iterable of Functions
The functions that the Lagrangian depends on. The Euler equations are differential equations for each of these functions.
vars : Symbol or an iterable of Symbols
The Symbols that are the independent variables of the functions.
- Returns
eqns : list of Eq
The list of differential equations, one for each function.
References
Examples
>>> from sympy import Symbol, Function >>> from sympy.calculus.euler import euler_equations >>> x = Function('x') >>> t = Symbol('t') >>> L = (x(t).diff(t))**2/2 - x(t)**2/2 >>> euler_equations(L, x(t), t) [Eq(-x(t) - Derivative(x(t), (t, 2)), 0)] >>> u = Function('u') >>> x = Symbol('x') >>> L = (u(t, x).diff(t))**2/2 - (u(t, x).diff(x))**2/2 >>> euler_equations(L, u(t, x), [t, x]) [Eq(-Derivative(u(t, x), (t, 2)) + Derivative(u(t, x), (x, 2)), 0)]
Singularities¶
This module implements algorithms for finding singularities for a function and identifying types of functions.
The differential calculus methods in this module include methods to identify
the following function types in the given Interval
:
- Increasing
- Strictly Increasing
- Decreasing
- Strictly Decreasing
- Monotonic
-
sympy.calculus.singularities.
is_decreasing
(expression, interval=Reals, symbol=None)[source]¶ Return whether the function is decreasing in the given interval.
Examples
>>> from sympy import is_decreasing >>> from sympy.abc import x, y >>> from sympy import S, Interval, oo >>> is_decreasing(1/(x**2 - 3*x), Interval.open(1.5, 3)) True >>> is_decreasing(1/(x**2 - 3*x), Interval.Lopen(3, oo)) True >>> is_decreasing(1/(x**2 - 3*x), Interval.Ropen(-oo, S(3)/2)) False >>> is_decreasing(-x**2, Interval(-oo, 0)) False >>> is_decreasing(-x**2 + y, Interval(-oo, 0), x) False
-
sympy.calculus.singularities.
is_increasing
(expression, interval=Reals, symbol=None)[source]¶ Return whether the function is increasing in the given interval.
Examples
>>> from sympy import is_increasing >>> from sympy.abc import x, y >>> from sympy import S, Interval, oo >>> is_increasing(x**3 - 3*x**2 + 4*x, S.Reals) True >>> is_increasing(-x**2, Interval(-oo, 0)) True >>> is_increasing(-x**2, Interval(0, oo)) False >>> is_increasing(4*x**3 - 6*x**2 - 72*x + 30, Interval(-2, 3)) False >>> is_increasing(x**2 + y, Interval(1, 2), x) True
-
sympy.calculus.singularities.
is_monotonic
(expression, interval=Reals, symbol=None)[source]¶ Return whether the function is monotonic in the given interval.
Examples
>>> from sympy import is_monotonic >>> from sympy.abc import x, y >>> from sympy import S, Interval, oo >>> is_monotonic(1/(x**2 - 3*x), Interval.open(1.5, 3)) True >>> is_monotonic(1/(x**2 - 3*x), Interval.Lopen(3, oo)) True >>> is_monotonic(x**3 - 3*x**2 + 4*x, S.Reals) True >>> is_monotonic(-x**2, S.Reals) False >>> is_monotonic(x**2 + y + 1, Interval(1, 2), x) True
-
sympy.calculus.singularities.
is_strictly_decreasing
(expression, interval=Reals, symbol=None)[source]¶ Return whether the function is strictly decreasing in the given interval.
Examples
>>> from sympy import is_strictly_decreasing >>> from sympy.abc import x, y >>> from sympy import S, Interval, oo >>> is_strictly_decreasing(1/(x**2 - 3*x), Interval.Lopen(3, oo)) True >>> is_strictly_decreasing(1/(x**2 - 3*x), Interval.Ropen(-oo, S(3)/2)) False >>> is_strictly_decreasing(-x**2, Interval(-oo, 0)) False >>> is_strictly_decreasing(-x**2 + y, Interval(-oo, 0), x) False
-
sympy.calculus.singularities.
is_strictly_increasing
(expression, interval=Reals, symbol=None)[source]¶ Return whether the function is strictly increasing in the given interval.
Examples
>>> from sympy import is_strictly_increasing >>> from sympy.abc import x, y >>> from sympy import Interval, oo >>> is_strictly_increasing(4*x**3 - 6*x**2 - 72*x + 30, Interval.Ropen(-oo, -2)) True >>> is_strictly_increasing(4*x**3 - 6*x**2 - 72*x + 30, Interval.Lopen(3, oo)) True >>> is_strictly_increasing(4*x**3 - 6*x**2 - 72*x + 30, Interval.open(-2, 3)) False >>> is_strictly_increasing(-x**2, Interval(0, oo)) False >>> is_strictly_increasing(-x**2 + y, Interval(-oo, 0), x) False
-
sympy.calculus.singularities.
monotonicity_helper
(expression, predicate, interval=Reals, symbol=None)[source]¶ Helper function for functions checking function monotonicity.
It returns a boolean indicating whether the interval in which the function’s derivative satisfies given predicate is a superset of the given interval.
-
sympy.calculus.singularities.
singularities
(expression, symbol)[source]¶ Find singularities of a given function.
Currently supported functions are: - univariate rational (real or complex) functions
Notes
This function does not find nonisolated singularities nor does it find branch points of the expression.
References
Examples
>>> from sympy.calculus.singularities import singularities >>> from sympy import Symbol >>> x = Symbol('x', real=True) >>> y = Symbol('y', real=False) >>> singularities(x**2 + x + 1, x) EmptySet() >>> singularities(1/(x + 1), x) {-1} >>> singularities(1/(y**2 + 1), y) {-I, I} >>> singularities(1/(y**3 + 1), y) {-1, 1/2 - sqrt(3)*I/2, 1/2 + sqrt(3)*I/2}
Finite difference weights¶
This module implements an algorithm for efficient generation of finite difference weights for ordinary differentials of functions for derivatives from 0 (interpolation) up to arbitrary order.
The core algorithm is provided in the finite difference weight generating
function (finite_diff_weights
), and two convenience functions are provided
for:
- estimating a derivative (or interpolate) directly from a series of points
is also provided (
apply_finite_diff
).
- differentiating by using finite difference approximations
(
differentiate_finite
).
-
sympy.calculus.finite_diff.
apply_finite_diff
(order, x_list, y_list, x0=0)[source]¶ Calculates the finite difference approximation of the derivative of requested order at
x0
from points provided inx_list
andy_list
.- Parameters
order: int
order of derivative to approximate. 0 corresponds to interpolation.
x_list: sequence
Sequence of (unique) values for the independent variable.
y_list: sequence
The function value at corresponding values for the independent variable in x_list.
x0: Number or Symbol
At what value of the independent variable the derivative should be evaluated. Defaults to S(0).
- Returns
sympy.core.add.Add or sympy.core.numbers.Number
The finite difference expression approximating the requested derivative order at
x0
.
Notes
Order = 0 corresponds to interpolation. Only supply so many points you think makes sense to around x0 when extracting the derivative (the function need to be well behaved within that region). Also beware of Runge’s phenomenon.
References
Fortran 90 implementation with Python interface for numerics: finitediff
Examples
>>> from sympy.calculus import apply_finite_diff >>> cube = lambda arg: (1.0*arg)**3 >>> xlist = range(-3,3+1) >>> apply_finite_diff(2, xlist, map(cube, xlist), 2) - 12 -3.55271367880050e-15
we see that the example above only contain rounding errors. apply_finite_diff can also be used on more abstract objects:
>>> from sympy import IndexedBase, Idx >>> from sympy.calculus import apply_finite_diff >>> x, y = map(IndexedBase, 'xy') >>> i = Idx('i') >>> x_list, y_list = zip(*[(x[i+j], y[i+j]) for j in range(-1,2)]) >>> apply_finite_diff(1, x_list, y_list, x[i]) ((x[i + 1] - x[i])/(-x[i - 1] + x[i]) - 1)*y[i]/(x[i + 1] - x[i]) - (x[i + 1] - x[i])*y[i - 1]/((x[i + 1] - x[i - 1])*(-x[i - 1] + x[i])) + (-x[i - 1] + x[i])*y[i + 1]/((x[i + 1] - x[i - 1])*(x[i + 1] - x[i]))
-
sympy.calculus.finite_diff.
as_finite_diff
(derivative, points=1, x0=None, wrt=None)¶ Returns an approximation of a derivative of a function in the form of a finite difference formula. The expression is a weighted sum of the function at a number of discrete values of (one of) the independent variable(s).
- Parameters
derivative: a Derivative instance
points: sequence or coefficient, optional
If sequence: discrete values (length >= order+1) of the independent variable used for generating the finite difference weights. If it is a coefficient, it will be used as the step-size for generating an equidistant sequence of length order+1 centered around
x0
. default: 1 (step-size 1)x0: number or Symbol, optional
the value of the independent variable (
wrt
) at which the derivative is to be approximated. Default: same aswrt
.wrt: Symbol, optional
“with respect to” the variable for which the (partial) derivative is to be approximated for. If not provided it is required that the Derivative is ordinary. Default:
None
.
See also
sympy.calculus.finite_diff.apply_finite_diff
,sympy.calculus.finite_diff.finite_diff_weights
Examples
>>> from sympy import symbols, Function, exp, sqrt, Symbol, as_finite_diff >>> from sympy.utilities.exceptions import SymPyDeprecationWarning >>> import warnings >>> warnings.simplefilter("ignore", SymPyDeprecationWarning) >>> x, h = symbols('x h') >>> f = Function('f') >>> as_finite_diff(f(x).diff(x)) -f(x - 1/2) + f(x + 1/2)
The default step size and number of points are 1 and
order + 1
respectively. We can change the step size by passing a symbol as a parameter:>>> as_finite_diff(f(x).diff(x), h) -f(-h/2 + x)/h + f(h/2 + x)/h
We can also specify the discretized values to be used in a sequence:
>>> as_finite_diff(f(x).diff(x), [x, x+h, x+2*h]) -3*f(x)/(2*h) + 2*f(h + x)/h - f(2*h + x)/(2*h)
The algorithm is not restricted to use equidistant spacing, nor do we need to make the approximation around
x0
, but we can get an expression estimating the derivative at an offset:>>> e, sq2 = exp(1), sqrt(2) >>> xl = [x-h, x+h, x+e*h] >>> as_finite_diff(f(x).diff(x, 1), xl, x+h*sq2) 2*h*((h + sqrt(2)*h)/(2*h) - (-sqrt(2)*h + h)/(2*h))*f(E*h + x)/((-h + E*h)*(h + E*h)) + (-(-sqrt(2)*h + h)/(2*h) - (-sqrt(2)*h + E*h)/(2*h))*f(-h + x)/(h + E*h) + (-(h + sqrt(2)*h)/(2*h) + (-sqrt(2)*h + E*h)/(2*h))*f(h + x)/(-h + E*h)
Partial derivatives are also supported:
>>> y = Symbol('y') >>> d2fdxdy=f(x,y).diff(x,y) >>> as_finite_diff(d2fdxdy, wrt=x) -Derivative(f(x - 1/2, y), y) + Derivative(f(x + 1/2, y), y)
-
sympy.calculus.finite_diff.
differentiate_finite
(expr, *symbols, **kwargs)[source]¶ Differentiate expr and replace Derivatives with finite differences.
- Parameters
expr : expression
*symbols : differentiate with respect to symbols
points: sequence or coefficient, optional
see
Derivative.as_finite_difference
x0: number or Symbol, optional
see
Derivative.as_finite_difference
wrt: Symbol, optional
see
Derivative.as_finite_difference
evaluate : bool
kwarg passed on to
diff
, whether or not to evaluate the Derivative intermediately (default:False
).
Examples
>>> from sympy import cos, sin, Function, differentiate_finite >>> from sympy.abc import x, y, h >>> f, g = Function('f'), Function('g') >>> differentiate_finite(f(x)*g(x), x, points=[x-h, x+h]) -f(-h + x)*g(-h + x)/(2*h) + f(h + x)*g(h + x)/(2*h)
Note that the above form preserves the product rule in discrete form. If we want we can pass
evaluate=True
to get another form (which is usually not what we want):>>> differentiate_finite(f(x)*g(x), x, points=[x-h, x+h], evaluate=True).simplify() -((f(-h + x) - f(h + x))*g(x) + (g(-h + x) - g(h + x))*f(x))/(2*h)
differentiate_finite
works on any expression:>>> differentiate_finite(f(x) + sin(x), x, 2) -2*f(x) + f(x - 1) + f(x + 1) - 2*sin(x) + sin(x - 1) + sin(x + 1) >>> differentiate_finite(f(x) + sin(x), x, 2, evaluate=True) -2*f(x) + f(x - 1) + f(x + 1) - sin(x) >>> differentiate_finite(f(x, y), x, y) f(x - 1/2, y - 1/2) - f(x - 1/2, y + 1/2) - f(x + 1/2, y - 1/2) + f(x + 1/2, y + 1/2)
-
sympy.calculus.finite_diff.
finite_diff_weights
(order, x_list, x0=1)[source]¶ Calculates the finite difference weights for an arbitrarily spaced one-dimensional grid (
x_list
) for derivatives atx0
of order 0, 1, …, up toorder
using a recursive formula. Order of accuracy is at leastlen(x_list) - order
, ifx_list
is defined correctly.- Parameters
order: int
Up to what derivative order weights should be calculated. 0 corresponds to interpolation.
x_list: sequence
Sequence of (unique) values for the independent variable. It is useful (but not necessary) to order
x_list
from nearest to furthest fromx0
; see examples below.x0: Number or Symbol
Root or value of the independent variable for which the finite difference weights should be generated. Default is
S.One
.- Returns
list
A list of sublists, each corresponding to coefficients for increasing derivative order, and each containing lists of coefficients for increasing subsets of x_list.
Notes
If weights for a finite difference approximation of 3rd order derivative is wanted, weights for 0th, 1st and 2nd order are calculated “for free”, so are formulae using subsets of
x_list
. This is something one can take advantage of to save computational cost. Be aware that one should definex_list
from nearest to farest fromx0
. If not, subsets ofx_list
will yield poorer approximations, which might not grand an order of accuracy oflen(x_list) - order
.References
- R24
Generation of Finite Difference Formulas on Arbitrarily Spaced Grids, Bengt Fornberg; Mathematics of computation; 51; 184; (1988); 699-706; doi:10.1090/S0025-5718-1988-0935077-0
Examples
>>> from sympy import S >>> from sympy.calculus import finite_diff_weights >>> res = finite_diff_weights(1, [-S(1)/2, S(1)/2, S(3)/2, S(5)/2], 0) >>> res [[[1, 0, 0, 0], [1/2, 1/2, 0, 0], [3/8, 3/4, -1/8, 0], [5/16, 15/16, -5/16, 1/16]], [[0, 0, 0, 0], [-1, 1, 0, 0], [-1, 1, 0, 0], [-23/24, 7/8, 1/8, -1/24]]] >>> res[0][-1] # FD weights for 0th derivative, using full x_list [5/16, 15/16, -5/16, 1/16] >>> res[1][-1] # FD weights for 1st derivative [-23/24, 7/8, 1/8, -1/24] >>> res[1][-2] # FD weights for 1st derivative, using x_list[:-1] [-1, 1, 0, 0] >>> res[1][-1][0] # FD weight for 1st deriv. for x_list[0] -23/24 >>> res[1][-1][1] # FD weight for 1st deriv. for x_list[1], etc. 7/8
Each sublist contains the most accurate formula at the end. Note, that in the above example
res[1][1]
is the same asres[1][2]
. Since res[1][2] has an order of accuracy oflen(x_list[:3]) - order = 3 - 1 = 2
, the same is true forres[1][1]
!>>> from sympy import S >>> from sympy.calculus import finite_diff_weights >>> res = finite_diff_weights(1, [S(0), S(1), -S(1), S(2), -S(2)], 0)[1] >>> res [[0, 0, 0, 0, 0], [-1, 1, 0, 0, 0], [0, 1/2, -1/2, 0, 0], [-1/2, 1, -1/3, -1/6, 0], [0, 2/3, -2/3, -1/12, 1/12]] >>> res[0] # no approximation possible, using x_list[0] only [0, 0, 0, 0, 0] >>> res[1] # classic forward step approximation [-1, 1, 0, 0, 0] >>> res[2] # classic centered approximation [0, 1/2, -1/2, 0, 0] >>> res[3:] # higher order approximations [[-1/2, 1, -1/3, -1/6, 0], [0, 2/3, -2/3, -1/12, 1/12]]
Let us compare this to a differently defined
x_list
. Pay attention tofoo[i][k]
corresponding to the gridpoint defined byx_list[k]
.>>> from sympy import S >>> from sympy.calculus import finite_diff_weights >>> foo = finite_diff_weights(1, [-S(2), -S(1), S(0), S(1), S(2)], 0)[1] >>> foo [[0, 0, 0, 0, 0], [-1, 1, 0, 0, 0], [1/2, -2, 3/2, 0, 0], [1/6, -1, 1/2, 1/3, 0], [1/12, -2/3, 0, 2/3, -1/12]] >>> foo[1] # not the same and of lower accuracy as res[1]! [-1, 1, 0, 0, 0] >>> foo[2] # classic double backward step approximation [1/2, -2, 3/2, 0, 0] >>> foo[4] # the same as res[4] [1/12, -2/3, 0, 2/3, -1/12]
Note that, unless you plan on using approximations based on subsets of
x_list
, the order of gridpoints does not matter.The capability to generate weights at arbitrary points can be used e.g. to minimize Runge’s phenomenon by using Chebyshev nodes:
>>> from sympy import cos, symbols, pi, simplify >>> from sympy.calculus import finite_diff_weights >>> N, (h, x) = 4, symbols('h x') >>> x_list = [x+h*cos(i*pi/(N)) for i in range(N,-1,-1)] # chebyshev nodes >>> print(x_list) [-h + x, -sqrt(2)*h/2 + x, x, sqrt(2)*h/2 + x, h + x] >>> mycoeffs = finite_diff_weights(1, x_list, 0)[1][4] >>> [simplify(c) for c in mycoeffs] [(h**3/2 + h**2*x - 3*h*x**2 - 4*x**3)/h**4, (-sqrt(2)*h**3 - 4*h**2*x + 3*sqrt(2)*h*x**2 + 8*x**3)/h**4, 6*x/h**2 - 8*x**3/h**4, (sqrt(2)*h**3 - 4*h**2*x - 3*sqrt(2)*h*x**2 + 8*x**3)/h**4, (-h**3/2 + h**2*x + 3*h*x**2 - 4*x**3)/h**4]