Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
r""" Generalized Functions
Sage implements several generalized functions (also known as distributions) such as Dirac delta, Heaviside step functions. These generalized functions can be manipulated within Sage like any other symbolic functions.
AUTHORS:
- Golam Mortuza Hossain (2009-06-26): initial version
EXAMPLES:
Dirac delta function::
sage: dirac_delta(x) dirac_delta(x)
Heaviside step function::
sage: heaviside(x) heaviside(x)
Unit step function::
sage: unit_step(x) unit_step(x)
Signum (sgn) function::
sage: sgn(x) sgn(x)
Kronecker delta function::
sage: m,n=var('m,n') sage: kronecker_delta(m,n) kronecker_delta(m, n)
"""
############################################################################## # # Copyright (C) 2009 Golam Mortuza Hossain <gmhossain@gmail.com> # # Distributed under the terms of the GNU General Public License (GPL v2+) # http://www.gnu.org/licenses/ # ##############################################################################
from sage.symbolic.function import (BuiltinFunction, GinacFunction) from sage.rings.all import ComplexIntervalField, ZZ
class FunctionDiracDelta(BuiltinFunction): r""" The Dirac delta (generalized) function, `\delta(x)` (``dirac_delta(x)``).
INPUT:
- ``x`` - a real number or a symbolic expression
DEFINITION:
Dirac delta function `\delta(x)`, is defined in Sage as:
`\delta(x) = 0` for real `x \ne 0` and `\int_{-\infty}^{\infty} \delta(x) dx = 1`
Its alternate definition with respect to an arbitrary test function `f(x)` is
`\int_{-\infty}^{\infty} f(x) \delta(x-a) dx = f(a)`
EXAMPLES::
sage: dirac_delta(1) 0 sage: dirac_delta(0) dirac_delta(0) sage: dirac_delta(x) dirac_delta(x) sage: integrate(dirac_delta(x), x, -1, 1, algorithm='sympy') 1
REFERENCES:
- :wikipedia:`Dirac_delta_function`
""" def __init__(self): r""" The Dirac delta (generalized) function, ``dirac_delta(x)``.
INPUT:
- ``x`` - a real number or a symbolic expression
EXAMPLES::
sage: dirac_delta(1) 0 sage: dirac_delta(0) dirac_delta(0) sage: dirac_delta(x) dirac_delta(x) sage: latex(dirac_delta(x)) \delta\left(x\right)
sage: loads(dumps(dirac_delta(x))) dirac_delta(x) sage: dirac_delta(x)._sympy_() DiracDelta(x) """ conversions=dict(maxima='delta', mathematica='DiracDelta', sympy='DiracDelta', giac='Dirac'))
def _eval_(self, x): """ INPUT:
- ``x`` - a real number or a symbolic expression
EXAMPLES::
sage: dirac_delta(1) 0 sage: dirac_delta(0) dirac_delta(0) sage: dirac_delta(x) dirac_delta(x) sage: dirac_delta(exp(-10000000000000000000)) 0
Evaluation test::
sage: dirac_delta(x).subs(x=1) 0 """
def _evalf_(self, x, **kwds): """ TESTS::
sage: h(x) = dirac_delta(x) sage: h(pi).numerical_approx() 0.000000000000000 """ else: raise ValueError("Numeric evaluation of symbolic expression")
dirac_delta = FunctionDiracDelta()
class FunctionHeaviside(GinacFunction): r""" The Heaviside step function, `H(x)` (``heaviside(x)``).
INPUT:
- ``x`` - a real number or a symbolic expression
DEFINITION:
The Heaviside step function, `H(x)` is defined in Sage as:
`H(x) = 0` for `x < 0` and `H(x) = 1` for `x > 0`
.. SEEALSO:: :func:`unit_step()<sage.functions.generalized.FunctionUnitStep>`
EXAMPLES::
sage: heaviside(-1) 0 sage: heaviside(1) 1 sage: heaviside(0) heaviside(0) sage: heaviside(x) heaviside(x)
sage: heaviside(-1/2) 0 sage: heaviside(exp(-1000000000000000000000)) 1
TESTS::
sage: heaviside(x)._sympy_() Heaviside(x) sage: heaviside(x).subs(x=1) 1 sage: heaviside(x).subs(x=-1) 0
::
sage: ex = heaviside(x)+1 sage: t = loads(dumps(ex)); t heaviside(x) + 1 sage: bool(t == ex) True sage: t.subs(x=1) 2
REFERENCES:
- :wikipedia:`Heaviside_function`
""" def __init__(self): r""" The Heaviside step function, ``heaviside(x)``.
INPUT:
- ``x`` - a real number or a symbolic expression
EXAMPLES::
sage: heaviside(-1) 0 sage: heaviside(1) 1 sage: heaviside(0) heaviside(0) sage: heaviside(x) heaviside(x) sage: latex(heaviside(x)) H\left(x\right) sage: heaviside(x)._sympy_() Heaviside(x) sage: heaviside(x)._giac_() Heaviside(x) sage: h(x) = heaviside(x) sage: h(pi).numerical_approx() 1.00000000000000 """ conversions=dict(maxima='hstep', mathematica='HeavisideTheta', sympy='Heaviside', giac='Heaviside'))
def _derivative_(self, x, diff_param=None): """ Derivative of Heaviside step function
EXAMPLES::
sage: heaviside(x).diff(x) dirac_delta(x) """
heaviside = FunctionHeaviside()
class FunctionUnitStep(GinacFunction): r""" The unit step function, `\mathrm{u}(x)` (``unit_step(x)``).
INPUT:
- ``x`` - a real number or a symbolic expression
DEFINITION:
The unit step function, `\mathrm{u}(x)` is defined in Sage as:
`\mathrm{u}(x) = 0` for `x < 0` and `\mathrm{u}(x) = 1` for `x \geq 0`
.. SEEALSO:: :func:`heaviside()<sage.functions.generalized.FunctionHeaviside>`
EXAMPLES::
sage: unit_step(-1) 0 sage: unit_step(1) 1 sage: unit_step(0) 1 sage: unit_step(x) unit_step(x) sage: unit_step(-exp(-10000000000000000000)) 0
TESTS::
sage: unit_step(x).subs(x=1) 1 sage: unit_step(x).subs(x=0) 1 sage: h(x) = unit_step(x) sage: h(pi).numerical_approx() 1.00000000000000 """ def __init__(self): r""" The unit step function, ``unit_step(x)``.
INPUT:
- ``x`` - a real number or a symbolic expression
EXAMPLES:
sage: unit_step(-1) 0 sage: unit_step(1) 1 sage: unit_step(0) 1 sage: unit_step(x) unit_step(x) sage: latex(unit_step(x)) \mathrm{u}\left(x\right)
TESTS::
sage: t = loads(dumps(unit_step(x)+1)); t unit_step(x) + 1 sage: t.subs(x=0) 2 """ conversions=dict(mathematica='UnitStep'))
def _derivative_(self, x, diff_param=None): """ Derivative of unit step function
EXAMPLES::
sage: unit_step(x).diff(x) dirac_delta(x) """
unit_step = FunctionUnitStep()
class FunctionSignum(BuiltinFunction): r""" The signum or sgn function `\mathrm{sgn}(x)` (``sgn(x)``).
INPUT:
- ``x`` - a real number or a symbolic expression
DEFINITION:
The sgn function, `\mathrm{sgn}(x)` is defined as:
`\mathrm{sgn}(x) = 1` for `x > 0`, `\mathrm{sgn}(x) = 0` for `x = 0` and `\mathrm{sgn}(x) = -1` for `x < 0`
EXAMPLES::
sage: sgn(-1) -1 sage: sgn(1) 1 sage: sgn(0) 0 sage: sgn(x) sgn(x)
We can also use ``sign``::
sage: sign(1) 1 sage: sign(0) 0 sage: a = AA(-5).nth_root(7) sage: sign(a) -1
TESTS:
Check if conversion to sympy works :trac:`11921`::
sage: sgn(x)._sympy_() sign(x)
REFERENCES:
- :wikipedia:`Sign_function`
""" def __init__(self): r""" The sgn function, ``sgn(x)``.
EXAMPLES:
sage: sgn(-1) -1 sage: sgn(1) 1 sage: sgn(0) 0 sage: sgn(x) sgn(x) sage: sgn(x)._sympy_() sign(x) """ BuiltinFunction.__init__(self, "sgn", latex_name=r"\mathrm{sgn}", conversions=dict(maxima='signum',mathematica='Sign',sympy='sign'), alt_name="sign")
def _eval_(self, x): """
EXAMPLES::
sage: sgn(-1) -1 sage: sgn(1) 1 sage: sgn(0) 0 sage: sgn(x) sgn(x) sage: sgn(-exp(-10000000000000000000)) -1
Evaluation test::
sage: sgn(x).subs(x=1) 1 sage: sgn(x).subs(x=0) 0 sage: sgn(x).subs(x=-1) -1
More tests::
sage: sign(RR(2)) 1 sage: sign(RDF(2)) 1 sage: sign(AA(-2)) -1 sage: sign(AA(0)) 0 """
def _evalf_(self, x, **kwds): """ TESTS:
Check that :trac:`16587` is fixed::
sage: M = sgn(3/2, hold=True); M sgn(3/2) sage: M.n() 1 sage: h(x) = sgn(x) sage: h(pi).numerical_approx() 1.00000000000000 """ return x.sgn() return ZZ(0) # Now we have a non-zero real else: raise ValueError("Numeric evaluation of symbolic expression")
def _derivative_(self, x, diff_param=None): """ Derivative of sgn function
EXAMPLES::
sage: sgn(x).diff(x) 2*dirac_delta(x) """
sgn = FunctionSignum() sign = sgn
class FunctionKroneckerDelta(BuiltinFunction): r""" The Kronecker delta function `\delta_{m,n}` (``kronecker_delta(m, n)``).
INPUT:
- ``m`` - a number or a symbolic expression - ``n`` - a number or a symbolic expression
DEFINITION:
Kronecker delta function `\delta_{m,n}` is defined as:
`\delta_{m,n} = 0` for `m \ne n` and `\delta_{m,n} = 1` for `m = n`
EXAMPLES::
sage: kronecker_delta(1,2) 0 sage: kronecker_delta(1,1) 1 sage: m,n=var('m,n') sage: kronecker_delta(m,n) kronecker_delta(m, n)
REFERENCES:
- :wikipedia:`Kronecker_delta`
""" def __init__(self): r""" The Kronecker delta function.
EXAMPLES::
sage: kronecker_delta(1,2) 0 sage: kronecker_delta(1,1) 1 sage: y = var('y') sage: kronecker_delta(x, y)._sympy_() KroneckerDelta(x, y) """ BuiltinFunction.__init__(self, "kronecker_delta", nargs=2, conversions=dict(maxima='kron_delta', mathematica='KroneckerDelta', sympy='KroneckerDelta'))
def _eval_(self, m, n): """ The Kronecker delta function.
EXAMPLES::
sage: kronecker_delta(1,2) 0 sage: kronecker_delta(1,1) 1
Kronecker delta is a symmetric function. We keep arguments sorted to ensure that k_d(m, n) - k_d(n, m) cancels automatically::
sage: x,y=var('x,y') sage: kronecker_delta(x, y) kronecker_delta(x, y) sage: kronecker_delta(y, x) kronecker_delta(x, y) sage: kronecker_delta(x,2*x) kronecker_delta(2*x, x)
Evaluation test::
sage: kronecker_delta(1,x).subs(x=1) 1 """
def _evalf_(self, m, n, **kwds): """ TESTS::
sage: h(x) = kronecker_delta(3,x) sage: h(pi).numerical_approx() 0.000000000000000 """
else: else: return 0 # x is complex raise ValueError("Numeric evaluation of symbolic expression")
def _derivative_(self, *args, **kwds): """ Derivative of Kronecker delta
EXAMPLES::
sage: kronecker_delta(x,1).diff(x) 0 """ # Kronecker delta is non-zero (but finite) only in the set of # zero-measure unlike Dirac delta. Consequently, it is null # for the purpose of integration/differentiation. For *discrete sum* # Kronecker delta is however non-trivial.
def _print_latex_(self, m, n, **kwds): """ Return latex expression
EXAMPLES::
sage: from sage.misc.latex import latex sage: m,n=var('m,n') sage: latex(kronecker_delta(m,n)) \delta_{m,n}
"""
kronecker_delta = FunctionKroneckerDelta() |