I am done

This commit is contained in:
2024-10-30 22:14:35 +01:00
parent 720dc28c09
commit 40e2a747cf
36901 changed files with 5011519 additions and 0 deletions

View File

@ -0,0 +1,45 @@
"""Integration functions that integrate a SymPy expression.
Examples
========
>>> from sympy import integrate, sin
>>> from sympy.abc import x
>>> integrate(1/x,x)
log(x)
>>> integrate(sin(x),x)
-cos(x)
"""
from .integrals import integrate, Integral, line_integrate
from .transforms import (mellin_transform, inverse_mellin_transform,
MellinTransform, InverseMellinTransform,
laplace_transform, inverse_laplace_transform,
laplace_correspondence, laplace_initial_conds,
LaplaceTransform, InverseLaplaceTransform,
fourier_transform, inverse_fourier_transform,
FourierTransform, InverseFourierTransform,
sine_transform, inverse_sine_transform,
SineTransform, InverseSineTransform,
cosine_transform, inverse_cosine_transform,
CosineTransform, InverseCosineTransform,
hankel_transform, inverse_hankel_transform,
HankelTransform, InverseHankelTransform)
from .singularityfunctions import singularityintegrate
__all__ = [
'integrate', 'Integral', 'line_integrate',
'mellin_transform', 'inverse_mellin_transform', 'MellinTransform',
'InverseMellinTransform', 'laplace_transform',
'inverse_laplace_transform', 'LaplaceTransform',
'laplace_correspondence', 'laplace_initial_conds',
'InverseLaplaceTransform', 'fourier_transform',
'inverse_fourier_transform', 'FourierTransform',
'InverseFourierTransform', 'sine_transform', 'inverse_sine_transform',
'SineTransform', 'InverseSineTransform', 'cosine_transform',
'inverse_cosine_transform', 'CosineTransform', 'InverseCosineTransform',
'hankel_transform', 'inverse_hankel_transform', 'HankelTransform',
'InverseHankelTransform',
'singularityintegrate',
]

View File

@ -0,0 +1,21 @@
from sympy.core.symbol import Symbol
from sympy.functions.elementary.trigonometric import sin
from sympy.integrals.integrals import integrate
x = Symbol('x')
def bench_integrate_sin():
integrate(sin(x), x)
def bench_integrate_x1sin():
integrate(x**1*sin(x), x)
def bench_integrate_x2sin():
integrate(x**2*sin(x), x)
def bench_integrate_x3sin():
integrate(x**3*sin(x), x)

View File

@ -0,0 +1,13 @@
from sympy.core.symbol import Symbol
from sympy.functions.elementary.trigonometric import sin
from sympy.integrals.trigonometry import trigintegrate
x = Symbol('x')
def timeit_trigintegrate_sin3x():
trigintegrate(sin(x)**3, x)
def timeit_trigintegrate_x2():
trigintegrate(x**2, x) # -> None

View File

@ -0,0 +1,201 @@
from sympy.core.mul import Mul
from sympy.core.singleton import S
from sympy.core.sorting import default_sort_key
from sympy.functions import DiracDelta, Heaviside
from .integrals import Integral, integrate
def change_mul(node, x):
"""change_mul(node, x)
Rearranges the operands of a product, bringing to front any simple
DiracDelta expression.
Explanation
===========
If no simple DiracDelta expression was found, then all the DiracDelta
expressions are simplified (using DiracDelta.expand(diracdelta=True, wrt=x)).
Return: (dirac, new node)
Where:
o dirac is either a simple DiracDelta expression or None (if no simple
expression was found);
o new node is either a simplified DiracDelta expressions or None (if it
could not be simplified).
Examples
========
>>> from sympy import DiracDelta, cos
>>> from sympy.integrals.deltafunctions import change_mul
>>> from sympy.abc import x, y
>>> change_mul(x*y*DiracDelta(x)*cos(x), x)
(DiracDelta(x), x*y*cos(x))
>>> change_mul(x*y*DiracDelta(x**2 - 1)*cos(x), x)
(None, x*y*cos(x)*DiracDelta(x - 1)/2 + x*y*cos(x)*DiracDelta(x + 1)/2)
>>> change_mul(x*y*DiracDelta(cos(x))*cos(x), x)
(None, None)
See Also
========
sympy.functions.special.delta_functions.DiracDelta
deltaintegrate
"""
new_args = []
dirac = None
#Sorting is needed so that we consistently collapse the same delta;
#However, we must preserve the ordering of non-commutative terms
c, nc = node.args_cnc()
sorted_args = sorted(c, key=default_sort_key)
sorted_args.extend(nc)
for arg in sorted_args:
if arg.is_Pow and isinstance(arg.base, DiracDelta):
new_args.append(arg.func(arg.base, arg.exp - 1))
arg = arg.base
if dirac is None and (isinstance(arg, DiracDelta) and arg.is_simple(x)):
dirac = arg
else:
new_args.append(arg)
if not dirac: # there was no simple dirac
new_args = []
for arg in sorted_args:
if isinstance(arg, DiracDelta):
new_args.append(arg.expand(diracdelta=True, wrt=x))
elif arg.is_Pow and isinstance(arg.base, DiracDelta):
new_args.append(arg.func(arg.base.expand(diracdelta=True, wrt=x), arg.exp))
else:
new_args.append(arg)
if new_args != sorted_args:
nnode = Mul(*new_args).expand()
else: # if the node didn't change there is nothing to do
nnode = None
return (None, nnode)
return (dirac, Mul(*new_args))
def deltaintegrate(f, x):
"""
deltaintegrate(f, x)
Explanation
===========
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:
1) The expression is a simple expression: we return the integral,
taking care if we are dealing with a Derivative or with a proper
DiracDelta.
2) The expression is not simple (i.e. DiracDelta(cos(x))): we can do
nothing at all.
- If the node is a multiplication node having a DiracDelta term:
First we expand it.
If the expansion did work, then we try to integrate the expansion.
If not, we try to extract a simple DiracDelta term, then we have two
cases:
1) We have a simple DiracDelta term, so we return the integral.
2) We didn't have a simple term, but we do have an expression with
simplified DiracDelta terms, so we integrate this expression.
Examples
========
>>> from sympy.abc import x, y, z
>>> from sympy.integrals.deltafunctions import deltaintegrate
>>> from sympy import sin, cos, DiracDelta
>>> 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)
See Also
========
sympy.functions.special.delta_functions.DiracDelta
sympy.integrals.integrals.Integral
"""
if not f.has(DiracDelta):
return None
# g(x) = DiracDelta(h(x))
if f.func == DiracDelta:
h = f.expand(diracdelta=True, wrt=x)
if h == f: # can't simplify the expression
#FIXME: the second term tells whether is DeltaDirac or Derivative
#For integrating derivatives of DiracDelta we need the chain rule
if f.is_simple(x):
if (len(f.args) <= 1 or f.args[1] == 0):
return Heaviside(f.args[0])
else:
return (DiracDelta(f.args[0], f.args[1] - 1) /
f.args[0].as_poly().LC())
else: # let's try to integrate the simplified expression
fh = integrate(h, x)
return fh
elif f.is_Mul or f.is_Pow: # g(x) = a*b*c*f(DiracDelta(h(x)))*d*e
g = f.expand()
if f != g: # the expansion worked
fh = integrate(g, x)
if fh is not None and not isinstance(fh, Integral):
return fh
else:
# no expansion performed, try to extract a simple DiracDelta term
deltaterm, rest_mult = change_mul(f, x)
if not deltaterm:
if rest_mult:
fh = integrate(rest_mult, x)
return fh
else:
from sympy.solvers import solve
deltaterm = deltaterm.expand(diracdelta=True, wrt=x)
if deltaterm.is_Mul: # Take out any extracted factors
deltaterm, rest_mult_2 = change_mul(deltaterm, x)
rest_mult = rest_mult*rest_mult_2
point = solve(deltaterm.args[0], x)[0]
# Return the largest hyperreal term left after
# repeated integration by parts. For example,
#
# integrate(y*DiracDelta(x, 1),x) == y*DiracDelta(x,0), not 0
#
# This is so Integral(y*DiracDelta(x).diff(x),x).doit()
# will return y*DiracDelta(x) instead of 0 or DiracDelta(x),
# both of which are correct everywhere the value is defined
# but give wrong answers for nested integration.
n = (0 if len(deltaterm.args)==1 else deltaterm.args[1])
m = 0
while n >= 0:
r = S.NegativeOne**n*rest_mult.diff(x, n).subs(x, point)
if r.is_zero:
n -= 1
m += 1
else:
if m == 0:
return r*Heaviside(x - point)
else:
return r*DiracDelta(x,m-1)
# In some very weak sense, x=0 is still a singularity,
# but we hope will not be of any practical consequence.
return S.Zero
return None

View File

@ -0,0 +1,780 @@
from __future__ import annotations
from collections import defaultdict
from functools import reduce
from itertools import permutations
from sympy.core.add import Add
from sympy.core.basic import Basic
from sympy.core.mul import Mul
from sympy.core.symbol import Wild, Dummy, Symbol
from sympy.core.basic import sympify
from sympy.core.numbers import Rational, pi, I
from sympy.core.relational import Eq, Ne
from sympy.core.singleton import S
from sympy.core.sorting import ordered
from sympy.core.traversal import iterfreeargs
from sympy.functions import exp, sin, cos, tan, cot, asin, atan
from sympy.functions import log, sinh, cosh, tanh, coth, asinh
from sympy.functions import sqrt, erf, erfi, li, Ei
from sympy.functions import besselj, bessely, besseli, besselk
from sympy.functions import hankel1, hankel2, jn, yn
from sympy.functions.elementary.complexes import Abs, re, im, sign, arg
from sympy.functions.elementary.exponential import LambertW
from sympy.functions.elementary.integers import floor, ceiling
from sympy.functions.elementary.piecewise import Piecewise
from sympy.functions.special.delta_functions import Heaviside, DiracDelta
from sympy.simplify.radsimp import collect
from sympy.logic.boolalg import And, Or
from sympy.utilities.iterables import uniq
from sympy.polys import quo, gcd, lcm, factor_list, cancel, PolynomialError
from sympy.polys.monomials import itermonomials
from sympy.polys.polyroots import root_factors
from sympy.polys.rings import PolyRing
from sympy.polys.solvers import solve_lin_sys
from sympy.polys.constructor import construct_domain
from sympy.integrals.integrals import integrate
def components(f, x):
"""
Returns a set of all functional components of the given expression
which includes symbols, function applications and compositions and
non-integer powers. Fractional powers are collected with
minimal, positive exponents.
Examples
========
>>> from sympy import cos, sin
>>> from sympy.abc import x
>>> from sympy.integrals.heurisch import components
>>> components(sin(x)*cos(x)**2, x)
{x, sin(x), cos(x)}
See Also
========
heurisch
"""
result = set()
if f.has_free(x):
if f.is_symbol and f.is_commutative:
result.add(f)
elif f.is_Function or f.is_Derivative:
for g in f.args:
result |= components(g, x)
result.add(f)
elif f.is_Pow:
result |= components(f.base, x)
if not f.exp.is_Integer:
if f.exp.is_Rational:
result.add(f.base**Rational(1, f.exp.q))
else:
result |= components(f.exp, x) | {f}
else:
for g in f.args:
result |= components(g, x)
return result
# name -> [] of symbols
_symbols_cache: dict[str, list[Dummy]] = {}
# NB @cacheit is not convenient here
def _symbols(name, n):
"""get vector of symbols local to this module"""
try:
lsyms = _symbols_cache[name]
except KeyError:
lsyms = []
_symbols_cache[name] = lsyms
while len(lsyms) < n:
lsyms.append( Dummy('%s%i' % (name, len(lsyms))) )
return lsyms[:n]
def heurisch_wrapper(f, x, rewrite=False, hints=None, mappings=None, retries=3,
degree_offset=0, unnecessary_permutations=None,
_try_heurisch=None):
"""
A wrapper around the heurisch integration algorithm.
Explanation
===========
This method takes the result from heurisch and checks for poles in the
denominator. For each of these poles, the integral is reevaluated, and
the final integration result is given in terms of a Piecewise.
Examples
========
>>> from sympy import cos, symbols
>>> from sympy.integrals.heurisch import heurisch, heurisch_wrapper
>>> n, x = symbols('n x')
>>> heurisch(cos(n*x), x)
sin(n*x)/n
>>> heurisch_wrapper(cos(n*x), x)
Piecewise((sin(n*x)/n, Ne(n, 0)), (x, True))
See Also
========
heurisch
"""
from sympy.solvers.solvers import solve, denoms
f = sympify(f)
if not f.has_free(x):
return f*x
res = heurisch(f, x, rewrite, hints, mappings, retries, degree_offset,
unnecessary_permutations, _try_heurisch)
if not isinstance(res, Basic):
return res
# We consider each denominator in the expression, and try to find
# cases where one or more symbolic denominator might be zero. The
# conditions for these cases are stored in the list slns.
#
# Since denoms returns a set we use ordered. This is important because the
# ordering of slns determines the order of the resulting Piecewise so we
# need a deterministic order here to make the output deterministic.
slns = []
for d in ordered(denoms(res)):
try:
slns += solve([d], dict=True, exclude=(x,))
except NotImplementedError:
pass
if not slns:
return res
slns = list(uniq(slns))
# Remove the solutions corresponding to poles in the original expression.
slns0 = []
for d in denoms(f):
try:
slns0 += solve([d], dict=True, exclude=(x,))
except NotImplementedError:
pass
slns = [s for s in slns if s not in slns0]
if not slns:
return res
if len(slns) > 1:
eqs = []
for sub_dict in slns:
eqs.extend([Eq(key, value) for key, value in sub_dict.items()])
slns = solve(eqs, dict=True, exclude=(x,)) + slns
# For each case listed in the list slns, we reevaluate the integral.
pairs = []
for sub_dict in slns:
expr = heurisch(f.subs(sub_dict), x, rewrite, hints, mappings, retries,
degree_offset, unnecessary_permutations,
_try_heurisch)
cond = And(*[Eq(key, value) for key, value in sub_dict.items()])
generic = Or(*[Ne(key, value) for key, value in sub_dict.items()])
if expr is None:
expr = integrate(f.subs(sub_dict),x)
pairs.append((expr, cond))
# If there is one condition, put the generic case first. Otherwise,
# doing so may lead to longer Piecewise formulas
if len(pairs) == 1:
pairs = [(heurisch(f, x, rewrite, hints, mappings, retries,
degree_offset, unnecessary_permutations,
_try_heurisch),
generic),
(pairs[0][0], True)]
else:
pairs.append((heurisch(f, x, rewrite, hints, mappings, retries,
degree_offset, unnecessary_permutations,
_try_heurisch),
True))
return Piecewise(*pairs)
class BesselTable:
"""
Derivatives of Bessel functions of orders n and n-1
in terms of each other.
See the docstring of DiffCache.
"""
def __init__(self):
self.table = {}
self.n = Dummy('n')
self.z = Dummy('z')
self._create_table()
def _create_table(t):
table, n, z = t.table, t.n, t.z
for f in (besselj, bessely, hankel1, hankel2):
table[f] = (f(n-1, z) - n*f(n, z)/z,
(n-1)*f(n-1, z)/z - f(n, z))
f = besseli
table[f] = (f(n-1, z) - n*f(n, z)/z,
(n-1)*f(n-1, z)/z + f(n, z))
f = besselk
table[f] = (-f(n-1, z) - n*f(n, z)/z,
(n-1)*f(n-1, z)/z - f(n, z))
for f in (jn, yn):
table[f] = (f(n-1, z) - (n+1)*f(n, z)/z,
(n-1)*f(n-1, z)/z - f(n, z))
def diffs(t, f, n, z):
if f in t.table:
diff0, diff1 = t.table[f]
repl = [(t.n, n), (t.z, z)]
return (diff0.subs(repl), diff1.subs(repl))
def has(t, f):
return f in t.table
_bessel_table = None
class DiffCache:
"""
Store for derivatives of expressions.
Explanation
===========
The standard form of the derivative of a Bessel function of order n
contains two Bessel functions of orders n-1 and n+1, respectively.
Such forms cannot be used in parallel Risch algorithm, because
there is a linear recurrence relation between the three functions
while the algorithm expects that functions and derivatives are
represented in terms of algebraically independent transcendentals.
The solution is to take two of the functions, e.g., those of orders
n and n-1, and to express the derivatives in terms of the pair.
To guarantee that the proper form is used the two derivatives are
cached as soon as one is encountered.
Derivatives of other functions are also cached at no extra cost.
All derivatives are with respect to the same variable `x`.
"""
def __init__(self, x):
self.cache = {}
self.x = x
global _bessel_table
if not _bessel_table:
_bessel_table = BesselTable()
def get_diff(self, f):
cache = self.cache
if f in cache:
pass
elif (not hasattr(f, 'func') or
not _bessel_table.has(f.func)):
cache[f] = cancel(f.diff(self.x))
else:
n, z = f.args
d0, d1 = _bessel_table.diffs(f.func, n, z)
dz = self.get_diff(z)
cache[f] = d0*dz
cache[f.func(n-1, z)] = d1*dz
return cache[f]
def heurisch(f, x, rewrite=False, hints=None, mappings=None, retries=3,
degree_offset=0, unnecessary_permutations=None,
_try_heurisch=None):
"""
Compute indefinite integral using heuristic Risch algorithm.
Explanation
===========
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 top level
'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
Examples
========
>>> from sympy import tan
>>> from sympy.integrals.heurisch 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":
References
==========
.. [1] https://www-sop.inria.fr/cafe/Manuel.Bronstein/pmint/index.html
For more information on the implemented algorithm refer to:
.. [2] K. Geddes, L. Stefanus, On the Risch-Norman Integration
Method and its Implementation in Maple, Proceedings of
ISSAC'89, ACM Press, 212-217.
.. [3] J. H. Davenport, On the Parallel Risch Algorithm (I),
Proceedings of EUROCAM'82, LNCS 144, Springer, 144-157.
.. [4] J. H. Davenport, On the Parallel Risch Algorithm (III):
Use of Tangents, SIGSAM Bulletin 16 (1982), 3-6.
.. [5] J. H. Davenport, B. M. Trager, On the Parallel Risch
Algorithm (II), ACM Transactions on Mathematical
Software 11 (1985), 356-362.
See Also
========
sympy.integrals.integrals.Integral.doit
sympy.integrals.integrals.Integral
sympy.integrals.heurisch.components
"""
f = sympify(f)
# There are some functions that Heurisch cannot currently handle,
# so do not even try.
# Set _try_heurisch=True to skip this check
if _try_heurisch is not True:
if f.has(Abs, re, im, sign, Heaviside, DiracDelta, floor, ceiling, arg):
return
if not f.has_free(x):
return f*x
if not f.is_Add:
indep, f = f.as_independent(x)
else:
indep = S.One
rewritables = {
(sin, cos, cot): tan,
(sinh, cosh, coth): tanh,
}
if rewrite:
for candidates, rule in rewritables.items():
f = f.rewrite(candidates, rule)
else:
for candidates in rewritables.keys():
if f.has(*candidates):
break
else:
rewrite = True
terms = components(f, x)
dcache = DiffCache(x)
if hints is not None:
if not hints:
a = Wild('a', exclude=[x])
b = Wild('b', exclude=[x])
c = Wild('c', exclude=[x])
for g in set(terms): # using copy of terms
if g.is_Function:
if isinstance(g, li):
M = g.args[0].match(a*x**b)
if M is not None:
terms.add( x*(li(M[a]*x**M[b]) - (M[a]*x**M[b])**(-1/M[b])*Ei((M[b]+1)*log(M[a]*x**M[b])/M[b])) )
#terms.add( x*(li(M[a]*x**M[b]) - (x**M[b])**(-1/M[b])*Ei((M[b]+1)*log(M[a]*x**M[b])/M[b])) )
#terms.add( x*(li(M[a]*x**M[b]) - x*Ei((M[b]+1)*log(M[a]*x**M[b])/M[b])) )
#terms.add( li(M[a]*x**M[b]) - Ei((M[b]+1)*log(M[a]*x**M[b])/M[b]) )
elif isinstance(g, exp):
M = g.args[0].match(a*x**2)
if M is not None:
if M[a].is_positive:
terms.add(erfi(sqrt(M[a])*x))
else: # M[a].is_negative or unknown
terms.add(erf(sqrt(-M[a])*x))
M = g.args[0].match(a*x**2 + b*x + c)
if M is not None:
if M[a].is_positive:
terms.add(sqrt(pi/4*(-M[a]))*exp(M[c] - M[b]**2/(4*M[a]))*
erfi(sqrt(M[a])*x + M[b]/(2*sqrt(M[a]))))
elif M[a].is_negative:
terms.add(sqrt(pi/4*(-M[a]))*exp(M[c] - M[b]**2/(4*M[a]))*
erf(sqrt(-M[a])*x - M[b]/(2*sqrt(-M[a]))))
M = g.args[0].match(a*log(x)**2)
if M is not None:
if M[a].is_positive:
terms.add(erfi(sqrt(M[a])*log(x) + 1/(2*sqrt(M[a]))))
if M[a].is_negative:
terms.add(erf(sqrt(-M[a])*log(x) - 1/(2*sqrt(-M[a]))))
elif g.is_Pow:
if g.exp.is_Rational and g.exp.q == 2:
M = g.base.match(a*x**2 + b)
if M is not None and M[b].is_positive:
if M[a].is_positive:
terms.add(asinh(sqrt(M[a]/M[b])*x))
elif M[a].is_negative:
terms.add(asin(sqrt(-M[a]/M[b])*x))
M = g.base.match(a*x**2 - b)
if M is not None and M[b].is_positive:
if M[a].is_positive:
dF = 1/sqrt(M[a]*x**2 - M[b])
F = log(2*sqrt(M[a])*sqrt(M[a]*x**2 - M[b]) + 2*M[a]*x)/sqrt(M[a])
dcache.cache[F] = dF # hack: F.diff(x) doesn't automatically simplify to f
terms.add(F)
elif M[a].is_negative:
terms.add(-M[b]/2*sqrt(-M[a])*
atan(sqrt(-M[a])*x/sqrt(M[a]*x**2 - M[b])))
else:
terms |= set(hints)
for g in set(terms): # using copy of terms
terms |= components(dcache.get_diff(g), x)
# XXX: The commented line below makes heurisch more deterministic wrt
# PYTHONHASHSEED and the iteration order of sets. There are other places
# where sets are iterated over but this one is possibly the most important.
# Theoretically the order here should not matter but different orderings
# can expose potential bugs in the different code paths so potentially it
# is better to keep the non-determinism.
#
# terms = list(ordered(terms))
# TODO: caching is significant factor for why permutations work at all. Change this.
V = _symbols('x', len(terms))
# sort mapping expressions from largest to smallest (last is always x).
mapping = list(reversed(list(zip(*ordered( #
[(a[0].as_independent(x)[1], a) for a in zip(terms, V)])))[1])) #
rev_mapping = {v: k for k, v in mapping} #
if mappings is None: #
# optimizing the number of permutations of mapping #
assert mapping[-1][0] == x # if not, find it and correct this comment
unnecessary_permutations = [mapping.pop(-1)]
# only permute types of objects and let the ordering
# of types take care of the order of replacement
types = defaultdict(list)
for i in mapping:
types[type(i)].append(i)
mapping = [types[i] for i in types]
def _iter_mappings():
for i in permutations(mapping):
yield [j for i in i for j in i]
mappings = _iter_mappings()
else:
unnecessary_permutations = unnecessary_permutations or []
def _substitute(expr):
return expr.subs(mapping)
for mapping in mappings:
mapping = list(mapping)
mapping = mapping + unnecessary_permutations
diffs = [ _substitute(dcache.get_diff(g)) for g in terms ]
denoms = [ g.as_numer_denom()[1] for g in diffs ]
if all(h.is_polynomial(*V) for h in denoms) and _substitute(f).is_rational_function(*V):
denom = reduce(lambda p, q: lcm(p, q, *V), denoms)
break
else:
if not rewrite:
result = heurisch(f, x, rewrite=True, hints=hints,
unnecessary_permutations=unnecessary_permutations)
if result is not None:
return indep*result
return None
numers = [ cancel(denom*g) for g in diffs ]
def _derivation(h):
return Add(*[ d * h.diff(v) for d, v in zip(numers, V) ])
def _deflation(p):
for y in V:
if not p.has(y):
continue
if _derivation(p) is not S.Zero:
c, q = p.as_poly(y).primitive()
return _deflation(c)*gcd(q, q.diff(y)).as_expr()
return p
def _splitter(p):
for y in V:
if not p.has(y):
continue
if _derivation(y) is not S.Zero:
c, q = p.as_poly(y).primitive()
q = q.as_expr()
h = gcd(q, _derivation(q), y)
s = quo(h, gcd(q, q.diff(y), y), y)
c_split = _splitter(c)
if s.as_poly(y).degree() == 0:
return (c_split[0], q * c_split[1])
q_split = _splitter(cancel(q / s))
return (c_split[0]*q_split[0]*s, c_split[1]*q_split[1])
return (S.One, p)
special = {}
for term in terms:
if term.is_Function:
if isinstance(term, tan):
special[1 + _substitute(term)**2] = False
elif isinstance(term, tanh):
special[1 + _substitute(term)] = False
special[1 - _substitute(term)] = False
elif isinstance(term, LambertW):
special[_substitute(term)] = True
F = _substitute(f)
P, Q = F.as_numer_denom()
u_split = _splitter(denom)
v_split = _splitter(Q)
polys = set(list(v_split) + [ u_split[0] ] + list(special.keys()))
s = u_split[0] * Mul(*[ k for k, v in special.items() if v ])
polified = [ p.as_poly(*V) for p in [s, P, Q] ]
if None in polified:
return None
#--- definitions for _integrate
a, b, c = [ p.total_degree() for p in polified ]
poly_denom = (s * v_split[0] * _deflation(v_split[1])).as_expr()
def _exponent(g):
if g.is_Pow:
if g.exp.is_Rational and g.exp.q != 1:
if g.exp.p > 0:
return g.exp.p + g.exp.q - 1
else:
return abs(g.exp.p + g.exp.q)
else:
return 1
elif not g.is_Atom and g.args:
return max(_exponent(h) for h in g.args)
else:
return 1
A, B = _exponent(f), a + max(b, c)
if A > 1 and B > 1:
monoms = tuple(ordered(itermonomials(V, A + B - 1 + degree_offset)))
else:
monoms = tuple(ordered(itermonomials(V, A + B + degree_offset)))
poly_coeffs = _symbols('A', len(monoms))
poly_part = Add(*[ poly_coeffs[i]*monomial
for i, monomial in enumerate(monoms) ])
reducibles = set()
for poly in ordered(polys):
coeff, factors = factor_list(poly, *V)
reducibles.add(coeff)
reducibles.update(fact for fact, mul in factors)
def _integrate(field=None):
atans = set()
pairs = set()
if field == 'Q':
irreducibles = set(reducibles)
else:
setV = set(V)
irreducibles = set()
for poly in ordered(reducibles):
zV = setV & set(iterfreeargs(poly))
for z in ordered(zV):
s = set(root_factors(poly, z, filter=field))
irreducibles |= s
break
log_part, atan_part = [], []
for poly in ordered(irreducibles):
m = collect(poly, I, evaluate=False)
y = m.get(I, S.Zero)
if y:
x = m.get(S.One, S.Zero)
if x.has(I) or y.has(I):
continue # nontrivial x + I*y
pairs.add((x, y))
irreducibles.remove(poly)
while pairs:
x, y = pairs.pop()
if (x, -y) in pairs:
pairs.remove((x, -y))
# Choosing b with no minus sign
if y.could_extract_minus_sign():
y = -y
irreducibles.add(x*x + y*y)
atans.add(atan(x/y))
else:
irreducibles.add(x + I*y)
B = _symbols('B', len(irreducibles))
C = _symbols('C', len(atans))
# Note: the ordering matters here
for poly, b in reversed(list(zip(ordered(irreducibles), B))):
if poly.has(*V):
poly_coeffs.append(b)
log_part.append(b * log(poly))
for poly, c in reversed(list(zip(ordered(atans), C))):
if poly.has(*V):
poly_coeffs.append(c)
atan_part.append(c * poly)
# TODO: Currently it's better to use symbolic expressions here instead
# of rational functions, because it's simpler and FracElement doesn't
# give big speed improvement yet. This is because cancellation is slow
# due to slow polynomial GCD algorithms. If this gets improved then
# revise this code.
candidate = poly_part/poly_denom + Add(*log_part) + Add(*atan_part)
h = F - _derivation(candidate) / denom
raw_numer = h.as_numer_denom()[0]
# Rewrite raw_numer as a polynomial in K[coeffs][V] where K is a field
# that we have to determine. We can't use simply atoms() because log(3),
# sqrt(y) and similar expressions can appear, leading to non-trivial
# domains.
syms = set(poly_coeffs) | set(V)
non_syms = set()
def find_non_syms(expr):
if expr.is_Integer or expr.is_Rational:
pass # ignore trivial numbers
elif expr in syms:
pass # ignore variables
elif not expr.has_free(*syms):
non_syms.add(expr)
elif expr.is_Add or expr.is_Mul or expr.is_Pow:
list(map(find_non_syms, expr.args))
else:
# TODO: Non-polynomial expression. This should have been
# filtered out at an earlier stage.
raise PolynomialError
try:
find_non_syms(raw_numer)
except PolynomialError:
return None
else:
ground, _ = construct_domain(non_syms, field=True)
coeff_ring = PolyRing(poly_coeffs, ground)
ring = PolyRing(V, coeff_ring)
try:
numer = ring.from_expr(raw_numer)
except ValueError:
raise PolynomialError
solution = solve_lin_sys(numer.coeffs(), coeff_ring, _raw=False)
if solution is None:
return None
else:
return candidate.xreplace(solution).xreplace(
dict(zip(poly_coeffs, [S.Zero]*len(poly_coeffs))))
if all(isinstance(_, Symbol) for _ in V):
more_free = F.free_symbols - set(V)
else:
Fd = F.as_dummy()
more_free = Fd.xreplace(dict(zip(V, (Dummy() for _ in V)))
).free_symbols & Fd.free_symbols
if not more_free:
# all free generators are identified in V
solution = _integrate('Q')
if solution is None:
solution = _integrate()
else:
solution = _integrate()
if solution is not None:
antideriv = solution.subs(rev_mapping)
antideriv = cancel(antideriv).expand()
if antideriv.is_Add:
antideriv = antideriv.as_independent(x)[1]
return indep*antideriv
else:
if retries >= 0:
result = heurisch(f, x, mappings=mappings, rewrite=rewrite, hints=hints, retries=retries - 1, unnecessary_permutations=unnecessary_permutations)
if result is not None:
return indep*result
return None

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
""" This module cooks up a docstring when imported. Its only purpose is to
be displayed in the sphinx documentation. """
from __future__ import annotations
from typing import Any
from sympy.integrals.meijerint import _create_lookup_table
from sympy.core.add import Add
from sympy.core.basic import Basic
from sympy.core.relational import Eq
from sympy.core.symbol import Symbol
from sympy.printing.latex import latex
t: dict[tuple[type[Basic], ...], list[Any]] = {}
_create_lookup_table(t)
doc = ""
for about, category in t.items():
if about == ():
doc += 'Elementary functions:\n\n'
else:
doc += 'Functions involving ' + ', '.join('`%s`' % latex(
list(category[0][0].atoms(func))[0]) for func in about) + ':\n\n'
for formula, gs, cond, hint in category:
if not isinstance(gs, list):
g = Symbol('\\text{generated}')
else:
g = Add(*[fac*f for (fac, f) in gs])
obj = Eq(formula, g)
if cond is True:
cond = ""
else:
cond = ',\\text{ if } %s' % latex(cond)
doc += ".. math::\n %s%s\n\n" % (latex(obj), cond)
__doc__ = doc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,617 @@
from sympy.core import S, Dummy, pi
from sympy.functions.combinatorial.factorials import factorial
from sympy.functions.elementary.trigonometric import sin, cos
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.functions.special.gamma_functions import gamma
from sympy.polys.orthopolys import (legendre_poly, laguerre_poly,
hermite_poly, jacobi_poly)
from sympy.polys.rootoftools import RootOf
def gauss_legendre(n, n_digits):
r"""
Computes the Gauss-Legendre quadrature [1]_ points and weights.
Explanation
===========
The Gauss-Legendre quadrature approximates the integral:
.. math::
\int_{-1}^1 f(x)\,dx \approx \sum_{i=1}^n w_i f(x_i)
The nodes `x_i` of an order `n` quadrature rule are the roots of `P_n`
and the weights `w_i` are given by:
.. math::
w_i = \frac{2}{\left(1-x_i^2\right) \left(P'_n(x_i)\right)^2}
Parameters
==========
n :
The order of quadrature.
n_digits :
Number of significant digits of the points and weights to return.
Returns
=======
(x, w) : the ``x`` and ``w`` are lists of points and weights as Floats.
The points `x_i` and weights `w_i` are returned as ``(x, w)``
tuple of lists.
Examples
========
>>> from sympy.integrals.quadrature import gauss_legendre
>>> x, w = gauss_legendre(3, 5)
>>> x
[-0.7746, 0, 0.7746]
>>> w
[0.55556, 0.88889, 0.55556]
>>> x, w = gauss_legendre(4, 5)
>>> x
[-0.86114, -0.33998, 0.33998, 0.86114]
>>> w
[0.34785, 0.65215, 0.65215, 0.34785]
See Also
========
gauss_laguerre, gauss_gen_laguerre, gauss_hermite, gauss_chebyshev_t, gauss_chebyshev_u, gauss_jacobi, gauss_lobatto
References
==========
.. [1] https://en.wikipedia.org/wiki/Gaussian_quadrature
.. [2] https://people.sc.fsu.edu/~jburkardt/cpp_src/legendre_rule/legendre_rule.html
"""
x = Dummy("x")
p = legendre_poly(n, x, polys=True)
pd = p.diff(x)
xi = []
w = []
for r in p.real_roots():
if isinstance(r, RootOf):
r = r.eval_rational(S.One/10**(n_digits+2))
xi.append(r.n(n_digits))
w.append((2/((1-r**2) * pd.subs(x, r)**2)).n(n_digits))
return xi, w
def gauss_laguerre(n, n_digits):
r"""
Computes the Gauss-Laguerre quadrature [1]_ points and weights.
Explanation
===========
The Gauss-Laguerre quadrature approximates the integral:
.. math::
\int_0^{\infty} e^{-x} f(x)\,dx \approx \sum_{i=1}^n w_i f(x_i)
The nodes `x_i` of an order `n` quadrature rule are the roots of `L_n`
and the weights `w_i` are given by:
.. math::
w_i = \frac{x_i}{(n+1)^2 \left(L_{n+1}(x_i)\right)^2}
Parameters
==========
n :
The order of quadrature.
n_digits :
Number of significant digits of the points and weights to return.
Returns
=======
(x, w) : The ``x`` and ``w`` are lists of points and weights as Floats.
The points `x_i` and weights `w_i` are returned as ``(x, w)``
tuple of lists.
Examples
========
>>> from sympy.integrals.quadrature import gauss_laguerre
>>> x, w = gauss_laguerre(3, 5)
>>> x
[0.41577, 2.2943, 6.2899]
>>> w
[0.71109, 0.27852, 0.010389]
>>> x, w = gauss_laguerre(6, 5)
>>> x
[0.22285, 1.1889, 2.9927, 5.7751, 9.8375, 15.983]
>>> w
[0.45896, 0.417, 0.11337, 0.010399, 0.00026102, 8.9855e-7]
See Also
========
gauss_legendre, gauss_gen_laguerre, gauss_hermite, gauss_chebyshev_t, gauss_chebyshev_u, gauss_jacobi, gauss_lobatto
References
==========
.. [1] https://en.wikipedia.org/wiki/Gauss%E2%80%93Laguerre_quadrature
.. [2] https://people.sc.fsu.edu/~jburkardt/cpp_src/laguerre_rule/laguerre_rule.html
"""
x = Dummy("x")
p = laguerre_poly(n, x, polys=True)
p1 = laguerre_poly(n+1, x, polys=True)
xi = []
w = []
for r in p.real_roots():
if isinstance(r, RootOf):
r = r.eval_rational(S.One/10**(n_digits+2))
xi.append(r.n(n_digits))
w.append((r/((n+1)**2 * p1.subs(x, r)**2)).n(n_digits))
return xi, w
def gauss_hermite(n, n_digits):
r"""
Computes the Gauss-Hermite quadrature [1]_ points and weights.
Explanation
===========
The Gauss-Hermite quadrature approximates the integral:
.. math::
\int_{-\infty}^{\infty} e^{-x^2} f(x)\,dx \approx
\sum_{i=1}^n w_i f(x_i)
The nodes `x_i` of an order `n` quadrature rule are the roots of `H_n`
and the weights `w_i` are given by:
.. math::
w_i = \frac{2^{n-1} n! \sqrt{\pi}}{n^2 \left(H_{n-1}(x_i)\right)^2}
Parameters
==========
n :
The order of quadrature.
n_digits :
Number of significant digits of the points and weights to return.
Returns
=======
(x, w) : The ``x`` and ``w`` are lists of points and weights as Floats.
The points `x_i` and weights `w_i` are returned as ``(x, w)``
tuple of lists.
Examples
========
>>> from sympy.integrals.quadrature import gauss_hermite
>>> x, w = gauss_hermite(3, 5)
>>> x
[-1.2247, 0, 1.2247]
>>> w
[0.29541, 1.1816, 0.29541]
>>> x, w = gauss_hermite(6, 5)
>>> x
[-2.3506, -1.3358, -0.43608, 0.43608, 1.3358, 2.3506]
>>> w
[0.00453, 0.15707, 0.72463, 0.72463, 0.15707, 0.00453]
See Also
========
gauss_legendre, gauss_laguerre, gauss_gen_laguerre, gauss_chebyshev_t, gauss_chebyshev_u, gauss_jacobi, gauss_lobatto
References
==========
.. [1] https://en.wikipedia.org/wiki/Gauss-Hermite_Quadrature
.. [2] https://people.sc.fsu.edu/~jburkardt/cpp_src/hermite_rule/hermite_rule.html
.. [3] https://people.sc.fsu.edu/~jburkardt/cpp_src/gen_hermite_rule/gen_hermite_rule.html
"""
x = Dummy("x")
p = hermite_poly(n, x, polys=True)
p1 = hermite_poly(n-1, x, polys=True)
xi = []
w = []
for r in p.real_roots():
if isinstance(r, RootOf):
r = r.eval_rational(S.One/10**(n_digits+2))
xi.append(r.n(n_digits))
w.append(((2**(n-1) * factorial(n) * sqrt(pi)) /
(n**2 * p1.subs(x, r)**2)).n(n_digits))
return xi, w
def gauss_gen_laguerre(n, alpha, n_digits):
r"""
Computes the generalized Gauss-Laguerre quadrature [1]_ points and weights.
Explanation
===========
The generalized Gauss-Laguerre quadrature approximates the integral:
.. math::
\int_{0}^\infty x^{\alpha} e^{-x} f(x)\,dx \approx
\sum_{i=1}^n w_i f(x_i)
The nodes `x_i` of an order `n` quadrature rule are the roots of
`L^{\alpha}_n` and the weights `w_i` are given by:
.. math::
w_i = \frac{\Gamma(\alpha+n)}
{n \Gamma(n) L^{\alpha}_{n-1}(x_i) L^{\alpha+1}_{n-1}(x_i)}
Parameters
==========
n :
The order of quadrature.
alpha :
The exponent of the singularity, `\alpha > -1`.
n_digits :
Number of significant digits of the points and weights to return.
Returns
=======
(x, w) : the ``x`` and ``w`` are lists of points and weights as Floats.
The points `x_i` and weights `w_i` are returned as ``(x, w)``
tuple of lists.
Examples
========
>>> from sympy import S
>>> from sympy.integrals.quadrature import gauss_gen_laguerre
>>> x, w = gauss_gen_laguerre(3, -S.Half, 5)
>>> x
[0.19016, 1.7845, 5.5253]
>>> w
[1.4493, 0.31413, 0.00906]
>>> x, w = gauss_gen_laguerre(4, 3*S.Half, 5)
>>> x
[0.97851, 2.9904, 6.3193, 11.712]
>>> w
[0.53087, 0.67721, 0.11895, 0.0023152]
See Also
========
gauss_legendre, gauss_laguerre, gauss_hermite, gauss_chebyshev_t, gauss_chebyshev_u, gauss_jacobi, gauss_lobatto
References
==========
.. [1] https://en.wikipedia.org/wiki/Gauss%E2%80%93Laguerre_quadrature
.. [2] https://people.sc.fsu.edu/~jburkardt/cpp_src/gen_laguerre_rule/gen_laguerre_rule.html
"""
x = Dummy("x")
p = laguerre_poly(n, x, alpha=alpha, polys=True)
p1 = laguerre_poly(n-1, x, alpha=alpha, polys=True)
p2 = laguerre_poly(n-1, x, alpha=alpha+1, polys=True)
xi = []
w = []
for r in p.real_roots():
if isinstance(r, RootOf):
r = r.eval_rational(S.One/10**(n_digits+2))
xi.append(r.n(n_digits))
w.append((gamma(alpha+n) /
(n*gamma(n)*p1.subs(x, r)*p2.subs(x, r))).n(n_digits))
return xi, w
def gauss_chebyshev_t(n, n_digits):
r"""
Computes the Gauss-Chebyshev quadrature [1]_ points and weights of
the first kind.
Explanation
===========
The Gauss-Chebyshev quadrature of the first kind approximates the integral:
.. math::
\int_{-1}^{1} \frac{1}{\sqrt{1-x^2}} f(x)\,dx \approx
\sum_{i=1}^n w_i f(x_i)
The nodes `x_i` of an order `n` quadrature rule are the roots of `T_n`
and the weights `w_i` are given by:
.. math::
w_i = \frac{\pi}{n}
Parameters
==========
n :
The order of quadrature.
n_digits :
Number of significant digits of the points and weights to return.
Returns
=======
(x, w) : the ``x`` and ``w`` are lists of points and weights as Floats.
The points `x_i` and weights `w_i` are returned as ``(x, w)``
tuple of lists.
Examples
========
>>> from sympy.integrals.quadrature import gauss_chebyshev_t
>>> x, w = gauss_chebyshev_t(3, 5)
>>> x
[0.86602, 0, -0.86602]
>>> w
[1.0472, 1.0472, 1.0472]
>>> x, w = gauss_chebyshev_t(6, 5)
>>> x
[0.96593, 0.70711, 0.25882, -0.25882, -0.70711, -0.96593]
>>> w
[0.5236, 0.5236, 0.5236, 0.5236, 0.5236, 0.5236]
See Also
========
gauss_legendre, gauss_laguerre, gauss_hermite, gauss_gen_laguerre, gauss_chebyshev_u, gauss_jacobi, gauss_lobatto
References
==========
.. [1] https://en.wikipedia.org/wiki/Chebyshev%E2%80%93Gauss_quadrature
.. [2] https://people.sc.fsu.edu/~jburkardt/cpp_src/chebyshev1_rule/chebyshev1_rule.html
"""
xi = []
w = []
for i in range(1, n+1):
xi.append((cos((2*i-S.One)/(2*n)*S.Pi)).n(n_digits))
w.append((S.Pi/n).n(n_digits))
return xi, w
def gauss_chebyshev_u(n, n_digits):
r"""
Computes the Gauss-Chebyshev quadrature [1]_ points and weights of
the second kind.
Explanation
===========
The Gauss-Chebyshev quadrature of the second kind approximates the
integral:
.. math::
\int_{-1}^{1} \sqrt{1-x^2} f(x)\,dx \approx \sum_{i=1}^n w_i f(x_i)
The nodes `x_i` of an order `n` quadrature rule are the roots of `U_n`
and the weights `w_i` are given by:
.. math::
w_i = \frac{\pi}{n+1} \sin^2 \left(\frac{i}{n+1}\pi\right)
Parameters
==========
n : the order of quadrature
n_digits : number of significant digits of the points and weights to return
Returns
=======
(x, w) : the ``x`` and ``w`` are lists of points and weights as Floats.
The points `x_i` and weights `w_i` are returned as ``(x, w)``
tuple of lists.
Examples
========
>>> from sympy.integrals.quadrature import gauss_chebyshev_u
>>> x, w = gauss_chebyshev_u(3, 5)
>>> x
[0.70711, 0, -0.70711]
>>> w
[0.3927, 0.7854, 0.3927]
>>> x, w = gauss_chebyshev_u(6, 5)
>>> x
[0.90097, 0.62349, 0.22252, -0.22252, -0.62349, -0.90097]
>>> w
[0.084489, 0.27433, 0.42658, 0.42658, 0.27433, 0.084489]
See Also
========
gauss_legendre, gauss_laguerre, gauss_hermite, gauss_gen_laguerre, gauss_chebyshev_t, gauss_jacobi, gauss_lobatto
References
==========
.. [1] https://en.wikipedia.org/wiki/Chebyshev%E2%80%93Gauss_quadrature
.. [2] https://people.sc.fsu.edu/~jburkardt/cpp_src/chebyshev2_rule/chebyshev2_rule.html
"""
xi = []
w = []
for i in range(1, n+1):
xi.append((cos(i/(n+S.One)*S.Pi)).n(n_digits))
w.append((S.Pi/(n+S.One)*sin(i*S.Pi/(n+S.One))**2).n(n_digits))
return xi, w
def gauss_jacobi(n, alpha, beta, n_digits):
r"""
Computes the Gauss-Jacobi quadrature [1]_ points and weights.
Explanation
===========
The Gauss-Jacobi quadrature of the first kind approximates the integral:
.. math::
\int_{-1}^1 (1-x)^\alpha (1+x)^\beta f(x)\,dx \approx
\sum_{i=1}^n w_i f(x_i)
The nodes `x_i` of an order `n` quadrature rule are the roots of
`P^{(\alpha,\beta)}_n` and the weights `w_i` are given by:
.. math::
w_i = -\frac{2n+\alpha+\beta+2}{n+\alpha+\beta+1}
\frac{\Gamma(n+\alpha+1)\Gamma(n+\beta+1)}
{\Gamma(n+\alpha+\beta+1)(n+1)!}
\frac{2^{\alpha+\beta}}{P'_n(x_i)
P^{(\alpha,\beta)}_{n+1}(x_i)}
Parameters
==========
n : the order of quadrature
alpha : the first parameter of the Jacobi Polynomial, `\alpha > -1`
beta : the second parameter of the Jacobi Polynomial, `\beta > -1`
n_digits : number of significant digits of the points and weights to return
Returns
=======
(x, w) : the ``x`` and ``w`` are lists of points and weights as Floats.
The points `x_i` and weights `w_i` are returned as ``(x, w)``
tuple of lists.
Examples
========
>>> from sympy import S
>>> from sympy.integrals.quadrature import gauss_jacobi
>>> x, w = gauss_jacobi(3, S.Half, -S.Half, 5)
>>> x
[-0.90097, -0.22252, 0.62349]
>>> w
[1.7063, 1.0973, 0.33795]
>>> x, w = gauss_jacobi(6, 1, 1, 5)
>>> x
[-0.87174, -0.5917, -0.2093, 0.2093, 0.5917, 0.87174]
>>> w
[0.050584, 0.22169, 0.39439, 0.39439, 0.22169, 0.050584]
See Also
========
gauss_legendre, gauss_laguerre, gauss_hermite, gauss_gen_laguerre,
gauss_chebyshev_t, gauss_chebyshev_u, gauss_lobatto
References
==========
.. [1] https://en.wikipedia.org/wiki/Gauss%E2%80%93Jacobi_quadrature
.. [2] https://people.sc.fsu.edu/~jburkardt/cpp_src/jacobi_rule/jacobi_rule.html
.. [3] https://people.sc.fsu.edu/~jburkardt/cpp_src/gegenbauer_rule/gegenbauer_rule.html
"""
x = Dummy("x")
p = jacobi_poly(n, alpha, beta, x, polys=True)
pd = p.diff(x)
pn = jacobi_poly(n+1, alpha, beta, x, polys=True)
xi = []
w = []
for r in p.real_roots():
if isinstance(r, RootOf):
r = r.eval_rational(S.One/10**(n_digits+2))
xi.append(r.n(n_digits))
w.append((
- (2*n+alpha+beta+2) / (n+alpha+beta+S.One) *
(gamma(n+alpha+1)*gamma(n+beta+1)) /
(gamma(n+alpha+beta+S.One)*gamma(n+2)) *
2**(alpha+beta) / (pd.subs(x, r) * pn.subs(x, r))).n(n_digits))
return xi, w
def gauss_lobatto(n, n_digits):
r"""
Computes the Gauss-Lobatto quadrature [1]_ points and weights.
Explanation
===========
The Gauss-Lobatto quadrature approximates the integral:
.. math::
\int_{-1}^1 f(x)\,dx \approx \sum_{i=1}^n w_i f(x_i)
The nodes `x_i` of an order `n` quadrature rule are the roots of `P'_(n-1)`
and the weights `w_i` are given by:
.. math::
&w_i = \frac{2}{n(n-1) \left[P_{n-1}(x_i)\right]^2},\quad x\neq\pm 1\\
&w_i = \frac{2}{n(n-1)},\quad x=\pm 1
Parameters
==========
n : the order of quadrature
n_digits : number of significant digits of the points and weights to return
Returns
=======
(x, w) : the ``x`` and ``w`` are lists of points and weights as Floats.
The points `x_i` and weights `w_i` are returned as ``(x, w)``
tuple of lists.
Examples
========
>>> from sympy.integrals.quadrature import gauss_lobatto
>>> x, w = gauss_lobatto(3, 5)
>>> x
[-1, 0, 1]
>>> w
[0.33333, 1.3333, 0.33333]
>>> x, w = gauss_lobatto(4, 5)
>>> x
[-1, -0.44721, 0.44721, 1]
>>> w
[0.16667, 0.83333, 0.83333, 0.16667]
See Also
========
gauss_legendre,gauss_laguerre, gauss_gen_laguerre, gauss_hermite, gauss_chebyshev_t, gauss_chebyshev_u, gauss_jacobi
References
==========
.. [1] https://en.wikipedia.org/wiki/Gaussian_quadrature#Gauss.E2.80.93Lobatto_rules
.. [2] https://web.archive.org/web/20200118141346/http://people.math.sfu.ca/~cbm/aands/page_888.htm
"""
x = Dummy("x")
p = legendre_poly(n-1, x, polys=True)
pd = p.diff(x)
xi = []
w = []
for r in pd.real_roots():
if isinstance(r, RootOf):
r = r.eval_rational(S.One/10**(n_digits+2))
xi.append(r.n(n_digits))
w.append((2/(n*(n-1) * p.subs(x, r)**2)).n(n_digits))
xi.insert(0, -1)
xi.append(1)
w.insert(0, (S(2)/(n*(n-1))).n(n_digits))
w.append((S(2)/(n*(n-1))).n(n_digits))
return xi, w

View File

@ -0,0 +1,429 @@
"""This module implements tools for integrating rational functions. """
from sympy.core.function import Lambda
from sympy.core.numbers import I
from sympy.core.singleton import S
from sympy.core.symbol import (Dummy, Symbol, symbols)
from sympy.functions.elementary.exponential import log
from sympy.functions.elementary.trigonometric import atan
from sympy.polys.polyroots import roots
from sympy.polys.polytools import cancel
from sympy.polys.rootoftools import RootSum
from sympy.polys import Poly, resultant, ZZ
def ratint(f, x, **flags):
"""
Performs indefinite integration of rational functions.
Explanation
===========
Given a field :math:`K` and a rational function :math:`f = p/q`,
where :math:`p` and :math:`q` are polynomials in :math:`K[x]`,
returns a function :math:`g` such that :math:`f = g'`.
Examples
========
>>> 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)
References
==========
.. [1] M. Bronstein, Symbolic Integration I: Transcendental
Functions, Second Edition, Springer-Verlag, 2005, pp. 35-70
See Also
========
sympy.integrals.integrals.Integral.doit
sympy.integrals.rationaltools.ratint_logpart
sympy.integrals.rationaltools.ratint_ratpart
"""
if isinstance(f, tuple):
p, q = f
else:
p, q = f.as_numer_denom()
p, q = Poly(p, x, composite=False, field=True), Poly(q, x, composite=False, field=True)
coeff, p, q = p.cancel(q)
poly, p = p.div(q)
result = poly.integrate(x).as_expr()
if p.is_zero:
return coeff*result
g, h = ratint_ratpart(p, q, x)
P, Q = h.as_numer_denom()
P = Poly(P, x)
Q = Poly(Q, x)
q, r = P.div(Q)
result += g + q.integrate(x).as_expr()
if not r.is_zero:
symbol = flags.get('symbol', 't')
if not isinstance(symbol, Symbol):
t = Dummy(symbol)
else:
t = symbol.as_dummy()
L = ratint_logpart(r, Q, x, t)
real = flags.get('real')
if real is None:
if isinstance(f, tuple):
p, q = f
atoms = p.atoms() | q.atoms()
else:
atoms = f.atoms()
for elt in atoms - {x}:
if not elt.is_extended_real:
real = False
break
else:
real = True
eps = S.Zero
if not real:
for h, q in L:
_, h = h.primitive()
eps += RootSum(
q, Lambda(t, t*log(h.as_expr())), quadratic=True)
else:
for h, q in L:
_, h = h.primitive()
R = log_to_real(h, q, x, t)
if R is not None:
eps += R
else:
eps += RootSum(
q, Lambda(t, t*log(h.as_expr())), quadratic=True)
result += eps
return coeff*result
def ratint_ratpart(f, g, x):
"""
Horowitz-Ostrogradsky algorithm.
Explanation
===========
Given a field K and polynomials f and g in K[x], such that f and g
are coprime and deg(f) < deg(g), returns fractions A and B in K(x),
such that f/g = A' + B and B has square-free denominator.
Examples
========
>>> from sympy.integrals.rationaltools import ratint_ratpart
>>> from sympy.abc import x, y
>>> from sympy import Poly
>>> ratint_ratpart(Poly(1, x, domain='ZZ'),
... Poly(x + 1, x, domain='ZZ'), x)
(0, 1/(x + 1))
>>> ratint_ratpart(Poly(1, x, domain='EX'),
... Poly(x**2 + y**2, x, domain='EX'), x)
(0, 1/(x**2 + y**2))
>>> ratint_ratpart(Poly(36, x, domain='ZZ'),
... Poly(x**5 - 2*x**4 - 2*x**3 + 4*x**2 + x - 2, x, domain='ZZ'), x)
((12*x + 6)/(x**2 - 1), 12/(x**2 - x - 2))
See Also
========
ratint, ratint_logpart
"""
from sympy.solvers.solvers import solve
f = Poly(f, x)
g = Poly(g, x)
u, v, _ = g.cofactors(g.diff())
n = u.degree()
m = v.degree()
A_coeffs = [ Dummy('a' + str(n - i)) for i in range(0, n) ]
B_coeffs = [ Dummy('b' + str(m - i)) for i in range(0, m) ]
C_coeffs = A_coeffs + B_coeffs
A = Poly(A_coeffs, x, domain=ZZ[C_coeffs])
B = Poly(B_coeffs, x, domain=ZZ[C_coeffs])
H = f - A.diff()*v + A*(u.diff()*v).quo(u) - B*u
result = solve(H.coeffs(), C_coeffs)
A = A.as_expr().subs(result)
B = B.as_expr().subs(result)
rat_part = cancel(A/u.as_expr(), x)
log_part = cancel(B/v.as_expr(), x)
return rat_part, log_part
def ratint_logpart(f, g, x, t=None):
r"""
Lazard-Rioboo-Trager algorithm.
Explanation
===========
Given a field K and polynomials f and g in K[x], such that f and g
are coprime, deg(f) < deg(g) and g is square-free, returns a list
of tuples (s_i, q_i) of polynomials, for i = 1..n, such that s_i
in K[t, x] and q_i in K[t], and::
___ ___
d f d \ ` \ `
-- - = -- ) ) a log(s_i(a, x))
dx g dx /__, /__,
i=1..n a | q_i(a) = 0
Examples
========
>>> from sympy.integrals.rationaltools import ratint_logpart
>>> from sympy.abc import x
>>> from sympy import Poly
>>> ratint_logpart(Poly(1, x, domain='ZZ'),
... Poly(x**2 + x + 1, x, domain='ZZ'), x)
[(Poly(x + 3*_t/2 + 1/2, x, domain='QQ[_t]'),
...Poly(3*_t**2 + 1, _t, domain='ZZ'))]
>>> ratint_logpart(Poly(12, x, domain='ZZ'),
... Poly(x**2 - x - 2, x, domain='ZZ'), x)
[(Poly(x - 3*_t/8 - 1/2, x, domain='QQ[_t]'),
...Poly(-_t**2 + 16, _t, domain='ZZ'))]
See Also
========
ratint, ratint_ratpart
"""
f, g = Poly(f, x), Poly(g, x)
t = t or Dummy('t')
a, b = g, f - g.diff()*Poly(t, x)
res, R = resultant(a, b, includePRS=True)
res = Poly(res, t, composite=False)
assert res, "BUG: resultant(%s, %s) cannot be zero" % (a, b)
R_map, H = {}, []
for r in R:
R_map[r.degree()] = r
def _include_sign(c, sqf):
if c.is_extended_real and (c < 0) == True:
h, k = sqf[0]
c_poly = c.as_poly(h.gens)
sqf[0] = h*c_poly, k
C, res_sqf = res.sqf_list()
_include_sign(C, res_sqf)
for q, i in res_sqf:
_, q = q.primitive()
if g.degree() == i:
H.append((g, q))
else:
h = R_map[i]
h_lc = Poly(h.LC(), t, field=True)
c, h_lc_sqf = h_lc.sqf_list(all=True)
_include_sign(c, h_lc_sqf)
for a, j in h_lc_sqf:
h = h.quo(Poly(a.gcd(q)**j, x))
inv, coeffs = h_lc.invert(q), [S.One]
for coeff in h.coeffs()[1:]:
coeff = coeff.as_poly(inv.gens)
T = (inv*coeff).rem(q)
coeffs.append(T.as_expr())
h = Poly(dict(list(zip(h.monoms(), coeffs))), x)
H.append((h, q))
return H
def log_to_atan(f, g):
"""
Convert complex logarithms to real arctangents.
Explanation
===========
Given a real field K and polynomials f and g in K[x], with g != 0,
returns a sum h of arctangents of polynomials in K[x], such that:
dh d f + I g
-- = -- I log( ------- )
dx dx f - I g
Examples
========
>>> from sympy.integrals.rationaltools import log_to_atan
>>> from sympy.abc import x
>>> from sympy import Poly, sqrt, S
>>> log_to_atan(Poly(x, x, domain='ZZ'), Poly(1, x, domain='ZZ'))
2*atan(x)
>>> log_to_atan(Poly(x + S(1)/2, x, domain='QQ'),
... Poly(sqrt(3)/2, x, domain='EX'))
2*atan(2*sqrt(3)*x/3 + sqrt(3)/3)
See Also
========
log_to_real
"""
if f.degree() < g.degree():
f, g = -g, f
f = f.to_field()
g = g.to_field()
p, q = f.div(g)
if q.is_zero:
return 2*atan(p.as_expr())
else:
s, t, h = g.gcdex(-f)
u = (f*s + g*t).quo(h)
A = 2*atan(u.as_expr())
return A + log_to_atan(s, t)
def log_to_real(h, q, x, t):
r"""
Convert complex logarithms to real functions.
Explanation
===========
Given real field K and polynomials h in K[t,x] and q in K[t],
returns real function f such that:
___
df d \ `
-- = -- ) a log(h(a, x))
dx dx /__,
a | q(a) = 0
Examples
========
>>> from sympy.integrals.rationaltools import log_to_real
>>> from sympy.abc import x, y
>>> from sympy import Poly, S
>>> log_to_real(Poly(x + 3*y/2 + S(1)/2, x, domain='QQ[y]'),
... Poly(3*y**2 + 1, y, domain='ZZ'), x, y)
2*sqrt(3)*atan(2*sqrt(3)*x/3 + sqrt(3)/3)/3
>>> log_to_real(Poly(x**2 - 1, x, domain='ZZ'),
... Poly(-2*y + 1, y, domain='ZZ'), x, y)
log(x**2 - 1)/2
See Also
========
log_to_atan
"""
from sympy.simplify.radsimp import collect
u, v = symbols('u,v', cls=Dummy)
H = h.as_expr().xreplace({t: u + I*v}).expand()
Q = q.as_expr().xreplace({t: u + I*v}).expand()
H_map = collect(H, I, evaluate=False)
Q_map = collect(Q, I, evaluate=False)
a, b = H_map.get(S.One, S.Zero), H_map.get(I, S.Zero)
c, d = Q_map.get(S.One, S.Zero), Q_map.get(I, S.Zero)
R = Poly(resultant(c, d, v), u)
R_u = roots(R, filter='R')
if len(R_u) != R.count_roots():
return None
result = S.Zero
for r_u in R_u.keys():
C = Poly(c.xreplace({u: r_u}), v)
if not C:
# t was split into real and imaginary parts
# and denom Q(u, v) = c + I*d. We just found
# that c(r_u) is 0 so the roots are in d
C = Poly(d.xreplace({u: r_u}), v)
# we were going to reject roots from C that
# did not set d to zero, but since we are now
# using C = d and c is already 0, there is
# nothing to check
d = S.Zero
R_v = roots(C, filter='R')
if len(R_v) != C.count_roots():
return None
R_v_paired = [] # take one from each pair of conjugate roots
for r_v in R_v:
if r_v not in R_v_paired and -r_v not in R_v_paired:
if r_v.is_negative or r_v.could_extract_minus_sign():
R_v_paired.append(-r_v)
elif not r_v.is_zero:
R_v_paired.append(r_v)
for r_v in R_v_paired:
D = d.xreplace({u: r_u, v: r_v})
if D.evalf(chop=True) != 0:
continue
A = Poly(a.xreplace({u: r_u, v: r_v}), x)
B = Poly(b.xreplace({u: r_u, v: r_v}), x)
AB = (A**2 + B**2).as_expr()
result += r_u*log(AB) + r_v*log_to_atan(A, B)
R_q = roots(q, filter='R')
if len(R_q) != q.count_roots():
return None
for r in R_q.keys():
result += r*log(h.as_expr().subs(t, r))
return result

View File

@ -0,0 +1,800 @@
"""
Algorithms for solving the Risch differential equation.
Given a differential field K of characteristic 0 that is a simple
monomial extension of a base field k and f, g in K, the Risch
Differential Equation problem is to decide if there exist y in K such
that Dy + f*y == g and to find one if there are some. If t is a
monomial over k and the coefficients of f and g are in k(t), then y is
in k(t), and the outline of the algorithm here is given as:
1. Compute the normal part n of the denominator of y. The problem is
then reduced to finding y' in k<t>, where y == y'/n.
2. Compute the special part s of the denominator of y. The problem is
then reduced to finding y'' in k[t], where y == y''/(n*s)
3. Bound the degree of y''.
4. Reduce the equation Dy + f*y == g to a similar equation with f, g in
k[t].
5. Find the solutions in k[t] of bounded degree of the reduced equation.
See Chapter 6 of "Symbolic Integration I: Transcendental Functions" by
Manuel Bronstein. See also the docstring of risch.py.
"""
from operator import mul
from functools import reduce
from sympy.core import oo
from sympy.core.symbol import Dummy
from sympy.polys import Poly, gcd, ZZ, cancel
from sympy.functions.elementary.complexes import (im, re)
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.integrals.risch import (gcdex_diophantine, frac_in, derivation,
splitfactor, NonElementaryIntegralException, DecrementLevel, recognize_log_derivative)
# TODO: Add messages to NonElementaryIntegralException errors
def order_at(a, p, t):
"""
Computes the order of a at p, with respect to t.
Explanation
===========
For a, p in k[t], the order of a at p is defined as nu_p(a) = max({n
in Z+ such that p**n|a}), where a != 0. If a == 0, nu_p(a) = +oo.
To compute the order at a rational function, a/b, use the fact that
nu_p(a/b) == nu_p(a) - nu_p(b).
"""
if a.is_zero:
return oo
if p == Poly(t, t):
return a.as_poly(t).ET()[0][0]
# Uses binary search for calculating the power. power_list collects the tuples
# (p^k,k) where each k is some power of 2. After deciding the largest k
# such that k is power of 2 and p^k|a the loop iteratively calculates
# the actual power.
power_list = []
p1 = p
r = a.rem(p1)
tracks_power = 1
while r.is_zero:
power_list.append((p1,tracks_power))
p1 = p1*p1
tracks_power *= 2
r = a.rem(p1)
n = 0
product = Poly(1, t)
while len(power_list) != 0:
final = power_list.pop()
productf = product*final[0]
r = a.rem(productf)
if r.is_zero:
n += final[1]
product = productf
return n
def order_at_oo(a, d, t):
"""
Computes the order of a/d at oo (infinity), with respect to t.
For f in k(t), the order or f at oo is defined as deg(d) - deg(a), where
f == a/d.
"""
if a.is_zero:
return oo
return d.degree(t) - a.degree(t)
def weak_normalizer(a, d, DE, z=None):
"""
Weak normalization.
Explanation
===========
Given a derivation D on k[t] and f == a/d in k(t), return q in k[t]
such that f - Dq/q is weakly normalized with respect to t.
f in k(t) is said to be "weakly normalized" with respect to t if
residue_p(f) is not a positive integer for any normal irreducible p
in k[t] such that f is in R_p (Definition 6.1.1). If f has an
elementary integral, this is equivalent to no logarithm of
integral(f) whose argument depends on t has a positive integer
coefficient, where the arguments of the logarithms not in k(t) are
in k[t].
Returns (q, f - Dq/q)
"""
z = z or Dummy('z')
dn, ds = splitfactor(d, DE)
# Compute d1, where dn == d1*d2**2*...*dn**n is a square-free
# factorization of d.
g = gcd(dn, dn.diff(DE.t))
d_sqf_part = dn.quo(g)
d1 = d_sqf_part.quo(gcd(d_sqf_part, g))
a1, b = gcdex_diophantine(d.quo(d1).as_poly(DE.t), d1.as_poly(DE.t),
a.as_poly(DE.t))
r = (a - Poly(z, DE.t)*derivation(d1, DE)).as_poly(DE.t).resultant(
d1.as_poly(DE.t))
r = Poly(r, z)
if not r.expr.has(z):
return (Poly(1, DE.t), (a, d))
N = [i for i in r.real_roots() if i in ZZ and i > 0]
q = reduce(mul, [gcd(a - Poly(n, DE.t)*derivation(d1, DE), d1) for n in N],
Poly(1, DE.t))
dq = derivation(q, DE)
sn = q*a - d*dq
sd = q*d
sn, sd = sn.cancel(sd, include=True)
return (q, (sn, sd))
def normal_denom(fa, fd, ga, gd, DE):
"""
Normal part of the denominator.
Explanation
===========
Given a derivation D on k[t] and f, g in k(t) with f weakly
normalized with respect to t, either raise NonElementaryIntegralException,
in which case the equation Dy + f*y == g has no solution in k(t), or the
quadruplet (a, b, c, h) such that a, h in k[t], b, c in k<t>, and for any
solution y in k(t) of Dy + f*y == g, q = y*h in k<t> satisfies
a*Dq + b*q == c.
This constitutes step 1 in the outline given in the rde.py docstring.
"""
dn, ds = splitfactor(fd, DE)
en, es = splitfactor(gd, DE)
p = dn.gcd(en)
h = en.gcd(en.diff(DE.t)).quo(p.gcd(p.diff(DE.t)))
a = dn*h
c = a*h
if c.div(en)[1]:
# en does not divide dn*h**2
raise NonElementaryIntegralException
ca = c*ga
ca, cd = ca.cancel(gd, include=True)
ba = a*fa - dn*derivation(h, DE)*fd
ba, bd = ba.cancel(fd, include=True)
# (dn*h, dn*h*f - dn*Dh, dn*h**2*g, h)
return (a, (ba, bd), (ca, cd), h)
def special_denom(a, ba, bd, ca, cd, DE, case='auto'):
"""
Special part of the denominator.
Explanation
===========
case is one of {'exp', 'tan', 'primitive'} for the hyperexponential,
hypertangent, and primitive cases, respectively. For the
hyperexponential (resp. hypertangent) case, given a derivation D on
k[t] and a in k[t], b, c, in k<t> with Dt/t in k (resp. Dt/(t**2 + 1) in
k, sqrt(-1) not in k), a != 0, and gcd(a, t) == 1 (resp.
gcd(a, t**2 + 1) == 1), return the quadruplet (A, B, C, 1/h) such that
A, B, C, h in k[t] and for any solution q in k<t> of a*Dq + b*q == c,
r = qh in k[t] satisfies A*Dr + B*r == C.
For ``case == 'primitive'``, k<t> == k[t], so it returns (a, b, c, 1) in
this case.
This constitutes step 2 of the outline given in the rde.py docstring.
"""
# TODO: finish writing this and write tests
if case == 'auto':
case = DE.case
if case == 'exp':
p = Poly(DE.t, DE.t)
elif case == 'tan':
p = Poly(DE.t**2 + 1, DE.t)
elif case in ('primitive', 'base'):
B = ba.to_field().quo(bd)
C = ca.to_field().quo(cd)
return (a, B, C, Poly(1, DE.t))
else:
raise ValueError("case must be one of {'exp', 'tan', 'primitive', "
"'base'}, not %s." % case)
nb = order_at(ba, p, DE.t) - order_at(bd, p, DE.t)
nc = order_at(ca, p, DE.t) - order_at(cd, p, DE.t)
n = min(0, nc - min(0, nb))
if not nb:
# Possible cancellation.
from .prde import parametric_log_deriv
if case == 'exp':
dcoeff = DE.d.quo(Poly(DE.t, DE.t))
with DecrementLevel(DE): # We are guaranteed to not have problems,
# because case != 'base'.
alphaa, alphad = frac_in(-ba.eval(0)/bd.eval(0)/a.eval(0), DE.t)
etaa, etad = frac_in(dcoeff, DE.t)
A = parametric_log_deriv(alphaa, alphad, etaa, etad, DE)
if A is not None:
Q, m, z = A
if Q == 1:
n = min(n, m)
elif case == 'tan':
dcoeff = DE.d.quo(Poly(DE.t**2+1, DE.t))
with DecrementLevel(DE): # We are guaranteed to not have problems,
# because case != 'base'.
alphaa, alphad = frac_in(im(-ba.eval(sqrt(-1))/bd.eval(sqrt(-1))/a.eval(sqrt(-1))), DE.t)
betaa, betad = frac_in(re(-ba.eval(sqrt(-1))/bd.eval(sqrt(-1))/a.eval(sqrt(-1))), DE.t)
etaa, etad = frac_in(dcoeff, DE.t)
if recognize_log_derivative(Poly(2, DE.t)*betaa, betad, DE):
A = parametric_log_deriv(alphaa*Poly(sqrt(-1), DE.t)*betad+alphad*betaa, alphad*betad, etaa, etad, DE)
if A is not None:
Q, m, z = A
if Q == 1:
n = min(n, m)
N = max(0, -nb, n - nc)
pN = p**N
pn = p**-n
A = a*pN
B = ba*pN.quo(bd) + Poly(n, DE.t)*a*derivation(p, DE).quo(p)*pN
C = (ca*pN*pn).quo(cd)
h = pn
# (a*p**N, (b + n*a*Dp/p)*p**N, c*p**(N - n), p**-n)
return (A, B, C, h)
def bound_degree(a, b, cQ, DE, case='auto', parametric=False):
"""
Bound on polynomial solutions.
Explanation
===========
Given a derivation D on k[t] and ``a``, ``b``, ``c`` in k[t] with ``a != 0``, return
n in ZZ such that deg(q) <= n for any solution q in k[t] of
a*Dq + b*q == c, when parametric=False, or deg(q) <= n for any solution
c1, ..., cm in Const(k) and q in k[t] of a*Dq + b*q == Sum(ci*gi, (i, 1, m))
when parametric=True.
For ``parametric=False``, ``cQ`` is ``c``, a ``Poly``; for ``parametric=True``, ``cQ`` is Q ==
[q1, ..., qm], a list of Polys.
This constitutes step 3 of the outline given in the rde.py docstring.
"""
# TODO: finish writing this and write tests
if case == 'auto':
case = DE.case
da = a.degree(DE.t)
db = b.degree(DE.t)
# The parametric and regular cases are identical, except for this part
if parametric:
dc = max(i.degree(DE.t) for i in cQ)
else:
dc = cQ.degree(DE.t)
alpha = cancel(-b.as_poly(DE.t).LC().as_expr()/
a.as_poly(DE.t).LC().as_expr())
if case == 'base':
n = max(0, dc - max(db, da - 1))
if db == da - 1 and alpha.is_Integer:
n = max(0, alpha, dc - db)
elif case == 'primitive':
if db > da:
n = max(0, dc - db)
else:
n = max(0, dc - da + 1)
etaa, etad = frac_in(DE.d, DE.T[DE.level - 1])
t1 = DE.t
with DecrementLevel(DE):
alphaa, alphad = frac_in(alpha, DE.t)
if db == da - 1:
from .prde import limited_integrate
# if alpha == m*Dt + Dz for z in k and m in ZZ:
try:
(za, zd), m = limited_integrate(alphaa, alphad, [(etaa, etad)],
DE)
except NonElementaryIntegralException:
pass
else:
if len(m) != 1:
raise ValueError("Length of m should be 1")
n = max(n, m[0])
elif db == da:
# if alpha == Dz/z for z in k*:
# beta = -lc(a*Dz + b*z)/(z*lc(a))
# if beta == m*Dt + Dw for w in k and m in ZZ:
# n = max(n, m)
from .prde import is_log_deriv_k_t_radical_in_field
A = is_log_deriv_k_t_radical_in_field(alphaa, alphad, DE)
if A is not None:
aa, z = A
if aa == 1:
beta = -(a*derivation(z, DE).as_poly(t1) +
b*z.as_poly(t1)).LC()/(z.as_expr()*a.LC())
betaa, betad = frac_in(beta, DE.t)
from .prde import limited_integrate
try:
(za, zd), m = limited_integrate(betaa, betad,
[(etaa, etad)], DE)
except NonElementaryIntegralException:
pass
else:
if len(m) != 1:
raise ValueError("Length of m should be 1")
n = max(n, m[0].as_expr())
elif case == 'exp':
from .prde import parametric_log_deriv
n = max(0, dc - max(db, da))
if da == db:
etaa, etad = frac_in(DE.d.quo(Poly(DE.t, DE.t)), DE.T[DE.level - 1])
with DecrementLevel(DE):
alphaa, alphad = frac_in(alpha, DE.t)
A = parametric_log_deriv(alphaa, alphad, etaa, etad, DE)
if A is not None:
# if alpha == m*Dt/t + Dz/z for z in k* and m in ZZ:
# n = max(n, m)
a, m, z = A
if a == 1:
n = max(n, m)
elif case in ('tan', 'other_nonlinear'):
delta = DE.d.degree(DE.t)
lam = DE.d.LC()
alpha = cancel(alpha/lam)
n = max(0, dc - max(da + delta - 1, db))
if db == da + delta - 1 and alpha.is_Integer:
n = max(0, alpha, dc - db)
else:
raise ValueError("case must be one of {'exp', 'tan', 'primitive', "
"'other_nonlinear', 'base'}, not %s." % case)
return n
def spde(a, b, c, n, DE):
"""
Rothstein's Special Polynomial Differential Equation algorithm.
Explanation
===========
Given a derivation D on k[t], an integer n and ``a``,``b``,``c`` in k[t] with
``a != 0``, either raise NonElementaryIntegralException, in which case the
equation a*Dq + b*q == c has no solution of degree at most ``n`` in
k[t], or return the tuple (B, C, m, alpha, beta) such that B, C,
alpha, beta in k[t], m in ZZ, and any solution q in k[t] of degree
at most n of a*Dq + b*q == c must be of the form
q == alpha*h + beta, where h in k[t], deg(h) <= m, and Dh + B*h == C.
This constitutes step 4 of the outline given in the rde.py docstring.
"""
zero = Poly(0, DE.t)
alpha = Poly(1, DE.t)
beta = Poly(0, DE.t)
while True:
if c.is_zero:
return (zero, zero, 0, zero, beta) # -1 is more to the point
if (n < 0) is True:
raise NonElementaryIntegralException
g = a.gcd(b)
if not c.rem(g).is_zero: # g does not divide c
raise NonElementaryIntegralException
a, b, c = a.quo(g), b.quo(g), c.quo(g)
if a.degree(DE.t) == 0:
b = b.to_field().quo(a)
c = c.to_field().quo(a)
return (b, c, n, alpha, beta)
r, z = gcdex_diophantine(b, a, c)
b += derivation(a, DE)
c = z - derivation(r, DE)
n -= a.degree(DE.t)
beta += alpha * r
alpha *= a
def no_cancel_b_large(b, c, n, DE):
"""
Poly Risch Differential Equation - No cancellation: deg(b) large enough.
Explanation
===========
Given a derivation D on k[t], ``n`` either an integer or +oo, and ``b``,``c``
in k[t] with ``b != 0`` and either D == d/dt or
deg(b) > max(0, deg(D) - 1), either raise NonElementaryIntegralException, in
which case the equation ``Dq + b*q == c`` has no solution of degree at
most n in k[t], or a solution q in k[t] of this equation with
``deg(q) < n``.
"""
q = Poly(0, DE.t)
while not c.is_zero:
m = c.degree(DE.t) - b.degree(DE.t)
if not 0 <= m <= n: # n < 0 or m < 0 or m > n
raise NonElementaryIntegralException
p = Poly(c.as_poly(DE.t).LC()/b.as_poly(DE.t).LC()*DE.t**m, DE.t,
expand=False)
q = q + p
n = m - 1
c = c - derivation(p, DE) - b*p
return q
def no_cancel_b_small(b, c, n, DE):
"""
Poly Risch Differential Equation - No cancellation: deg(b) small enough.
Explanation
===========
Given a derivation D on k[t], ``n`` either an integer or +oo, and ``b``,``c``
in k[t] with deg(b) < deg(D) - 1 and either D == d/dt or
deg(D) >= 2, either raise NonElementaryIntegralException, in which case the
equation Dq + b*q == c has no solution of degree at most n in k[t],
or a solution q in k[t] of this equation with deg(q) <= n, or the
tuple (h, b0, c0) such that h in k[t], b0, c0, in k, and for any
solution q in k[t] of degree at most n of Dq + bq == c, y == q - h
is a solution in k of Dy + b0*y == c0.
"""
q = Poly(0, DE.t)
while not c.is_zero:
if n == 0:
m = 0
else:
m = c.degree(DE.t) - DE.d.degree(DE.t) + 1
if not 0 <= m <= n: # n < 0 or m < 0 or m > n
raise NonElementaryIntegralException
if m > 0:
p = Poly(c.as_poly(DE.t).LC()/(m*DE.d.as_poly(DE.t).LC())*DE.t**m,
DE.t, expand=False)
else:
if b.degree(DE.t) != c.degree(DE.t):
raise NonElementaryIntegralException
if b.degree(DE.t) == 0:
return (q, b.as_poly(DE.T[DE.level - 1]),
c.as_poly(DE.T[DE.level - 1]))
p = Poly(c.as_poly(DE.t).LC()/b.as_poly(DE.t).LC(), DE.t,
expand=False)
q = q + p
n = m - 1
c = c - derivation(p, DE) - b*p
return q
# TODO: better name for this function
def no_cancel_equal(b, c, n, DE):
"""
Poly Risch Differential Equation - No cancellation: deg(b) == deg(D) - 1
Explanation
===========
Given a derivation D on k[t] with deg(D) >= 2, n either an integer
or +oo, and b, c in k[t] with deg(b) == deg(D) - 1, either raise
NonElementaryIntegralException, in which case the equation Dq + b*q == c has
no solution of degree at most n in k[t], or a solution q in k[t] of
this equation with deg(q) <= n, or the tuple (h, m, C) such that h
in k[t], m in ZZ, and C in k[t], and for any solution q in k[t] of
degree at most n of Dq + b*q == c, y == q - h is a solution in k[t]
of degree at most m of Dy + b*y == C.
"""
q = Poly(0, DE.t)
lc = cancel(-b.as_poly(DE.t).LC()/DE.d.as_poly(DE.t).LC())
if lc.is_Integer and lc.is_positive:
M = lc
else:
M = -1
while not c.is_zero:
m = max(M, c.degree(DE.t) - DE.d.degree(DE.t) + 1)
if not 0 <= m <= n: # n < 0 or m < 0 or m > n
raise NonElementaryIntegralException
u = cancel(m*DE.d.as_poly(DE.t).LC() + b.as_poly(DE.t).LC())
if u.is_zero:
return (q, m, c)
if m > 0:
p = Poly(c.as_poly(DE.t).LC()/u*DE.t**m, DE.t, expand=False)
else:
if c.degree(DE.t) != DE.d.degree(DE.t) - 1:
raise NonElementaryIntegralException
else:
p = c.as_poly(DE.t).LC()/b.as_poly(DE.t).LC()
q = q + p
n = m - 1
c = c - derivation(p, DE) - b*p
return q
def cancel_primitive(b, c, n, DE):
"""
Poly Risch Differential Equation - Cancellation: Primitive case.
Explanation
===========
Given a derivation D on k[t], n either an integer or +oo, ``b`` in k, and
``c`` in k[t] with Dt in k and ``b != 0``, either raise
NonElementaryIntegralException, in which case the equation Dq + b*q == c
has no solution of degree at most n in k[t], or a solution q in k[t] of
this equation with deg(q) <= n.
"""
# Delayed imports
from .prde import is_log_deriv_k_t_radical_in_field
with DecrementLevel(DE):
ba, bd = frac_in(b, DE.t)
A = is_log_deriv_k_t_radical_in_field(ba, bd, DE)
if A is not None:
n, z = A
if n == 1: # b == Dz/z
raise NotImplementedError("is_deriv_in_field() is required to "
" solve this problem.")
# if z*c == Dp for p in k[t] and deg(p) <= n:
# return p/z
# else:
# raise NonElementaryIntegralException
if c.is_zero:
return c # return 0
if n < c.degree(DE.t):
raise NonElementaryIntegralException
q = Poly(0, DE.t)
while not c.is_zero:
m = c.degree(DE.t)
if n < m:
raise NonElementaryIntegralException
with DecrementLevel(DE):
a2a, a2d = frac_in(c.LC(), DE.t)
sa, sd = rischDE(ba, bd, a2a, a2d, DE)
stm = Poly(sa.as_expr()/sd.as_expr()*DE.t**m, DE.t, expand=False)
q += stm
n = m - 1
c -= b*stm + derivation(stm, DE)
return q
def cancel_exp(b, c, n, DE):
"""
Poly Risch Differential Equation - Cancellation: Hyperexponential case.
Explanation
===========
Given a derivation D on k[t], n either an integer or +oo, ``b`` in k, and
``c`` in k[t] with Dt/t in k and ``b != 0``, either raise
NonElementaryIntegralException, in which case the equation Dq + b*q == c
has no solution of degree at most n in k[t], or a solution q in k[t] of
this equation with deg(q) <= n.
"""
from .prde import parametric_log_deriv
eta = DE.d.quo(Poly(DE.t, DE.t)).as_expr()
with DecrementLevel(DE):
etaa, etad = frac_in(eta, DE.t)
ba, bd = frac_in(b, DE.t)
A = parametric_log_deriv(ba, bd, etaa, etad, DE)
if A is not None:
a, m, z = A
if a == 1:
raise NotImplementedError("is_deriv_in_field() is required to "
"solve this problem.")
# if c*z*t**m == Dp for p in k<t> and q = p/(z*t**m) in k[t] and
# deg(q) <= n:
# return q
# else:
# raise NonElementaryIntegralException
if c.is_zero:
return c # return 0
if n < c.degree(DE.t):
raise NonElementaryIntegralException
q = Poly(0, DE.t)
while not c.is_zero:
m = c.degree(DE.t)
if n < m:
raise NonElementaryIntegralException
# a1 = b + m*Dt/t
a1 = b.as_expr()
with DecrementLevel(DE):
# TODO: Write a dummy function that does this idiom
a1a, a1d = frac_in(a1, DE.t)
a1a = a1a*etad + etaa*a1d*Poly(m, DE.t)
a1d = a1d*etad
a2a, a2d = frac_in(c.LC(), DE.t)
sa, sd = rischDE(a1a, a1d, a2a, a2d, DE)
stm = Poly(sa.as_expr()/sd.as_expr()*DE.t**m, DE.t, expand=False)
q += stm
n = m - 1
c -= b*stm + derivation(stm, DE) # deg(c) becomes smaller
return q
def solve_poly_rde(b, cQ, n, DE, parametric=False):
"""
Solve a Polynomial Risch Differential Equation with degree bound ``n``.
This constitutes step 4 of the outline given in the rde.py docstring.
For parametric=False, cQ is c, a Poly; for parametric=True, cQ is Q ==
[q1, ..., qm], a list of Polys.
"""
# No cancellation
if not b.is_zero and (DE.case == 'base' or
b.degree(DE.t) > max(0, DE.d.degree(DE.t) - 1)):
if parametric:
# Delayed imports
from .prde import prde_no_cancel_b_large
return prde_no_cancel_b_large(b, cQ, n, DE)
return no_cancel_b_large(b, cQ, n, DE)
elif (b.is_zero or b.degree(DE.t) < DE.d.degree(DE.t) - 1) and \
(DE.case == 'base' or DE.d.degree(DE.t) >= 2):
if parametric:
from .prde import prde_no_cancel_b_small
return prde_no_cancel_b_small(b, cQ, n, DE)
R = no_cancel_b_small(b, cQ, n, DE)
if isinstance(R, Poly):
return R
else:
# XXX: Might k be a field? (pg. 209)
h, b0, c0 = R
with DecrementLevel(DE):
b0, c0 = b0.as_poly(DE.t), c0.as_poly(DE.t)
if b0 is None: # See above comment
raise ValueError("b0 should be a non-Null value")
if c0 is None:
raise ValueError("c0 should be a non-Null value")
y = solve_poly_rde(b0, c0, n, DE).as_poly(DE.t)
return h + y
elif DE.d.degree(DE.t) >= 2 and b.degree(DE.t) == DE.d.degree(DE.t) - 1 and \
n > -b.as_poly(DE.t).LC()/DE.d.as_poly(DE.t).LC():
# TODO: Is this check necessary, and if so, what should it do if it fails?
# b comes from the first element returned from spde()
if not b.as_poly(DE.t).LC().is_number:
raise TypeError("Result should be a number")
if parametric:
raise NotImplementedError("prde_no_cancel_b_equal() is not yet "
"implemented.")
R = no_cancel_equal(b, cQ, n, DE)
if isinstance(R, Poly):
return R
else:
h, m, C = R
# XXX: Or should it be rischDE()?
y = solve_poly_rde(b, C, m, DE)
return h + y
else:
# Cancellation
if b.is_zero:
raise NotImplementedError("Remaining cases for Poly (P)RDE are "
"not yet implemented (is_deriv_in_field() required).")
else:
if DE.case == 'exp':
if parametric:
raise NotImplementedError("Parametric RDE cancellation "
"hyperexponential case is not yet implemented.")
return cancel_exp(b, cQ, n, DE)
elif DE.case == 'primitive':
if parametric:
raise NotImplementedError("Parametric RDE cancellation "
"primitive case is not yet implemented.")
return cancel_primitive(b, cQ, n, DE)
else:
raise NotImplementedError("Other Poly (P)RDE cancellation "
"cases are not yet implemented (%s)." % DE.case)
if parametric:
raise NotImplementedError("Remaining cases for Poly PRDE not yet "
"implemented.")
raise NotImplementedError("Remaining cases for Poly RDE not yet "
"implemented.")
def rischDE(fa, fd, ga, gd, DE):
"""
Solve a Risch Differential Equation: Dy + f*y == g.
Explanation
===========
See the outline in the docstring of rde.py for more information
about the procedure used. Either raise NonElementaryIntegralException, in
which case there is no solution y in the given differential field,
or return y in k(t) satisfying Dy + f*y == g, or raise
NotImplementedError, in which case, the algorithms necessary to
solve the given Risch Differential Equation have not yet been
implemented.
"""
_, (fa, fd) = weak_normalizer(fa, fd, DE)
a, (ba, bd), (ca, cd), hn = normal_denom(fa, fd, ga, gd, DE)
A, B, C, hs = special_denom(a, ba, bd, ca, cd, DE)
try:
# Until this is fully implemented, use oo. Note that this will almost
# certainly cause non-termination in spde() (unless A == 1), and
# *might* lead to non-termination in the next step for a nonelementary
# integral (I don't know for certain yet). Fortunately, spde() is
# currently written recursively, so this will just give
# RuntimeError: maximum recursion depth exceeded.
n = bound_degree(A, B, C, DE)
except NotImplementedError:
# Useful for debugging:
# import warnings
# warnings.warn("rischDE: Proceeding with n = oo; may cause "
# "non-termination.")
n = oo
B, C, m, alpha, beta = spde(A, B, C, n, DE)
if C.is_zero:
y = C
else:
y = solve_poly_rde(B, C, m, DE)
return (alpha*y + beta, hn*hs)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,63 @@
from sympy.functions import SingularityFunction, DiracDelta
from sympy.integrals import integrate
def singularityintegrate(f, x):
"""
This function handles the indefinite integrations of Singularity functions.
The ``integrate`` function calls this function internally whenever an
instance of SingularityFunction is passed as argument.
Explanation
===========
The idea for integration is the following:
- If we are dealing with a SingularityFunction expression,
i.e. ``SingularityFunction(x, a, n)``, we just return
``SingularityFunction(x, a, n + 1)/(n + 1)`` if ``n >= 0`` and
``SingularityFunction(x, a, n + 1)`` if ``n < 0``.
- If the node is a multiplication or power node having a
SingularityFunction term we rewrite the whole expression in terms of
Heaviside and DiracDelta and then integrate the output. Lastly, we
rewrite the output of integration back in terms of SingularityFunction.
- If none of the above case arises, we return None.
Examples
========
>>> from sympy.integrals.singularityfunctions import singularityintegrate
>>> from sympy import SingularityFunction, symbols, Function
>>> x, a, n, y = symbols('x a n y')
>>> f = Function('f')
>>> singularityintegrate(SingularityFunction(x, a, 3), x)
SingularityFunction(x, a, 4)/4
>>> singularityintegrate(5*SingularityFunction(x, 5, -2), x)
5*SingularityFunction(x, 5, -1)
>>> singularityintegrate(6*SingularityFunction(x, 5, -1), x)
6*SingularityFunction(x, 5, 0)
>>> singularityintegrate(x*SingularityFunction(x, 0, -1), x)
0
>>> singularityintegrate(SingularityFunction(x, 1, -1) * f(x), x)
f(1)*SingularityFunction(x, 1, 0)
"""
if not f.has(SingularityFunction):
return None
if isinstance(f, SingularityFunction):
x, a, n = f.args
if n.is_positive or n.is_zero:
return SingularityFunction(x, a, n + 1)/(n + 1)
elif n in (-1, -2, -3, -4):
return SingularityFunction(x, a, n + 1)
if f.is_Mul or f.is_Pow:
expr = f.rewrite(DiracDelta)
expr = integrate(expr, x)
return expr.rewrite(SingularityFunction)
return None

View File

@ -0,0 +1,79 @@
from sympy.core.function import Function
from sympy.core.numbers import (Rational, pi)
from sympy.core.singleton import S
from sympy.core.symbol import symbols
from sympy.functions.elementary.trigonometric import (cos, sin)
from sympy.functions.special.delta_functions import (DiracDelta, Heaviside)
from sympy.integrals.deltafunctions import change_mul, deltaintegrate
f = Function("f")
x_1, x_2, x, y, z = symbols("x_1 x_2 x y z")
def test_change_mul():
assert change_mul(x, x) == (None, None)
assert change_mul(x*y, x) == (None, None)
assert change_mul(x*y*DiracDelta(x), x) == (DiracDelta(x), x*y)
assert change_mul(x*y*DiracDelta(x)*DiracDelta(y), x) == \
(DiracDelta(x), x*y*DiracDelta(y))
assert change_mul(DiracDelta(x)**2, x) == \
(DiracDelta(x), DiracDelta(x))
assert change_mul(y*DiracDelta(x)**2, x) == \
(DiracDelta(x), y*DiracDelta(x))
def test_deltaintegrate():
assert deltaintegrate(x, x) is None
assert deltaintegrate(x + DiracDelta(x), x) is None
assert deltaintegrate(DiracDelta(x, 0), x) == Heaviside(x)
for n in range(10):
assert deltaintegrate(DiracDelta(x, n + 1), x) == DiracDelta(x, n)
assert deltaintegrate(DiracDelta(x), x) == Heaviside(x)
assert deltaintegrate(DiracDelta(-x), x) == Heaviside(x)
assert deltaintegrate(DiracDelta(x - y), x) == Heaviside(x - y)
assert deltaintegrate(DiracDelta(y - x), x) == Heaviside(x - y)
assert deltaintegrate(x*DiracDelta(x), x) == 0
assert deltaintegrate((x - y)*DiracDelta(x - y), x) == 0
assert deltaintegrate(DiracDelta(x)**2, x) == DiracDelta(0)*Heaviside(x)
assert deltaintegrate(y*DiracDelta(x)**2, x) == \
y*DiracDelta(0)*Heaviside(x)
assert deltaintegrate(DiracDelta(x, 1), x) == DiracDelta(x, 0)
assert deltaintegrate(y*DiracDelta(x, 1), x) == y*DiracDelta(x, 0)
assert deltaintegrate(DiracDelta(x, 1)**2, x) == -DiracDelta(0, 2)*Heaviside(x)
assert deltaintegrate(y*DiracDelta(x, 1)**2, x) == -y*DiracDelta(0, 2)*Heaviside(x)
assert deltaintegrate(DiracDelta(x) * f(x), x) == f(0) * Heaviside(x)
assert deltaintegrate(DiracDelta(-x) * f(x), x) == f(0) * Heaviside(x)
assert deltaintegrate(DiracDelta(x - 1) * f(x), x) == f(1) * Heaviside(x - 1)
assert deltaintegrate(DiracDelta(1 - x) * f(x), x) == f(1) * Heaviside(x - 1)
assert deltaintegrate(DiracDelta(x**2 + x - 2), x) == \
Heaviside(x - 1)/3 + Heaviside(x + 2)/3
p = cos(x)*(DiracDelta(x) + DiracDelta(x**2 - 1))*sin(x)*(x - pi)
assert deltaintegrate(p, x) - (-pi*(cos(1)*Heaviside(-1 + x)*sin(1)/2 - \
cos(1)*Heaviside(1 + x)*sin(1)/2) + \
cos(1)*Heaviside(1 + x)*sin(1)/2 + \
cos(1)*Heaviside(-1 + x)*sin(1)/2) == 0
p = x_2*DiracDelta(x - x_2)*DiracDelta(x_2 - x_1)
assert deltaintegrate(p, x_2) == x*DiracDelta(x - x_1)*Heaviside(x_2 - x)
p = x*y**2*z*DiracDelta(y - x)*DiracDelta(y - z)*DiracDelta(x - z)
assert deltaintegrate(p, y) == x**3*z*DiracDelta(x - z)**2*Heaviside(y - x)
assert deltaintegrate((x + 1)*DiracDelta(2*x), x) == S.Half * Heaviside(x)
assert deltaintegrate((x + 1)*DiracDelta(x*Rational(2, 3) + Rational(4, 9)), x) == \
S.Half * Heaviside(x + Rational(2, 3))
a, b, c = symbols('a b c', commutative=False)
assert deltaintegrate(DiracDelta(x - y)*f(x - b)*f(x - a), x) == \
f(y - b)*f(y - a)*Heaviside(x - y)
p = f(x - a)*DiracDelta(x - y)*f(x - c)*f(x - b)
assert deltaintegrate(p, x) == f(y - a)*f(y - c)*f(y - b)*Heaviside(x - y)
p = DiracDelta(x - z)*f(x - b)*f(x - a)*DiracDelta(x - y)
assert deltaintegrate(p, x) == DiracDelta(y - z)*f(y - b)*f(y - a) * \
Heaviside(x - y)

View File

@ -0,0 +1,277 @@
# A collection of failing integrals from the issues.
from sympy.core.numbers import (I, Rational, oo, pi)
from sympy.core.singleton import S
from sympy.core.symbol import symbols
from sympy.functions.elementary.complexes import sign
from sympy.functions.elementary.exponential import (exp, log)
from sympy.functions.elementary.hyperbolic import (sech, sinh)
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.functions.elementary.piecewise import Piecewise
from sympy.functions.elementary.trigonometric import (acos, atan, cos, sin, tan)
from sympy.functions.special.delta_functions import DiracDelta
from sympy.functions.special.gamma_functions import gamma
from sympy.integrals.integrals import (Integral, integrate)
from sympy.simplify.fu import fu
from sympy.testing.pytest import XFAIL, slow, tooslow
from sympy.abc import x, k, c, y, b, h, a, m, z, n, t
@tooslow
@XFAIL
def test_issue_3880():
# integrate_hyperexponential(Poly(t*2*(1 - t0**2)*t0*(x**3 + x**2), t), Poly((1 + t0**2)**2*2*(x**2 + x + 1), t), [Poly(1, x), Poly(1 + t0**2, t0), Poly(t, t)], [x, t0, t], [exp, tan])
assert not integrate(exp(x)*cos(2*x)*sin(2*x) * (x**3 + x**2)/(2*(x**2 + x + 1)), x).has(Integral)
def test_issue_4212_real():
xr = symbols('xr', real=True)
negabsx = Piecewise((-xr, xr < 0), (xr, True))
assert integrate(sign(xr), xr) == negabsx
@XFAIL
def test_issue_4212():
# XXX: Maybe this should be expected to fail without real assumptions on x.
# As a complex function sign(x) is not analytic and so there is no complex
# function whose complex derivative is sign(x). With real assumptions this
# works (see test_issue_4212_real above).
assert not integrate(sign(x), x).has(Integral)
def test_issue_4511():
# This works, but gives a slightly over-complicated answer.
f = integrate(cos(x)**2 / (1 - sin(x)), x)
assert fu(f) == x - cos(x) - 1
assert f == ((x*tan(x/2)**2 + x - 2)/(tan(x/2)**2 + 1)).expand()
def test_integrate_DiracDelta_no_meijerg():
assert integrate(integrate(integrate(
DiracDelta(x - y - z), (z, 0, oo)), (y, 0, 1), meijerg=False), (x, 0, 1)) == S.Half
@XFAIL
def test_integrate_DiracDelta_fails():
# issue 6427
# works without meijerg. See test_integrate_DiracDelta_no_meijerg above.
assert integrate(integrate(integrate(
DiracDelta(x - y - z), (z, 0, oo)), (y, 0, 1)), (x, 0, 1)) == S.Half
@XFAIL
@slow
def test_issue_4525():
# Warning: takes a long time
assert not integrate((x**m * (1 - x)**n * (a + b*x + c*x**2))/(1 + x**2), (x, 0, 1)).has(Integral)
@XFAIL
@tooslow
def test_issue_4540():
# Note, this integral is probably nonelementary
assert not integrate(
(sin(1/x) - x*exp(x)) /
((-sin(1/x) + x*exp(x))*x + x*sin(1/x)), x).has(Integral)
@XFAIL
@slow
def test_issue_4891():
# Requires the hypergeometric function.
assert not integrate(cos(x)**y, x).has(Integral)
@XFAIL
@slow
def test_issue_1796a():
assert not integrate(exp(2*b*x)*exp(-a*x**2), x).has(Integral)
@XFAIL
def test_issue_4895b():
assert not integrate(exp(2*b*x)*exp(-a*x**2), (x, -oo, 0)).has(Integral)
@XFAIL
def test_issue_4895c():
assert not integrate(exp(2*b*x)*exp(-a*x**2), (x, -oo, oo)).has(Integral)
@XFAIL
def test_issue_4895d():
assert not integrate(exp(2*b*x)*exp(-a*x**2), (x, 0, oo)).has(Integral)
@XFAIL
@slow
def test_issue_4941():
assert not integrate(sqrt(1 + sinh(x/20)**2), (x, -25, 25)).has(Integral)
@XFAIL
def test_issue_4992():
# Nonelementary integral. Requires hypergeometric/Meijer-G handling.
assert not integrate(log(x) * x**(k - 1) * exp(-x) / gamma(k), (x, 0, oo)).has(Integral)
@XFAIL
def test_issue_16396a():
i = integrate(1/(1+sqrt(tan(x))), (x, pi/3, pi/6))
assert not i.has(Integral)
@XFAIL
def test_issue_16396b():
i = integrate(x*sin(x)/(1+cos(x)**2), (x, 0, pi))
assert not i.has(Integral)
@XFAIL
def test_issue_16046():
assert integrate(exp(exp(I*x)), [x, 0, 2*pi]) == 2*pi
@XFAIL
def test_issue_15925a():
assert not integrate(sqrt((1+sin(x))**2+(cos(x))**2), (x, -pi/2, pi/2)).has(Integral)
def test_issue_15925b():
f = sqrt((-12*cos(x)**2*sin(x))**2+(12*cos(x)*sin(x)**2)**2)
assert integrate(f, (x, 0, pi/6)) == Rational(3, 2)
@XFAIL
def test_issue_15925b_manual():
assert not integrate(sqrt((-12*cos(x)**2*sin(x))**2+(12*cos(x)*sin(x)**2)**2),
(x, 0, pi/6), manual=True).has(Integral)
@XFAIL
@tooslow
def test_issue_15227():
i = integrate(log(1-x)*log((1+x)**2)/x, (x, 0, 1))
assert not i.has(Integral)
# assert i == -5*zeta(3)/4
@XFAIL
@slow
def test_issue_14716():
i = integrate(log(x + 5)*cos(pi*x),(x, S.Half, 1))
assert not i.has(Integral)
# Mathematica can not solve it either, but
# integrate(log(x + 5)*cos(pi*x),(x, S.Half, 1)).transform(x, y - 5).doit()
# works
# assert i == -log(Rational(11, 2))/pi - Si(pi*Rational(11, 2))/pi + Si(6*pi)/pi
@XFAIL
def test_issue_14709a():
i = integrate(x*acos(1 - 2*x/h), (x, 0, h))
assert not i.has(Integral)
# assert i == 5*h**2*pi/16
@slow
@XFAIL
def test_issue_14398():
assert not integrate(exp(x**2)*cos(x), x).has(Integral)
@XFAIL
def test_issue_14074():
i = integrate(log(sin(x)), (x, 0, pi/2))
assert not i.has(Integral)
# assert i == -pi*log(2)/2
@XFAIL
@slow
def test_issue_14078b():
i = integrate((atan(4*x)-atan(2*x))/x, (x, 0, oo))
assert not i.has(Integral)
# assert i == pi*log(2)/2
@XFAIL
def test_issue_13792():
i = integrate(log(1/x) / (1 - x), (x, 0, 1))
assert not i.has(Integral)
# assert i in [polylog(2, -exp_polar(I*pi)), pi**2/6]
@XFAIL
def test_issue_11845a():
assert not integrate(exp(y - x**3), (x, 0, 1)).has(Integral)
@XFAIL
def test_issue_11845b():
assert not integrate(exp(-y - x**3), (x, 0, 1)).has(Integral)
@XFAIL
def test_issue_11813():
assert not integrate((a - x)**Rational(-1, 2)*x, (x, 0, a)).has(Integral)
@XFAIL
def test_issue_11254c():
assert not integrate(sech(x)**2, (x, 0, 1)).has(Integral)
@XFAIL
def test_issue_10584():
assert not integrate(sqrt(x**2 + 1/x**2), x).has(Integral)
@XFAIL
def test_issue_9101():
assert not integrate(log(x + sqrt(x**2 + y**2 + z**2)), z).has(Integral)
@XFAIL
def test_issue_7147():
assert not integrate(x/sqrt(a*x**2 + b*x + c)**3, x).has(Integral)
@XFAIL
def test_issue_7109():
assert not integrate(sqrt(a**2/(a**2 - x**2)), x).has(Integral)
@XFAIL
def test_integrate_Piecewise_rational_over_reals():
f = Piecewise(
(0, t - 478.515625*pi < 0),
(13.2075145209219*pi/(0.000871222*t + 0.995)**2, t - 478.515625*pi >= 0))
assert abs((integrate(f, (t, 0, oo)) - 15235.9375*pi).evalf()) <= 1e-7
@XFAIL
def test_issue_4311_slow():
# Not slow when bypassing heurish
assert not integrate(x*abs(9-x**2), x).has(Integral)
@XFAIL
def test_issue_20370():
a = symbols('a', positive=True)
assert integrate((1 + a * cos(x))**-1, (x, 0, 2 * pi)) == (2 * pi / sqrt(1 - a**2))
@XFAIL
def test_polylog():
# log(1/x)*log(x+1)-polylog(2, -x)
assert not integrate(log(1/x)/(x + 1), x).has(Integral)
@XFAIL
def test_polylog_manual():
# Make sure _parts_rule does not go into an infinite loop here
assert not integrate(log(1/x)/(x + 1), x, manual=True).has(Integral)

View File

@ -0,0 +1,389 @@
from sympy.concrete.summations import Sum
from sympy.core.add import Add
from sympy.core.function import (Derivative, Function, diff)
from sympy.core.numbers import (I, Rational, pi)
from sympy.core.relational import Eq, Ne
from sympy.core.symbol import (Symbol, symbols)
from sympy.functions.elementary.exponential import (LambertW, exp, log)
from sympy.functions.elementary.hyperbolic import (asinh, cosh, sinh, tanh)
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.functions.elementary.piecewise import Piecewise
from sympy.functions.elementary.trigonometric import (acos, asin, atan, cos, sin, tan)
from sympy.functions.special.bessel import (besselj, besselk, bessely, jn)
from sympy.functions.special.error_functions import erf
from sympy.integrals.integrals import Integral
from sympy.logic.boolalg import And
from sympy.matrices import Matrix
from sympy.simplify.ratsimp import ratsimp
from sympy.simplify.simplify import simplify
from sympy.integrals.heurisch import components, heurisch, heurisch_wrapper
from sympy.testing.pytest import XFAIL, slow
from sympy.integrals.integrals import integrate
x, y, z, nu = symbols('x,y,z,nu')
f = Function('f')
def test_components():
assert components(x*y, x) == {x}
assert components(1/(x + y), x) == {x}
assert components(sin(x), x) == {sin(x), x}
assert components(sin(x)*sqrt(log(x)), x) == \
{log(x), sin(x), sqrt(log(x)), x}
assert components(x*sin(exp(x)*y), x) == \
{sin(y*exp(x)), x, exp(x)}
assert components(x**Rational(17, 54)/sqrt(sin(x)), x) == \
{sin(x), x**Rational(1, 54), sqrt(sin(x)), x}
assert components(f(x), x) == \
{x, f(x)}
assert components(Derivative(f(x), x), x) == \
{x, f(x), Derivative(f(x), x)}
assert components(f(x)*diff(f(x), x), x) == \
{x, f(x), Derivative(f(x), x), Derivative(f(x), x)}
def test_issue_10680():
assert isinstance(integrate(x**log(x**log(x**log(x))),x), Integral)
def test_issue_21166():
assert integrate(sin(x/sqrt(abs(x))), (x, -1, 1)) == 0
def test_heurisch_polynomials():
assert heurisch(1, x) == x
assert heurisch(x, x) == x**2/2
assert heurisch(x**17, x) == x**18/18
# For coverage
assert heurisch_wrapper(y, x) == y*x
def test_heurisch_fractions():
assert heurisch(1/x, x) == log(x)
assert heurisch(1/(2 + x), x) == log(x + 2)
assert heurisch(1/(x + sin(y)), x) == log(x + sin(y))
# Up to a constant, where C = pi*I*Rational(5, 12), Mathematica gives identical
# result in the first case. The difference is because SymPy changes
# signs of expressions without any care.
# XXX ^ ^ ^ is this still correct?
assert heurisch(5*x**5/(
2*x**6 - 5), x) in [5*log(2*x**6 - 5) / 12, 5*log(-2*x**6 + 5) / 12]
assert heurisch(5*x**5/(2*x**6 + 5), x) == 5*log(2*x**6 + 5) / 12
assert heurisch(1/x**2, x) == -1/x
assert heurisch(-1/x**5, x) == 1/(4*x**4)
def test_heurisch_log():
assert heurisch(log(x), x) == x*log(x) - x
assert heurisch(log(3*x), x) == -x + x*log(3) + x*log(x)
assert heurisch(log(x**2), x) in [x*log(x**2) - 2*x, 2*x*log(x) - 2*x]
def test_heurisch_exp():
assert heurisch(exp(x), x) == exp(x)
assert heurisch(exp(-x), x) == -exp(-x)
assert heurisch(exp(17*x), x) == exp(17*x) / 17
assert heurisch(x*exp(x), x) == x*exp(x) - exp(x)
assert heurisch(x*exp(x**2), x) == exp(x**2) / 2
assert heurisch(exp(-x**2), x) is None
assert heurisch(2**x, x) == 2**x/log(2)
assert heurisch(x*2**x, x) == x*2**x/log(2) - 2**x*log(2)**(-2)
assert heurisch(Integral(x**z*y, (y, 1, 2), (z, 2, 3)).function, x) == (x*x**z*y)/(z+1)
assert heurisch(Sum(x**z, (z, 1, 2)).function, z) == x**z/log(x)
# https://github.com/sympy/sympy/issues/23707
anti = -exp(z)/(sqrt(x - y)*exp(z*sqrt(x - y)) - exp(z*sqrt(x - y)))
assert heurisch(exp(z)*exp(-z*sqrt(x - y)), z) == anti
def test_heurisch_trigonometric():
assert heurisch(sin(x), x) == -cos(x)
assert heurisch(pi*sin(x) + 1, x) == x - pi*cos(x)
assert heurisch(cos(x), x) == sin(x)
assert heurisch(tan(x), x) in [
log(1 + tan(x)**2)/2,
log(tan(x) + I) + I*x,
log(tan(x) - I) - I*x,
]
assert heurisch(sin(x)*sin(y), x) == -cos(x)*sin(y)
assert heurisch(sin(x)*sin(y), y) == -cos(y)*sin(x)
# gives sin(x) in answer when run via setup.py and cos(x) when run via py.test
assert heurisch(sin(x)*cos(x), x) in [sin(x)**2 / 2, -cos(x)**2 / 2]
assert heurisch(cos(x)/sin(x), x) == log(sin(x))
assert heurisch(x*sin(7*x), x) == sin(7*x) / 49 - x*cos(7*x) / 7
assert heurisch(1/pi/4 * x**2*cos(x), x) == 1/pi/4*(x**2*sin(x) -
2*sin(x) + 2*x*cos(x))
assert heurisch(acos(x/4) * asin(x/4), x) == 2*x - (sqrt(16 - x**2))*asin(x/4) \
+ (sqrt(16 - x**2))*acos(x/4) + x*asin(x/4)*acos(x/4)
assert heurisch(sin(x)/(cos(x)**2+1), x) == -atan(cos(x)) #fixes issue 13723
assert heurisch(1/(cos(x)+2), x) == 2*sqrt(3)*atan(sqrt(3)*tan(x/2)/3)/3
assert heurisch(2*sin(x)*cos(x)/(sin(x)**4 + 1), x) == atan(sqrt(2)*sin(x)
- 1) - atan(sqrt(2)*sin(x) + 1)
assert heurisch(1/cosh(x), x) == 2*atan(tanh(x/2))
def test_heurisch_hyperbolic():
assert heurisch(sinh(x), x) == cosh(x)
assert heurisch(cosh(x), x) == sinh(x)
assert heurisch(x*sinh(x), x) == x*cosh(x) - sinh(x)
assert heurisch(x*cosh(x), x) == x*sinh(x) - cosh(x)
assert heurisch(
x*asinh(x/2), x) == x**2*asinh(x/2)/2 + asinh(x/2) - x*sqrt(4 + x**2)/4
def test_heurisch_mixed():
assert heurisch(sin(x)*exp(x), x) == exp(x)*sin(x)/2 - exp(x)*cos(x)/2
assert heurisch(sin(x/sqrt(-x)), x) == 2*x*cos(x/sqrt(-x))/sqrt(-x) - 2*sin(x/sqrt(-x))
def test_heurisch_radicals():
assert heurisch(1/sqrt(x), x) == 2*sqrt(x)
assert heurisch(1/sqrt(x)**3, x) == -2/sqrt(x)
assert heurisch(sqrt(x)**3, x) == 2*sqrt(x)**5/5
assert heurisch(sin(x)*sqrt(cos(x)), x) == -2*sqrt(cos(x))**3/3
y = Symbol('y')
assert heurisch(sin(y*sqrt(x)), x) == 2/y**2*sin(y*sqrt(x)) - \
2*sqrt(x)*cos(y*sqrt(x))/y
assert heurisch_wrapper(sin(y*sqrt(x)), x) == Piecewise(
(-2*sqrt(x)*cos(sqrt(x)*y)/y + 2*sin(sqrt(x)*y)/y**2, Ne(y, 0)),
(0, True))
y = Symbol('y', positive=True)
assert heurisch_wrapper(sin(y*sqrt(x)), x) == 2/y**2*sin(y*sqrt(x)) - \
2*sqrt(x)*cos(y*sqrt(x))/y
def test_heurisch_special():
assert heurisch(erf(x), x) == x*erf(x) + exp(-x**2)/sqrt(pi)
assert heurisch(exp(-x**2)*erf(x), x) == sqrt(pi)*erf(x)**2 / 4
def test_heurisch_symbolic_coeffs():
assert heurisch(1/(x + y), x) == log(x + y)
assert heurisch(1/(x + sqrt(2)), x) == log(x + sqrt(2))
assert simplify(diff(heurisch(log(x + y + z), y), y)) == log(x + y + z)
def test_heurisch_symbolic_coeffs_1130():
y = Symbol('y')
assert heurisch_wrapper(1/(x**2 + y), x) == Piecewise(
(log(x - sqrt(-y))/(2*sqrt(-y)) - log(x + sqrt(-y))/(2*sqrt(-y)),
Ne(y, 0)), (-1/x, True))
y = Symbol('y', positive=True)
assert heurisch_wrapper(1/(x**2 + y), x) == (atan(x/sqrt(y))/sqrt(y))
def test_heurisch_hacking():
assert heurisch(sqrt(1 + 7*x**2), x, hints=[]) == \
x*sqrt(1 + 7*x**2)/2 + sqrt(7)*asinh(sqrt(7)*x)/14
assert heurisch(sqrt(1 - 7*x**2), x, hints=[]) == \
x*sqrt(1 - 7*x**2)/2 + sqrt(7)*asin(sqrt(7)*x)/14
assert heurisch(1/sqrt(1 + 7*x**2), x, hints=[]) == \
sqrt(7)*asinh(sqrt(7)*x)/7
assert heurisch(1/sqrt(1 - 7*x**2), x, hints=[]) == \
sqrt(7)*asin(sqrt(7)*x)/7
assert heurisch(exp(-7*x**2), x, hints=[]) == \
sqrt(7*pi)*erf(sqrt(7)*x)/14
assert heurisch(1/sqrt(9 - 4*x**2), x, hints=[]) == \
asin(x*Rational(2, 3))/2
assert heurisch(1/sqrt(9 + 4*x**2), x, hints=[]) == \
asinh(x*Rational(2, 3))/2
assert heurisch(1/sqrt(3*x**2-4), x, hints=[]) == \
sqrt(3)*log(3*x + sqrt(3)*sqrt(3*x**2 - 4))/3
def test_heurisch_function():
assert heurisch(f(x), x) is None
@XFAIL
def test_heurisch_function_derivative():
# TODO: it looks like this used to work just by coincindence and
# thanks to sloppy implementation. Investigate why this used to
# work at all and if support for this can be restored.
df = diff(f(x), x)
assert heurisch(f(x)*df, x) == f(x)**2/2
assert heurisch(f(x)**2*df, x) == f(x)**3/3
assert heurisch(df/f(x), x) == log(f(x))
def test_heurisch_wrapper():
f = 1/(y + x)
assert heurisch_wrapper(f, x) == log(x + y)
f = 1/(y - x)
assert heurisch_wrapper(f, x) == -log(x - y)
f = 1/((y - x)*(y + x))
assert heurisch_wrapper(f, x) == Piecewise(
(-log(x - y)/(2*y) + log(x + y)/(2*y), Ne(y, 0)), (1/x, True))
# issue 6926
f = sqrt(x**2/((y - x)*(y + x)))
assert heurisch_wrapper(f, x) == x*sqrt(-x**2/(x**2 - y**2)) \
- y**2*sqrt(-x**2/(x**2 - y**2))/x
def test_issue_3609():
assert heurisch(1/(x * (1 + log(x)**2)), x) == atan(log(x))
### These are examples from the Poor Man's Integrator
### http://www-sop.inria.fr/cafe/Manuel.Bronstein/pmint/examples/
def test_pmint_rat():
# TODO: heurisch() is off by a constant: -3/4. Possibly different permutation
# would give the optimal result?
def drop_const(expr, x):
if expr.is_Add:
return Add(*[ arg for arg in expr.args if arg.has(x) ])
else:
return expr
f = (x**7 - 24*x**4 - 4*x**2 + 8*x - 8)/(x**8 + 6*x**6 + 12*x**4 + 8*x**2)
g = (4 + 8*x**2 + 6*x + 3*x**3)/(x**5 + 4*x**3 + 4*x) + log(x)
assert drop_const(ratsimp(heurisch(f, x)), x) == g
def test_pmint_trig():
f = (x - tan(x)) / tan(x)**2 + tan(x)
g = -x**2/2 - x/tan(x) + log(tan(x)**2 + 1)/2
assert heurisch(f, x) == g
def test_pmint_logexp():
f = (1 + x + x*exp(x))*(x + log(x) + exp(x) - 1)/(x + log(x) + exp(x))**2/x
g = log(x + exp(x) + log(x)) + 1/(x + exp(x) + log(x))
assert ratsimp(heurisch(f, x)) == g
def test_pmint_erf():
f = exp(-x**2)*erf(x)/(erf(x)**3 - erf(x)**2 - erf(x) + 1)
g = sqrt(pi)*log(erf(x) - 1)/8 - sqrt(pi)*log(erf(x) + 1)/8 - sqrt(pi)/(4*erf(x) - 4)
assert ratsimp(heurisch(f, x)) == g
def test_pmint_LambertW():
f = LambertW(x)
g = x*LambertW(x) - x + x/LambertW(x)
assert heurisch(f, x) == g
def test_pmint_besselj():
f = besselj(nu + 1, x)/besselj(nu, x)
g = nu*log(x) - log(besselj(nu, x))
assert heurisch(f, x) == g
f = (nu*besselj(nu, x) - x*besselj(nu + 1, x))/x
g = besselj(nu, x)
assert heurisch(f, x) == g
f = jn(nu + 1, x)/jn(nu, x)
g = nu*log(x) - log(jn(nu, x))
assert heurisch(f, x) == g
@slow
def test_pmint_bessel_products():
f = x*besselj(nu, x)*bessely(nu, 2*x)
g = -2*x*besselj(nu, x)*bessely(nu - 1, 2*x)/3 + x*besselj(nu - 1, x)*bessely(nu, 2*x)/3
assert heurisch(f, x) == g
f = x*besselj(nu, x)*besselk(nu, 2*x)
g = -2*x*besselj(nu, x)*besselk(nu - 1, 2*x)/5 - x*besselj(nu - 1, x)*besselk(nu, 2*x)/5
assert heurisch(f, x) == g
def test_pmint_WrightOmega():
def omega(x):
return LambertW(exp(x))
f = (1 + omega(x) * (2 + cos(omega(x)) * (x + omega(x))))/(1 + omega(x))/(x + omega(x))
g = log(x + LambertW(exp(x))) + sin(LambertW(exp(x)))
assert heurisch(f, x) == g
def test_RR():
# Make sure the algorithm does the right thing if the ring is RR. See
# issue 8685.
assert heurisch(sqrt(1 + 0.25*x**2), x, hints=[]) == \
0.5*x*sqrt(0.25*x**2 + 1) + 1.0*asinh(0.5*x)
# TODO: convert the rest of PMINT tests:
# Airy functions
# f = (x - AiryAi(x)*AiryAi(1, x)) / (x**2 - AiryAi(x)**2)
# g = Rational(1,2)*ln(x + AiryAi(x)) + Rational(1,2)*ln(x - AiryAi(x))
# f = x**2 * AiryAi(x)
# g = -AiryAi(x) + AiryAi(1, x)*x
# Whittaker functions
# f = WhittakerW(mu + 1, nu, x) / (WhittakerW(mu, nu, x) * x)
# g = x/2 - mu*ln(x) - ln(WhittakerW(mu, nu, x))
def test_issue_22527():
t, R = symbols(r't R')
z = Function('z')(t)
def f(x):
return x/sqrt(R**2 - x**2)
Uz = integrate(f(z), z)
Ut = integrate(f(t), t)
assert Ut == Uz.subs(z, t)
def test_heurisch_complex_erf_issue_26338():
r = symbols('r', real=True)
a = exp(-r**2/(2*(2 - I)**2))
assert heurisch(a, r, hints=[]) is None # None, not a wrong soln
a = sqrt(pi)*erf((1 + I)/2)/2
assert integrate(exp(-I*r**2/2), (r, 0, 1)) == a - I*a
a = exp(-x**2/(2*(2 - I)**2))
assert heurisch(a, x, hints=[]) is None # None, not a wrong soln
a = sqrt(pi)*erf((1 + I)/2)/2
assert integrate(exp(-I*x**2/2), (x, 0, 1)) == a - I*a
def test_issue_15498():
Z0 = Function('Z0')
k01, k10, t, s= symbols('k01 k10 t s', real=True, positive=True)
m = Matrix([[exp(-k10*t)]])
_83 = Rational(83, 100) # 0.83 works, too
[a, b, c, d, e, f, g] = [100, 0.5, _83, 50, 0.6, 2, 120]
AIF_btf = a*(d*e*(1 - exp(-(t - b)/e)) + f*g*(1 - exp(-(t - b)/g)))
AIF_atf = a*(d*e*exp(-(t - b)/e)*(exp((c - b)/e) - 1
) + f*g*exp(-(t - b)/g)*(exp((c - b)/g) - 1))
AIF_sym = Piecewise((0, t < b), (AIF_btf, And(b <= t, t < c)), (AIF_atf, c <= t))
aif_eq = Eq(Z0(t), AIF_sym)
f_vec = Matrix([[k01*Z0(t)]])
integrand = m*m.subs(t, s)**-1*f_vec.subs(aif_eq.lhs, aif_eq.rhs).subs(t, s)
solution = integrate(integrand[0], (s, 0, t))
assert solution is not None # does not hang and takes less than 10 s

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,627 @@
from sympy.functions.elementary.complexes import Abs
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.core import S, Rational
from sympy.integrals.intpoly import (decompose, best_origin, distance_to_side,
polytope_integrate, point_sort,
hyperplane_parameters, main_integrate3d,
main_integrate, polygon_integrate,
lineseg_integrate, integration_reduction,
integration_reduction_dynamic, is_vertex)
from sympy.geometry.line import Segment2D
from sympy.geometry.polygon import Polygon
from sympy.geometry.point import Point, Point2D
from sympy.abc import x, y, z
from sympy.testing.pytest import slow
def test_decompose():
assert decompose(x) == {1: x}
assert decompose(x**2) == {2: x**2}
assert decompose(x*y) == {2: x*y}
assert decompose(x + y) == {1: x + y}
assert decompose(x**2 + y) == {1: y, 2: x**2}
assert decompose(8*x**2 + 4*y + 7) == {0: 7, 1: 4*y, 2: 8*x**2}
assert decompose(x**2 + 3*y*x) == {2: x**2 + 3*x*y}
assert decompose(9*x**2 + y + 4*x + x**3 + y**2*x + 3) ==\
{0: 3, 1: 4*x + y, 2: 9*x**2, 3: x**3 + x*y**2}
assert decompose(x, True) == {x}
assert decompose(x ** 2, True) == {x**2}
assert decompose(x * y, True) == {x * y}
assert decompose(x + y, True) == {x, y}
assert decompose(x ** 2 + y, True) == {y, x ** 2}
assert decompose(8 * x ** 2 + 4 * y + 7, True) == {7, 4*y, 8*x**2}
assert decompose(x ** 2 + 3 * y * x, True) == {x ** 2, 3 * x * y}
assert decompose(9 * x ** 2 + y + 4 * x + x ** 3 + y ** 2 * x + 3, True) == \
{3, y, 4*x, 9*x**2, x*y**2, x**3}
def test_best_origin():
expr1 = y ** 2 * x ** 5 + y ** 5 * x ** 7 + 7 * x + x ** 12 + y ** 7 * x
l1 = Segment2D(Point(0, 3), Point(1, 1))
l2 = Segment2D(Point(S(3) / 2, 0), Point(S(3) / 2, 3))
l3 = Segment2D(Point(0, S(3) / 2), Point(3, S(3) / 2))
l4 = Segment2D(Point(0, 2), Point(2, 0))
l5 = Segment2D(Point(0, 2), Point(1, 1))
l6 = Segment2D(Point(2, 0), Point(1, 1))
assert best_origin((2, 1), 3, l1, expr1) == (0, 3)
# XXX: Should these return exact Rational output? Maybe best_origin should
# sympify its arguments...
assert best_origin((2, 0), 3, l2, x ** 7) == (1.5, 0)
assert best_origin((0, 2), 3, l3, x ** 7) == (0, 1.5)
assert best_origin((1, 1), 2, l4, x ** 7 * y ** 3) == (0, 2)
assert best_origin((1, 1), 2, l4, x ** 3 * y ** 7) == (2, 0)
assert best_origin((1, 1), 2, l5, x ** 2 * y ** 9) == (0, 2)
assert best_origin((1, 1), 2, l6, x ** 9 * y ** 2) == (2, 0)
@slow
def test_polytope_integrate():
# Convex 2-Polytopes
# Vertex representation
assert polytope_integrate(Polygon(Point(0, 0), Point(0, 2),
Point(4, 0)), 1) == 4
assert polytope_integrate(Polygon(Point(0, 0), Point(0, 1),
Point(1, 1), Point(1, 0)), x * y) ==\
Rational(1, 4)
assert polytope_integrate(Polygon(Point(0, 3), Point(5, 3), Point(1, 1)),
6*x**2 - 40*y) == Rational(-935, 3)
assert polytope_integrate(Polygon(Point(0, 0), Point(0, sqrt(3)),
Point(sqrt(3), sqrt(3)),
Point(sqrt(3), 0)), 1) == 3
hexagon = Polygon(Point(0, 0), Point(-sqrt(3) / 2, S.Half),
Point(-sqrt(3) / 2, S(3) / 2), Point(0, 2),
Point(sqrt(3) / 2, S(3) / 2), Point(sqrt(3) / 2, S.Half))
assert polytope_integrate(hexagon, 1) == S(3*sqrt(3)) / 2
# Hyperplane representation
assert polytope_integrate([((-1, 0), 0), ((1, 2), 4),
((0, -1), 0)], 1) == 4
assert polytope_integrate([((-1, 0), 0), ((0, 1), 1),
((1, 0), 1), ((0, -1), 0)], x * y) == Rational(1, 4)
assert polytope_integrate([((0, 1), 3), ((1, -2), -1),
((-2, -1), -3)], 6*x**2 - 40*y) == Rational(-935, 3)
assert polytope_integrate([((-1, 0), 0), ((0, sqrt(3)), 3),
((sqrt(3), 0), 3), ((0, -1), 0)], 1) == 3
hexagon = [((Rational(-1, 2), -sqrt(3) / 2), 0),
((-1, 0), sqrt(3) / 2),
((Rational(-1, 2), sqrt(3) / 2), sqrt(3)),
((S.Half, sqrt(3) / 2), sqrt(3)),
((1, 0), sqrt(3) / 2),
((S.Half, -sqrt(3) / 2), 0)]
assert polytope_integrate(hexagon, 1) == S(3*sqrt(3)) / 2
# Non-convex polytopes
# Vertex representation
assert polytope_integrate(Polygon(Point(-1, -1), Point(-1, 1),
Point(1, 1), Point(0, 0),
Point(1, -1)), 1) == 3
assert polytope_integrate(Polygon(Point(-1, -1), Point(-1, 1),
Point(0, 0), Point(1, 1),
Point(1, -1), Point(0, 0)), 1) == 2
# Hyperplane representation
assert polytope_integrate([((-1, 0), 1), ((0, 1), 1), ((1, -1), 0),
((1, 1), 0), ((0, -1), 1)], 1) == 3
assert polytope_integrate([((-1, 0), 1), ((1, 1), 0), ((-1, 1), 0),
((1, 0), 1), ((-1, -1), 0),
((1, -1), 0)], 1) == 2
# Tests for 2D polytopes mentioned in Chin et al(Page 10):
# http://dilbert.engr.ucdavis.edu/~suku/quadrature/cls-integration.pdf
fig1 = Polygon(Point(1.220, -0.827), Point(-1.490, -4.503),
Point(-3.766, -1.622), Point(-4.240, -0.091),
Point(-3.160, 4), Point(-0.981, 4.447),
Point(0.132, 4.027))
assert polytope_integrate(fig1, x**2 + x*y + y**2) ==\
S(2031627344735367)/(8*10**12)
fig2 = Polygon(Point(4.561, 2.317), Point(1.491, -1.315),
Point(-3.310, -3.164), Point(-4.845, -3.110),
Point(-4.569, 1.867))
assert polytope_integrate(fig2, x**2 + x*y + y**2) ==\
S(517091313866043)/(16*10**11)
fig3 = Polygon(Point(-2.740, -1.888), Point(-3.292, 4.233),
Point(-2.723, -0.697), Point(-0.643, -3.151))
assert polytope_integrate(fig3, x**2 + x*y + y**2) ==\
S(147449361647041)/(8*10**12)
fig4 = Polygon(Point(0.211, -4.622), Point(-2.684, 3.851),
Point(0.468, 4.879), Point(4.630, -1.325),
Point(-0.411, -1.044))
assert polytope_integrate(fig4, x**2 + x*y + y**2) ==\
S(180742845225803)/(10**12)
# Tests for many polynomials with maximum degree given(2D case).
tri = Polygon(Point(0, 3), Point(5, 3), Point(1, 1))
polys = []
expr1 = x**9*y + x**7*y**3 + 2*x**2*y**8
expr2 = x**6*y**4 + x**5*y**5 + 2*y**10
expr3 = x**10 + x**9*y + x**8*y**2 + x**5*y**5
polys.extend((expr1, expr2, expr3))
result_dict = polytope_integrate(tri, polys, max_degree=10)
assert result_dict[expr1] == Rational(615780107, 594)
assert result_dict[expr2] == Rational(13062161, 27)
assert result_dict[expr3] == Rational(1946257153, 924)
tri = Polygon(Point(0, 3), Point(5, 3), Point(1, 1))
expr1 = x**7*y**1 + 2*x**2*y**6
expr2 = x**6*y**4 + x**5*y**5 + 2*y**10
expr3 = x**10 + x**9*y + x**8*y**2 + x**5*y**5
polys.extend((expr1, expr2, expr3))
assert polytope_integrate(tri, polys, max_degree=9) == \
{x**7*y + 2*x**2*y**6: Rational(489262, 9)}
# Tests when all integral of all monomials up to a max_degree is to be
# calculated.
assert polytope_integrate(Polygon(Point(0, 0), Point(0, 1),
Point(1, 1), Point(1, 0)),
max_degree=4) == {0: 0, 1: 1, x: S.Half,
x ** 2 * y ** 2: S.One / 9,
x ** 4: S.One / 5,
y ** 4: S.One / 5,
y: S.Half,
x * y ** 2: S.One / 6,
y ** 2: S.One / 3,
x ** 3: S.One / 4,
x ** 2 * y: S.One / 6,
x ** 3 * y: S.One / 8,
x * y: S.One / 4,
y ** 3: S.One / 4,
x ** 2: S.One / 3,
x * y ** 3: S.One / 8}
# Tests for 3D polytopes
cube1 = [[(0, 0, 0), (0, 6, 6), (6, 6, 6), (3, 6, 0),
(0, 6, 0), (6, 0, 6), (3, 0, 0), (0, 0, 6)],
[1, 2, 3, 4], [3, 2, 5, 6], [1, 7, 5, 2], [0, 6, 5, 7],
[1, 4, 0, 7], [0, 4, 3, 6]]
assert polytope_integrate(cube1, 1) == S(162)
# 3D Test cases in Chin et al(2015)
cube2 = [[(0, 0, 0), (0, 0, 5), (0, 5, 0), (0, 5, 5), (5, 0, 0),
(5, 0, 5), (5, 5, 0), (5, 5, 5)],
[3, 7, 6, 2], [1, 5, 7, 3], [5, 4, 6, 7], [0, 4, 5, 1],
[2, 0, 1, 3], [2, 6, 4, 0]]
cube3 = [[(0, 0, 0), (5, 0, 0), (5, 4, 0), (3, 2, 0), (3, 5, 0),
(0, 5, 0), (0, 0, 5), (5, 0, 5), (5, 4, 5), (3, 2, 5),
(3, 5, 5), (0, 5, 5)],
[6, 11, 5, 0], [1, 7, 6, 0], [5, 4, 3, 2, 1, 0], [11, 10, 4, 5],
[10, 9, 3, 4], [9, 8, 2, 3], [8, 7, 1, 2], [7, 8, 9, 10, 11, 6]]
cube4 = [[(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1),
(S.One / 4, S.One / 4, S.One / 4)],
[0, 2, 1], [1, 3, 0], [4, 2, 3], [4, 3, 1],
[0, 1, 2], [2, 4, 1], [0, 3, 2]]
assert polytope_integrate(cube2, x ** 2 + y ** 2 + x * y + z ** 2) ==\
Rational(15625, 4)
assert polytope_integrate(cube3, x ** 2 + y ** 2 + x * y + z ** 2) ==\
S(33835) / 12
assert polytope_integrate(cube4, x ** 2 + y ** 2 + x * y + z ** 2) ==\
S(37) / 960
# Test cases from Mathematica's PolyhedronData library
octahedron = [[(S.NegativeOne / sqrt(2), 0, 0), (0, S.One / sqrt(2), 0),
(0, 0, S.NegativeOne / sqrt(2)), (0, 0, S.One / sqrt(2)),
(0, S.NegativeOne / sqrt(2), 0), (S.One / sqrt(2), 0, 0)],
[3, 4, 5], [3, 5, 1], [3, 1, 0], [3, 0, 4], [4, 0, 2],
[4, 2, 5], [2, 0, 1], [5, 2, 1]]
assert polytope_integrate(octahedron, 1) == sqrt(2) / 3
great_stellated_dodecahedron =\
[[(-0.32491969623290634095, 0, 0.42532540417601993887),
(0.32491969623290634095, 0, -0.42532540417601993887),
(-0.52573111211913359231, 0, 0.10040570794311363956),
(0.52573111211913359231, 0, -0.10040570794311363956),
(-0.10040570794311363956, -0.3090169943749474241, 0.42532540417601993887),
(-0.10040570794311363956, 0.30901699437494742410, 0.42532540417601993887),
(0.10040570794311363956, -0.3090169943749474241, -0.42532540417601993887),
(0.10040570794311363956, 0.30901699437494742410, -0.42532540417601993887),
(-0.16245984811645317047, -0.5, 0.10040570794311363956),
(-0.16245984811645317047, 0.5, 0.10040570794311363956),
(0.16245984811645317047, -0.5, -0.10040570794311363956),
(0.16245984811645317047, 0.5, -0.10040570794311363956),
(-0.42532540417601993887, -0.3090169943749474241, -0.10040570794311363956),
(-0.42532540417601993887, 0.30901699437494742410, -0.10040570794311363956),
(-0.26286555605956679615, 0.1909830056250525759, -0.42532540417601993887),
(-0.26286555605956679615, -0.1909830056250525759, -0.42532540417601993887),
(0.26286555605956679615, 0.1909830056250525759, 0.42532540417601993887),
(0.26286555605956679615, -0.1909830056250525759, 0.42532540417601993887),
(0.42532540417601993887, -0.3090169943749474241, 0.10040570794311363956),
(0.42532540417601993887, 0.30901699437494742410, 0.10040570794311363956)],
[12, 3, 0, 6, 16], [17, 7, 0, 3, 13],
[9, 6, 0, 7, 8], [18, 2, 1, 4, 14],
[15, 5, 1, 2, 19], [11, 4, 1, 5, 10],
[8, 19, 2, 18, 9], [10, 13, 3, 12, 11],
[16, 14, 4, 11, 12], [13, 10, 5, 15, 17],
[14, 16, 6, 9, 18], [19, 8, 7, 17, 15]]
# Actual volume is : 0.163118960624632
assert Abs(polytope_integrate(great_stellated_dodecahedron, 1) -\
0.163118960624632) < 1e-12
expr = x **2 + y ** 2 + z ** 2
octahedron_five_compound = [[(0, -0.7071067811865475244, 0),
(0, 0.70710678118654752440, 0),
(0.1148764602736805918,
-0.35355339059327376220, -0.60150095500754567366),
(0.1148764602736805918, 0.35355339059327376220,
-0.60150095500754567366),
(0.18587401723009224507,
-0.57206140281768429760, 0.37174803446018449013),
(0.18587401723009224507, 0.57206140281768429760,
0.37174803446018449013),
(0.30075047750377283683, -0.21850801222441053540,
0.60150095500754567366),
(0.30075047750377283683, 0.21850801222441053540,
0.60150095500754567366),
(0.48662449473386508189, -0.35355339059327376220,
-0.37174803446018449013),
(0.48662449473386508189, 0.35355339059327376220,
-0.37174803446018449013),
(-0.60150095500754567366, 0, -0.37174803446018449013),
(-0.30075047750377283683, -0.21850801222441053540,
-0.60150095500754567366),
(-0.30075047750377283683, 0.21850801222441053540,
-0.60150095500754567366),
(0.60150095500754567366, 0, 0.37174803446018449013),
(0.4156269377774534286, -0.57206140281768429760, 0),
(0.4156269377774534286, 0.57206140281768429760, 0),
(0.37174803446018449013, 0, -0.60150095500754567366),
(-0.4156269377774534286, -0.57206140281768429760, 0),
(-0.4156269377774534286, 0.57206140281768429760, 0),
(-0.67249851196395732696, -0.21850801222441053540, 0),
(-0.67249851196395732696, 0.21850801222441053540, 0),
(0.67249851196395732696, -0.21850801222441053540, 0),
(0.67249851196395732696, 0.21850801222441053540, 0),
(-0.37174803446018449013, 0, 0.60150095500754567366),
(-0.48662449473386508189, -0.35355339059327376220,
0.37174803446018449013),
(-0.48662449473386508189, 0.35355339059327376220,
0.37174803446018449013),
(-0.18587401723009224507, -0.57206140281768429760,
-0.37174803446018449013),
(-0.18587401723009224507, 0.57206140281768429760,
-0.37174803446018449013),
(-0.11487646027368059176, -0.35355339059327376220,
0.60150095500754567366),
(-0.11487646027368059176, 0.35355339059327376220,
0.60150095500754567366)],
[0, 10, 16], [23, 10, 0], [16, 13, 0],
[0, 13, 23], [16, 10, 1], [1, 10, 23],
[1, 13, 16], [23, 13, 1], [2, 4, 19],
[22, 4, 2], [2, 19, 27], [27, 22, 2],
[20, 5, 3], [3, 5, 21], [26, 20, 3],
[3, 21, 26], [29, 19, 4], [4, 22, 29],
[5, 20, 28], [28, 21, 5], [6, 8, 15],
[17, 8, 6], [6, 15, 25], [25, 17, 6],
[14, 9, 7], [7, 9, 18], [24, 14, 7],
[7, 18, 24], [8, 12, 15], [17, 12, 8],
[14, 11, 9], [9, 11, 18], [11, 14, 24],
[24, 18, 11], [25, 15, 12], [12, 17, 25],
[29, 27, 19], [20, 26, 28], [28, 26, 21],
[22, 27, 29]]
assert Abs(polytope_integrate(octahedron_five_compound, expr)) - 0.353553\
< 1e-6
cube_five_compound = [[(-0.1624598481164531631, -0.5, -0.6881909602355867691),
(-0.1624598481164531631, 0.5, -0.6881909602355867691),
(0.1624598481164531631, -0.5, 0.68819096023558676910),
(0.1624598481164531631, 0.5, 0.68819096023558676910),
(-0.52573111211913359231, 0, -0.6881909602355867691),
(0.52573111211913359231, 0, 0.68819096023558676910),
(-0.26286555605956679615, -0.8090169943749474241,
-0.1624598481164531631),
(-0.26286555605956679615, 0.8090169943749474241,
-0.1624598481164531631),
(0.26286555605956680301, -0.8090169943749474241,
0.1624598481164531631),
(0.26286555605956680301, 0.8090169943749474241,
0.1624598481164531631),
(-0.42532540417601993887, -0.3090169943749474241,
0.68819096023558676910),
(-0.42532540417601993887, 0.30901699437494742410,
0.68819096023558676910),
(0.42532540417601996609, -0.3090169943749474241,
-0.6881909602355867691),
(0.42532540417601996609, 0.30901699437494742410,
-0.6881909602355867691),
(-0.6881909602355867691, -0.5, 0.1624598481164531631),
(-0.6881909602355867691, 0.5, 0.1624598481164531631),
(0.68819096023558676910, -0.5, -0.1624598481164531631),
(0.68819096023558676910, 0.5, -0.1624598481164531631),
(-0.85065080835203998877, 0, -0.1624598481164531631),
(0.85065080835203993218, 0, 0.1624598481164531631)],
[18, 10, 3, 7], [13, 19, 8, 0], [18, 0, 8, 10],
[3, 19, 13, 7], [18, 7, 13, 0], [8, 19, 3, 10],
[6, 2, 11, 18], [1, 9, 19, 12], [11, 9, 1, 18],
[6, 12, 19, 2], [1, 12, 6, 18], [11, 2, 19, 9],
[4, 14, 11, 7], [17, 5, 8, 12], [4, 12, 8, 14],
[11, 5, 17, 7], [4, 7, 17, 12], [8, 5, 11, 14],
[6, 10, 15, 4], [13, 9, 5, 16], [15, 9, 13, 4],
[6, 16, 5, 10], [13, 16, 6, 4], [15, 10, 5, 9],
[14, 15, 1, 0], [16, 17, 3, 2], [14, 2, 3, 15],
[1, 17, 16, 0], [14, 0, 16, 2], [3, 17, 1, 15]]
assert Abs(polytope_integrate(cube_five_compound, expr) - 1.25) < 1e-12
echidnahedron = [[(0, 0, -2.4898982848827801995),
(0, 0, 2.4898982848827802734),
(0, -4.2360679774997896964, -2.4898982848827801995),
(0, -4.2360679774997896964, 2.4898982848827802734),
(0, 4.2360679774997896964, -2.4898982848827801995),
(0, 4.2360679774997896964, 2.4898982848827802734),
(-4.0287400534704067567, -1.3090169943749474241, -2.4898982848827801995),
(-4.0287400534704067567, -1.3090169943749474241, 2.4898982848827802734),
(-4.0287400534704067567, 1.3090169943749474241, -2.4898982848827801995),
(-4.0287400534704067567, 1.3090169943749474241, 2.4898982848827802734),
(4.0287400534704069747, -1.3090169943749474241, -2.4898982848827801995),
(4.0287400534704069747, -1.3090169943749474241, 2.4898982848827802734),
(4.0287400534704069747, 1.3090169943749474241, -2.4898982848827801995),
(4.0287400534704069747, 1.3090169943749474241, 2.4898982848827802734),
(-2.4898982848827801995, -3.4270509831248422723, -2.4898982848827801995),
(-2.4898982848827801995, -3.4270509831248422723, 2.4898982848827802734),
(-2.4898982848827801995, 3.4270509831248422723, -2.4898982848827801995),
(-2.4898982848827801995, 3.4270509831248422723, 2.4898982848827802734),
(2.4898982848827802734, -3.4270509831248422723, -2.4898982848827801995),
(2.4898982848827802734, -3.4270509831248422723, 2.4898982848827802734),
(2.4898982848827802734, 3.4270509831248422723, -2.4898982848827801995),
(2.4898982848827802734, 3.4270509831248422723, 2.4898982848827802734),
(-4.7169310137059934362, -0.8090169943749474241, -1.1135163644116066184),
(-4.7169310137059934362, 0.8090169943749474241, -1.1135163644116066184),
(4.7169310137059937438, -0.8090169943749474241, 1.11351636441160673519),
(4.7169310137059937438, 0.8090169943749474241, 1.11351636441160673519),
(-4.2916056095299737777, -2.1180339887498948482, 1.11351636441160673519),
(-4.2916056095299737777, 2.1180339887498948482, 1.11351636441160673519),
(4.2916056095299737777, -2.1180339887498948482, -1.1135163644116066184),
(4.2916056095299737777, 2.1180339887498948482, -1.1135163644116066184),
(-3.6034146492943870399, 0, -3.3405490932348205213),
(3.6034146492943870399, 0, 3.3405490932348202056),
(-3.3405490932348205213, -3.4270509831248422723, 1.11351636441160673519),
(-3.3405490932348205213, 3.4270509831248422723, 1.11351636441160673519),
(3.3405490932348202056, -3.4270509831248422723, -1.1135163644116066184),
(3.3405490932348202056, 3.4270509831248422723, -1.1135163644116066184),
(-2.9152236890588002395, -2.1180339887498948482, 3.3405490932348202056),
(-2.9152236890588002395, 2.1180339887498948482, 3.3405490932348202056),
(2.9152236890588002395, -2.1180339887498948482, -3.3405490932348205213),
(2.9152236890588002395, 2.1180339887498948482, -3.3405490932348205213),
(-2.2270327288232132368, 0, -1.1135163644116066184),
(-2.2270327288232132368, -4.2360679774997896964, -1.1135163644116066184),
(-2.2270327288232132368, 4.2360679774997896964, -1.1135163644116066184),
(2.2270327288232134704, 0, 1.11351636441160673519),
(2.2270327288232134704, -4.2360679774997896964, 1.11351636441160673519),
(2.2270327288232134704, 4.2360679774997896964, 1.11351636441160673519),
(-1.8017073246471935200, -1.3090169943749474241, 1.11351636441160673519),
(-1.8017073246471935200, 1.3090169943749474241, 1.11351636441160673519),
(1.8017073246471935043, -1.3090169943749474241, -1.1135163644116066184),
(1.8017073246471935043, 1.3090169943749474241, -1.1135163644116066184),
(-1.3763819204711735382, 0, -4.7169310137059934362),
(-1.3763819204711735382, 0, 0.26286555605956679615),
(1.37638192047117353821, 0, 4.7169310137059937438),
(1.37638192047117353821, 0, -0.26286555605956679615),
(-1.1135163644116066184, -3.4270509831248422723, -3.3405490932348205213),
(-1.1135163644116066184, -0.8090169943749474241, 4.7169310137059937438),
(-1.1135163644116066184, -0.8090169943749474241, -0.26286555605956679615),
(-1.1135163644116066184, 0.8090169943749474241, 4.7169310137059937438),
(-1.1135163644116066184, 0.8090169943749474241, -0.26286555605956679615),
(-1.1135163644116066184, 3.4270509831248422723, -3.3405490932348205213),
(1.11351636441160673519, -3.4270509831248422723, 3.3405490932348202056),
(1.11351636441160673519, -0.8090169943749474241, -4.7169310137059934362),
(1.11351636441160673519, -0.8090169943749474241, 0.26286555605956679615),
(1.11351636441160673519, 0.8090169943749474241, -4.7169310137059934362),
(1.11351636441160673519, 0.8090169943749474241, 0.26286555605956679615),
(1.11351636441160673519, 3.4270509831248422723, 3.3405490932348202056),
(-0.85065080835203998877, 0, 1.11351636441160673519),
(0.85065080835203993218, 0, -1.1135163644116066184),
(-0.6881909602355867691, -0.5, -1.1135163644116066184),
(-0.6881909602355867691, 0.5, -1.1135163644116066184),
(-0.6881909602355867691, -4.7360679774997896964, -1.1135163644116066184),
(-0.6881909602355867691, -2.1180339887498948482, -1.1135163644116066184),
(-0.6881909602355867691, 2.1180339887498948482, -1.1135163644116066184),
(-0.6881909602355867691, 4.7360679774997896964, -1.1135163644116066184),
(0.68819096023558676910, -0.5, 1.11351636441160673519),
(0.68819096023558676910, 0.5, 1.11351636441160673519),
(0.68819096023558676910, -4.7360679774997896964, 1.11351636441160673519),
(0.68819096023558676910, -2.1180339887498948482, 1.11351636441160673519),
(0.68819096023558676910, 2.1180339887498948482, 1.11351636441160673519),
(0.68819096023558676910, 4.7360679774997896964, 1.11351636441160673519),
(-0.42532540417601993887, -1.3090169943749474241, -4.7169310137059934362),
(-0.42532540417601993887, -1.3090169943749474241, 0.26286555605956679615),
(-0.42532540417601993887, 1.3090169943749474241, -4.7169310137059934362),
(-0.42532540417601993887, 1.3090169943749474241, 0.26286555605956679615),
(-0.26286555605956679615, -0.8090169943749474241, 1.11351636441160673519),
(-0.26286555605956679615, 0.8090169943749474241, 1.11351636441160673519),
(0.26286555605956679615, -0.8090169943749474241, -1.1135163644116066184),
(0.26286555605956679615, 0.8090169943749474241, -1.1135163644116066184),
(0.42532540417601996609, -1.3090169943749474241, 4.7169310137059937438),
(0.42532540417601996609, -1.3090169943749474241, -0.26286555605956679615),
(0.42532540417601996609, 1.3090169943749474241, 4.7169310137059937438),
(0.42532540417601996609, 1.3090169943749474241, -0.26286555605956679615)],
[9, 66, 47], [44, 62, 77], [20, 91, 49], [33, 47, 83],
[3, 77, 84], [12, 49, 53], [36, 84, 66], [28, 53, 62],
[73, 83, 91], [15, 84, 46], [25, 64, 43], [16, 58, 72],
[26, 46, 51], [11, 43, 74], [4, 72, 91], [60, 74, 84],
[35, 91, 64], [23, 51, 58], [19, 74, 77], [79, 83, 78],
[6, 56, 40], [76, 77, 81], [21, 78, 75], [8, 40, 58],
[31, 75, 74], [42, 58, 83], [41, 81, 56], [13, 75, 43],
[27, 51, 47], [2, 89, 71], [24, 43, 62], [17, 47, 85],
[14, 71, 56], [65, 85, 75], [22, 56, 51], [34, 62, 89],
[5, 85, 78], [32, 81, 46], [10, 53, 48], [45, 78, 64],
[7, 46, 66], [18, 48, 89], [37, 66, 85], [70, 89, 81],
[29, 64, 53], [88, 74, 1], [38, 67, 48], [42, 83, 72],
[57, 1, 85], [34, 48, 62], [59, 72, 87], [19, 62, 74],
[63, 87, 67], [17, 85, 83], [52, 75, 1], [39, 87, 49],
[22, 51, 40], [55, 1, 66], [29, 49, 64], [30, 40, 69],
[13, 64, 75], [82, 69, 87], [7, 66, 51], [90, 85, 1],
[59, 69, 72], [70, 81, 71], [88, 1, 84], [73, 72, 83],
[54, 71, 68], [5, 83, 85], [50, 68, 69], [3, 84, 81],
[57, 66, 1], [30, 68, 40], [28, 62, 48], [52, 1, 74],
[23, 40, 51], [38, 48, 86], [9, 51, 66], [80, 86, 68],
[11, 74, 62], [55, 84, 1], [54, 86, 71], [35, 64, 49],
[90, 1, 75], [41, 71, 81], [39, 49, 67], [15, 81, 84],
[61, 67, 86], [21, 75, 64], [24, 53, 43], [50, 69, 0],
[37, 85, 47], [31, 43, 75], [61, 0, 67], [27, 47, 58],
[10, 67, 53], [8, 58, 69], [90, 75, 85], [45, 91, 78],
[80, 68, 0], [36, 66, 46], [65, 78, 85], [63, 0, 87],
[32, 46, 56], [20, 87, 91], [14, 56, 68], [57, 85, 66],
[33, 58, 47], [61, 86, 0], [60, 84, 77], [37, 47, 66],
[82, 0, 69], [44, 77, 89], [16, 69, 58], [18, 89, 86],
[55, 66, 84], [26, 56, 46], [63, 67, 0], [31, 74, 43],
[36, 46, 84], [50, 0, 68], [25, 43, 53], [6, 68, 56],
[12, 53, 67], [88, 84, 74], [76, 89, 77], [82, 87, 0],
[65, 75, 78], [60, 77, 74], [80, 0, 86], [79, 78, 91],
[2, 86, 89], [4, 91, 87], [52, 74, 75], [21, 64, 78],
[18, 86, 48], [23, 58, 40], [5, 78, 83], [28, 48, 53],
[6, 40, 68], [25, 53, 64], [54, 68, 86], [33, 83, 58],
[17, 83, 47], [12, 67, 49], [41, 56, 71], [9, 47, 51],
[35, 49, 91], [2, 71, 86], [79, 91, 83], [38, 86, 67],
[26, 51, 56], [7, 51, 46], [4, 87, 72], [34, 89, 48],
[15, 46, 81], [42, 72, 58], [10, 48, 67], [27, 58, 51],
[39, 67, 87], [76, 81, 89], [3, 81, 77], [8, 69, 40],
[29, 53, 49], [19, 77, 62], [22, 40, 56], [20, 49, 87],
[32, 56, 81], [59, 87, 69], [24, 62, 53], [11, 62, 43],
[14, 68, 71], [73, 91, 72], [13, 43, 64], [70, 71, 89],
[16, 72, 69], [44, 89, 62], [30, 69, 68], [45, 64, 91]]
# Actual volume is : 51.405764746872634
assert Abs(polytope_integrate(echidnahedron, 1) - 51.4057647468726) < 1e-12
assert Abs(polytope_integrate(echidnahedron, expr) - 253.569603474519) <\
1e-12
# Tests for many polynomials with maximum degree given(2D case).
assert polytope_integrate(cube2, [x**2, y*z], max_degree=2) == \
{y * z: 3125 / S(4), x ** 2: 3125 / S(3)}
assert polytope_integrate(cube2, max_degree=2) == \
{1: 125, x: 625 / S(2), x * z: 3125 / S(4), y: 625 / S(2),
y * z: 3125 / S(4), z ** 2: 3125 / S(3), y ** 2: 3125 / S(3),
z: 625 / S(2), x * y: 3125 / S(4), x ** 2: 3125 / S(3)}
def test_point_sort():
assert point_sort([Point(0, 0), Point(1, 0), Point(1, 1)]) == \
[Point2D(1, 1), Point2D(1, 0), Point2D(0, 0)]
fig6 = Polygon((0, 0), (1, 0), (1, 1))
assert polytope_integrate(fig6, x*y) == Rational(-1, 8)
assert polytope_integrate(fig6, x*y, clockwise = True) == Rational(1, 8)
def test_polytopes_intersecting_sides():
fig5 = Polygon(Point(-4.165, -0.832), Point(-3.668, 1.568),
Point(-3.266, 1.279), Point(-1.090, -2.080),
Point(3.313, -0.683), Point(3.033, -4.845),
Point(-4.395, 4.840), Point(-1.007, -3.328))
assert polytope_integrate(fig5, x**2 + x*y + y**2) ==\
S(1633405224899363)/(24*10**12)
fig6 = Polygon(Point(-3.018, -4.473), Point(-0.103, 2.378),
Point(-1.605, -2.308), Point(4.516, -0.771),
Point(4.203, 0.478))
assert polytope_integrate(fig6, x**2 + x*y + y**2) ==\
S(88161333955921)/(3*10**12)
def test_max_degree():
polygon = Polygon((0, 0), (0, 1), (1, 1), (1, 0))
polys = [1, x, y, x*y, x**2*y, x*y**2]
assert polytope_integrate(polygon, polys, max_degree=3) == \
{1: 1, x: S.Half, y: S.Half, x*y: Rational(1, 4), x**2*y: Rational(1, 6), x*y**2: Rational(1, 6)}
assert polytope_integrate(polygon, polys, max_degree=2) == \
{1: 1, x: S.Half, y: S.Half, x*y: Rational(1, 4)}
assert polytope_integrate(polygon, polys, max_degree=1) == \
{1: 1, x: S.Half, y: S.Half}
def test_main_integrate3d():
cube = [[(0, 0, 0), (0, 0, 5), (0, 5, 0), (0, 5, 5), (5, 0, 0),\
(5, 0, 5), (5, 5, 0), (5, 5, 5)],\
[2, 6, 7, 3], [3, 7, 5, 1], [7, 6, 4, 5], [1, 5, 4, 0],\
[3, 1, 0, 2], [0, 4, 6, 2]]
vertices = cube[0]
faces = cube[1:]
hp_params = hyperplane_parameters(faces, vertices)
assert main_integrate3d(1, faces, vertices, hp_params) == -125
assert main_integrate3d(1, faces, vertices, hp_params, max_degree=1) == \
{1: -125, y: Rational(-625, 2), z: Rational(-625, 2), x: Rational(-625, 2)}
def test_main_integrate():
triangle = Polygon((0, 3), (5, 3), (1, 1))
facets = triangle.sides
hp_params = hyperplane_parameters(triangle)
assert main_integrate(x**2 + y**2, facets, hp_params) == Rational(325, 6)
assert main_integrate(x**2 + y**2, facets, hp_params, max_degree=1) == \
{0: 0, 1: 5, y: Rational(35, 3), x: 10}
def test_polygon_integrate():
cube = [[(0, 0, 0), (0, 0, 5), (0, 5, 0), (0, 5, 5), (5, 0, 0),\
(5, 0, 5), (5, 5, 0), (5, 5, 5)],\
[2, 6, 7, 3], [3, 7, 5, 1], [7, 6, 4, 5], [1, 5, 4, 0],\
[3, 1, 0, 2], [0, 4, 6, 2]]
facet = cube[1]
facets = cube[1:]
vertices = cube[0]
assert polygon_integrate(facet, [(0, 1, 0), 5], 0, facets, vertices, 1, 0) == -25
def test_distance_to_side():
point = (0, 0, 0)
assert distance_to_side(point, [(0, 0, 1), (0, 1, 0)], (1, 0, 0)) == -sqrt(2)/2
def test_lineseg_integrate():
polygon = [(0, 5, 0), (5, 5, 0), (5, 5, 5), (0, 5, 5)]
line_seg = [(0, 5, 0), (5, 5, 0)]
assert lineseg_integrate(polygon, 0, line_seg, 1, 0) == 5
assert lineseg_integrate(polygon, 0, line_seg, 0, 0) == 0
def test_integration_reduction():
triangle = Polygon(Point(0, 3), Point(5, 3), Point(1, 1))
facets = triangle.sides
a, b = hyperplane_parameters(triangle)[0]
assert integration_reduction(facets, 0, a, b, 1, (x, y), 0) == 5
assert integration_reduction(facets, 0, a, b, 0, (x, y), 0) == 0
def test_integration_reduction_dynamic():
triangle = Polygon(Point(0, 3), Point(5, 3), Point(1, 1))
facets = triangle.sides
a, b = hyperplane_parameters(triangle)[0]
x0 = facets[0].points[0]
monomial_values = [[0, 0, 0, 0], [1, 0, 0, 5],\
[y, 0, 1, 15], [x, 1, 0, None]]
assert integration_reduction_dynamic(facets, 0, a, b, x, 1, (x, y), 1,\
0, 1, x0, monomial_values, 3) == Rational(25, 2)
assert integration_reduction_dynamic(facets, 0, a, b, 0, 1, (x, y), 1,\
0, 1, x0, monomial_values, 3) == 0
def test_is_vertex():
assert is_vertex(2) is False
assert is_vertex((2, 3)) is True
assert is_vertex(Point(2, 3)) is True
assert is_vertex((2, 3, 4)) is True
assert is_vertex((2, 3, 4, 5)) is False
def test_issue_19234():
polygon = Polygon(Point(0, 0), Point(0, 1), Point(1, 1), Point(1, 0))
polys = [ 1, x, y, x*y, x**2*y, x*y**2]
assert polytope_integrate(polygon, polys) == \
{1: 1, x: S.Half, y: S.Half, x*y: Rational(1, 4), x**2*y: Rational(1, 6), x*y**2: Rational(1, 6)}
polys = [ 1, x, y, x*y, 3 + x**2*y, x + x*y**2]
assert polytope_integrate(polygon, polys) == \
{1: 1, x: S.Half, y: S.Half, x*y: Rational(1, 4), x**2*y + 3: Rational(19, 6), x*y**2 + x: Rational(2, 3)}

View File

@ -0,0 +1,769 @@
from sympy.integrals.laplace import (
laplace_transform, inverse_laplace_transform,
LaplaceTransform, InverseLaplaceTransform,
_laplace_deep_collect, laplace_correspondence,
laplace_initial_conds)
from sympy.core.function import Function, expand_mul
from sympy.core import EulerGamma, Subs, Derivative, diff
from sympy.core.exprtools import factor_terms
from sympy.core.numbers import I, oo, pi
from sympy.core.relational import Eq
from sympy.core.singleton import S
from sympy.core.symbol import Symbol, symbols
from sympy.simplify.simplify import simplify
from sympy.functions.elementary.complexes import Abs, re
from sympy.functions.elementary.exponential import exp, log, exp_polar
from sympy.functions.elementary.hyperbolic import cosh, sinh, coth, asinh
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.functions.elementary.piecewise import Piecewise
from sympy.functions.elementary.trigonometric import atan, cos, sin
from sympy.logic.boolalg import And
from sympy.functions.special.gamma_functions import (
lowergamma, gamma, uppergamma)
from sympy.functions.special.delta_functions import DiracDelta, Heaviside
from sympy.functions.special.singularity_functions import SingularityFunction
from sympy.functions.special.zeta_functions import lerchphi
from sympy.functions.special.error_functions import (
fresnelc, fresnels, erf, erfc, Ei, Ci, expint, E1)
from sympy.functions.special.bessel import besseli, besselj, besselk, bessely
from sympy.testing.pytest import slow, warns_deprecated_sympy
from sympy.matrices import Matrix, eye
from sympy.abc import s
@slow
def test_laplace_transform():
LT = laplace_transform
ILT = inverse_laplace_transform
a, b, c = symbols('a, b, c', positive=True)
np = symbols('np', integer=True, positive=True)
t, w, x = symbols('t, w, x')
f = Function('f')
F = Function('F')
g = Function('g')
y = Function('y')
Y = Function('Y')
# Test helper functions
assert (
_laplace_deep_collect(exp((t+a)*(t+b)) +
besselj(2, exp((t+a)*(t+b)-t**2)), t) ==
exp(a*b + t**2 + t*(a + b)) + besselj(2, exp(a*b + t*(a + b))))
L = laplace_transform(diff(y(t), t, 3), t, s, noconds=True)
L = laplace_correspondence(L, {y: Y})
L = laplace_initial_conds(L, t, {y: [2, 4, 8, 16, 32]})
assert L == s**3*Y(s) - 2*s**2 - 4*s - 8
# Test whether `noconds=True` in `doit`:
assert (2*LaplaceTransform(exp(t), t, s) - 1).doit() == -1 + 2/(s - 1)
assert (LT(a*t+t**2+t**(S(5)/2), t, s) ==
(a/s**2 + 2/s**3 + 15*sqrt(pi)/(8*s**(S(7)/2)), 0, True))
assert LT(b/(t+a), t, s) == (-b*exp(-a*s)*Ei(-a*s), 0, True)
assert (LT(1/sqrt(t+a), t, s) ==
(sqrt(pi)*sqrt(1/s)*exp(a*s)*erfc(sqrt(a)*sqrt(s)), 0, True))
assert (LT(sqrt(t)/(t+a), t, s) ==
(-pi*sqrt(a)*exp(a*s)*erfc(sqrt(a)*sqrt(s)) + sqrt(pi)*sqrt(1/s),
0, True))
assert (LT((t+a)**(-S(3)/2), t, s) ==
(-2*sqrt(pi)*sqrt(s)*exp(a*s)*erfc(sqrt(a)*sqrt(s)) + 2/sqrt(a),
0, True))
assert (LT(t**(S(1)/2)*(t+a)**(-1), t, s) ==
(-pi*sqrt(a)*exp(a*s)*erfc(sqrt(a)*sqrt(s)) + sqrt(pi)*sqrt(1/s),
0, True))
assert (LT(1/(a*sqrt(t) + t**(3/2)), t, s) ==
(pi*sqrt(a)*exp(a*s)*erfc(sqrt(a)*sqrt(s)), 0, True))
assert (LT((t+a)**b, t, s) ==
(s**(-b - 1)*exp(-a*s)*uppergamma(b + 1, a*s), 0, True))
assert LT(t**5/(t+a), t, s) == (120*a**5*uppergamma(-5, a*s), 0, True)
assert LT(exp(t), t, s) == (1/(s - 1), 1, True)
assert LT(exp(2*t), t, s) == (1/(s - 2), 2, True)
assert LT(exp(a*t), t, s) == (1/(s - a), a, True)
assert LT(exp(a*(t-b)), t, s) == (exp(-a*b)/(-a + s), a, True)
assert LT(t*exp(-a*(t)), t, s) == ((a + s)**(-2), -a, True)
assert LT(t*exp(-a*(t-b)), t, s) == (exp(a*b)/(a + s)**2, -a, True)
assert LT(b*t*exp(-a*t), t, s) == (b/(a + s)**2, -a, True)
assert LT(exp(-a*exp(-t)), t, s) == (lowergamma(s, a)/a**s, 0, True)
assert LT(exp(-a*exp(t)), t, s) == (a**s*uppergamma(-s, a), 0, True)
assert (LT(t**(S(7)/4)*exp(-8*t)/gamma(S(11)/4), t, s) ==
((s + 8)**(-S(11)/4), -8, True))
assert (LT(t**(S(3)/2)*exp(-8*t), t, s) ==
(3*sqrt(pi)/(4*(s + 8)**(S(5)/2)), -8, True))
assert LT(t**a*exp(-a*t), t, s) == ((a+s)**(-a-1)*gamma(a+1), -a, True)
assert (LT(b*exp(-a*t**2), t, s) ==
(sqrt(pi)*b*exp(s**2/(4*a))*erfc(s/(2*sqrt(a)))/(2*sqrt(a)),
0, True))
assert (LT(exp(-2*t**2), t, s) ==
(sqrt(2)*sqrt(pi)*exp(s**2/8)*erfc(sqrt(2)*s/4)/4, 0, True))
assert (LT(b*exp(2*t**2), t, s) ==
(b*LaplaceTransform(exp(2*t**2), t, s), -oo, True))
assert (LT(t*exp(-a*t**2), t, s) ==
(1/(2*a) - s*erfc(s/(2*sqrt(a)))/(4*sqrt(pi)*a**(S(3)/2)),
0, True))
assert (LT(exp(-a/t), t, s) ==
(2*sqrt(a)*sqrt(1/s)*besselk(1, 2*sqrt(a)*sqrt(s)), 0, True))
assert LT(sqrt(t)*exp(-a/t), t, s, simplify=True) == (
sqrt(pi)*(sqrt(a)*sqrt(s) + 1/S(2))*sqrt(s**(-3)) *
exp(-2*sqrt(a)*sqrt(s)), 0, True)
assert (LT(exp(-a/t)/sqrt(t), t, s) ==
(sqrt(pi)*sqrt(1/s)*exp(-2*sqrt(a)*sqrt(s)), 0, True))
assert (LT(exp(-a/t)/(t*sqrt(t)), t, s) ==
(sqrt(pi)*sqrt(1/a)*exp(-2*sqrt(a)*sqrt(s)), 0, True))
assert (
LT(exp(-2*sqrt(a*t)), t, s) ==
(1/s - sqrt(pi)*sqrt(a) * exp(a/s)*erfc(sqrt(a)*sqrt(1/s)) /
s**(S(3)/2), 0, True))
assert LT(exp(-2*sqrt(a*t))/sqrt(t), t, s) == (
exp(a/s)*erfc(sqrt(a) * sqrt(1/s))*(sqrt(pi)*sqrt(1/s)), 0, True)
assert (LT(t**4*exp(-2/t), t, s) ==
(8*sqrt(2)*(1/s)**(S(5)/2)*besselk(5, 2*sqrt(2)*sqrt(s)),
0, True))
assert LT(sinh(a*t), t, s) == (a/(-a**2 + s**2), a, True)
assert (LT(b*sinh(a*t)**2, t, s) ==
(2*a**2*b/(-4*a**2*s + s**3), 2*a, True))
assert (LT(b*sinh(a*t)**2, t, s, simplify=True) ==
(2*a**2*b/(s*(-4*a**2 + s**2)), 2*a, True))
# The following line confirms that issue #21202 is solved
assert LT(cosh(2*t), t, s) == (s/(-4 + s**2), 2, True)
assert LT(cosh(a*t), t, s) == (s/(-a**2 + s**2), a, True)
assert (LT(cosh(a*t)**2, t, s, simplify=True) ==
((2*a**2 - s**2)/(s*(4*a**2 - s**2)), 2*a, True))
assert (LT(sinh(x+3), x, s, simplify=True) ==
((s*sinh(3) + cosh(3))/(s**2 - 1), 1, True))
L, _, _ = LT(42*sin(w*t+x)**2, t, s)
assert (
L -
21*(s**2 + s*(-s*cos(2*x) + 2*w*sin(2*x)) +
4*w**2)/(s*(s**2 + 4*w**2))).simplify() == 0
# The following line replaces the old test test_issue_7173()
assert LT(sinh(a*t)*cosh(a*t), t, s, simplify=True) == (a/(-4*a**2 + s**2),
2*a, True)
assert LT(sinh(a*t)/t, t, s) == (log((a + s)/(-a + s))/2, a, True)
assert (LT(t**(-S(3)/2)*sinh(a*t), t, s) ==
(-sqrt(pi)*(sqrt(-a + s) - sqrt(a + s)), a, True))
assert (LT(sinh(2*sqrt(a*t)), t, s) ==
(sqrt(pi)*sqrt(a)*exp(a/s)/s**(S(3)/2), 0, True))
assert (LT(sqrt(t)*sinh(2*sqrt(a*t)), t, s, simplify=True) ==
((-sqrt(a)*s**(S(5)/2) + sqrt(pi)*s**2*(2*a + s)*exp(a/s) *
erf(sqrt(a)*sqrt(1/s))/2)/s**(S(9)/2), 0, True))
assert (LT(sinh(2*sqrt(a*t))/sqrt(t), t, s) ==
(sqrt(pi)*exp(a/s)*erf(sqrt(a)*sqrt(1/s))/sqrt(s), 0, True))
assert (LT(sinh(sqrt(a*t))**2/sqrt(t), t, s) ==
(sqrt(pi)*(exp(a/s) - 1)/(2*sqrt(s)), 0, True))
assert (LT(t**(S(3)/7)*cosh(a*t), t, s) ==
(((a + s)**(-S(10)/7) + (-a+s)**(-S(10)/7))*gamma(S(10)/7)/2,
a, True))
assert (LT(cosh(2*sqrt(a*t)), t, s) ==
(sqrt(pi)*sqrt(a)*exp(a/s)*erf(sqrt(a)*sqrt(1/s))/s**(S(3)/2) +
1/s, 0, True))
assert (LT(sqrt(t)*cosh(2*sqrt(a*t)), t, s) ==
(sqrt(pi)*(a + s/2)*exp(a/s)/s**(S(5)/2), 0, True))
assert (LT(cosh(2*sqrt(a*t))/sqrt(t), t, s) ==
(sqrt(pi)*exp(a/s)/sqrt(s), 0, True))
assert (LT(cosh(sqrt(a*t))**2/sqrt(t), t, s) ==
(sqrt(pi)*(exp(a/s) + 1)/(2*sqrt(s)), 0, True))
assert LT(log(t), t, s, simplify=True) == (
(-log(s) - EulerGamma)/s, 0, True)
assert (LT(-log(t/a), t, s, simplify=True) ==
((log(a) + log(s) + EulerGamma)/s, 0, True))
assert LT(log(1+a*t), t, s) == (-exp(s/a)*Ei(-s/a)/s, 0, True)
assert (LT(log(t+a), t, s, simplify=True) ==
((s*log(a) - exp(s/a)*Ei(-s/a))/s**2, 0, True))
assert (LT(log(t)/sqrt(t), t, s, simplify=True) ==
(sqrt(pi)*(-log(s) - log(4) - EulerGamma)/sqrt(s), 0, True))
assert (LT(t**(S(5)/2)*log(t), t, s, simplify=True) ==
(sqrt(pi)*(-15*log(s) - log(1073741824) - 15*EulerGamma + 46) /
(8*s**(S(7)/2)), 0, True))
assert (LT(t**3*log(t), t, s, noconds=True, simplify=True) -
6*(-log(s) - S.EulerGamma + S(11)/6)/s**4).simplify() == S.Zero
assert (LT(log(t)**2, t, s, simplify=True) ==
(((log(s) + EulerGamma)**2 + pi**2/6)/s, 0, True))
assert (LT(exp(-a*t)*log(t), t, s, simplify=True) ==
((-log(a + s) - EulerGamma)/(a + s), -a, True))
assert LT(sin(a*t), t, s) == (a/(a**2 + s**2), 0, True)
assert (LT(Abs(sin(a*t)), t, s) ==
(a*coth(pi*s/(2*a))/(a**2 + s**2), 0, True))
assert LT(sin(a*t)/t, t, s) == (atan(a/s), 0, True)
assert LT(sin(a*t)**2/t, t, s) == (log(4*a**2/s**2 + 1)/4, 0, True)
assert (LT(sin(a*t)**2/t**2, t, s) ==
(a*atan(2*a/s) - s*log(4*a**2/s**2 + 1)/4, 0, True))
assert (LT(sin(2*sqrt(a*t)), t, s) ==
(sqrt(pi)*sqrt(a)*exp(-a/s)/s**(S(3)/2), 0, True))
assert LT(sin(2*sqrt(a*t))/t, t, s) == (pi*erf(sqrt(a)*sqrt(1/s)), 0, True)
assert LT(cos(a*t), t, s) == (s/(a**2 + s**2), 0, True)
assert (LT(cos(a*t)**2, t, s) ==
((2*a**2 + s**2)/(s*(4*a**2 + s**2)), 0, True))
assert (LT(sqrt(t)*cos(2*sqrt(a*t)), t, s, simplify=True) ==
(sqrt(pi)*(-a + s/2)*exp(-a/s)/s**(S(5)/2), 0, True))
assert (LT(cos(2*sqrt(a*t))/sqrt(t), t, s) ==
(sqrt(pi)*sqrt(1/s)*exp(-a/s), 0, True))
assert (LT(sin(a*t)*sin(b*t), t, s) ==
(2*a*b*s/((s**2 + (a - b)**2)*(s**2 + (a + b)**2)), 0, True))
assert (LT(cos(a*t)*sin(b*t), t, s) ==
(b*(-a**2 + b**2 + s**2)/((s**2 + (a - b)**2)*(s**2 + (a + b)**2)),
0, True))
assert (LT(cos(a*t)*cos(b*t), t, s) ==
(s*(a**2 + b**2 + s**2)/((s**2 + (a - b)**2)*(s**2 + (a + b)**2)),
0, True))
assert (LT(-a*t*cos(a*t) + sin(a*t), t, s, simplify=True) ==
(2*a**3/(a**4 + 2*a**2*s**2 + s**4), 0, True))
assert LT(c*exp(-b*t)*sin(a*t), t, s) == (a *
c/(a**2 + (b + s)**2), -b, True)
assert LT(c*exp(-b*t)*cos(a*t), t, s) == (c*(b + s)/(a**2 + (b + s)**2),
-b, True)
L, plane, cond = LT(cos(x + 3), x, s, simplify=True)
assert plane == 0
assert L - (s*cos(3) - sin(3))/(s**2 + 1) == 0
# Error functions (laplace7.pdf)
assert LT(erf(a*t), t, s) == (exp(s**2/(4*a**2))*erfc(s/(2*a))/s, 0, True)
assert LT(erf(sqrt(a*t)), t, s) == (sqrt(a)/(s*sqrt(a + s)), 0, True)
assert (LT(exp(a*t)*erf(sqrt(a*t)), t, s, simplify=True) ==
(-sqrt(a)/(sqrt(s)*(a - s)), a, True))
assert (LT(erf(sqrt(a/t)/2), t, s, simplify=True) ==
(1/s - exp(-sqrt(a)*sqrt(s))/s, 0, True))
assert (LT(erfc(sqrt(a*t)), t, s, simplify=True) ==
(-sqrt(a)/(s*sqrt(a + s)) + 1/s, -a, True))
assert (LT(exp(a*t)*erfc(sqrt(a*t)), t, s) ==
(1/(sqrt(a)*sqrt(s) + s), 0, True))
assert LT(erfc(sqrt(a/t)/2), t, s) == (exp(-sqrt(a)*sqrt(s))/s, 0, True)
# Bessel functions (laplace8.pdf)
assert LT(besselj(0, a*t), t, s) == (1/sqrt(a**2 + s**2), 0, True)
assert (LT(besselj(1, a*t), t, s, simplify=True) ==
(a/(a**2 + s**2 + s*sqrt(a**2 + s**2)), 0, True))
assert (LT(besselj(2, a*t), t, s, simplify=True) ==
(a**2/(sqrt(a**2 + s**2)*(s + sqrt(a**2 + s**2))**2), 0, True))
assert (LT(t*besselj(0, a*t), t, s) ==
(s/(a**2 + s**2)**(S(3)/2), 0, True))
assert (LT(t*besselj(1, a*t), t, s) ==
(a/(a**2 + s**2)**(S(3)/2), 0, True))
assert (LT(t**2*besselj(2, a*t), t, s) ==
(3*a**2/(a**2 + s**2)**(S(5)/2), 0, True))
assert LT(besselj(0, 2*sqrt(a*t)), t, s) == (exp(-a/s)/s, 0, True)
assert (LT(t**(S(3)/2)*besselj(3, 2*sqrt(a*t)), t, s) ==
(a**(S(3)/2)*exp(-a/s)/s**4, 0, True))
assert (LT(besselj(0, a*sqrt(t**2+b*t)), t, s, simplify=True) ==
(exp(b*(s - sqrt(a**2 + s**2)))/sqrt(a**2 + s**2), 0, True))
assert LT(besseli(0, a*t), t, s) == (1/sqrt(-a**2 + s**2), a, True)
assert (LT(besseli(1, a*t), t, s, simplify=True) ==
(a/(-a**2 + s**2 + s*sqrt(-a**2 + s**2)), a, True))
assert (LT(besseli(2, a*t), t, s, simplify=True) ==
(a**2/(sqrt(-a**2 + s**2)*(s + sqrt(-a**2 + s**2))**2), a, True))
assert LT(t*besseli(0, a*t), t, s) == (s/(-a**2 + s**2)**(S(3)/2), a, True)
assert LT(t*besseli(1, a*t), t, s) == (a/(-a**2 + s**2)**(S(3)/2), a, True)
assert (LT(t**2*besseli(2, a*t), t, s) ==
(3*a**2/(-a**2 + s**2)**(S(5)/2), a, True))
assert (LT(t**(S(3)/2)*besseli(3, 2*sqrt(a*t)), t, s) ==
(a**(S(3)/2)*exp(a/s)/s**4, 0, True))
assert (LT(bessely(0, a*t), t, s) ==
(-2*asinh(s/a)/(pi*sqrt(a**2 + s**2)), 0, True))
assert (LT(besselk(0, a*t), t, s) ==
(log((s + sqrt(-a**2 + s**2))/a)/sqrt(-a**2 + s**2), -a, True))
assert (LT(sin(a*t)**4, t, s, simplify=True) ==
(24*a**4/(s*(64*a**4 + 20*a**2*s**2 + s**4)), 0, True))
# Test general rules and unevaluated forms
# These all also test whether issue #7219 is solved.
assert LT(Heaviside(t-1)*cos(t-1), t, s) == (s*exp(-s)/(s**2 + 1), 0, True)
assert LT(a*f(t), t, w) == (a*LaplaceTransform(f(t), t, w), -oo, True)
assert (LT(a*Heaviside(t+1)*f(t+1), t, s) ==
(a*LaplaceTransform(f(t + 1), t, s), -oo, True))
assert (LT(a*Heaviside(t-1)*f(t-1), t, s) ==
(a*LaplaceTransform(f(t), t, s)*exp(-s), -oo, True))
assert (LT(b*f(t/a), t, s) ==
(a*b*LaplaceTransform(f(t), t, a*s), -oo, True))
assert LT(exp(-f(x)*t), t, s) == (1/(s + f(x)), -re(f(x)), True)
assert (LT(exp(-a*t)*f(t), t, s) ==
(LaplaceTransform(f(t), t, a + s), -oo, True))
assert (LT(exp(-a*t)*erfc(sqrt(b/t)/2), t, s) ==
(exp(-sqrt(b)*sqrt(a + s))/(a + s), -a, True))
assert (LT(sinh(a*t)*f(t), t, s) ==
(LaplaceTransform(f(t), t, -a + s)/2 -
LaplaceTransform(f(t), t, a + s)/2, -oo, True))
assert (LT(sinh(a*t)*t, t, s, simplify=True) ==
(2*a*s/(a**4 - 2*a**2*s**2 + s**4), a, True))
assert (LT(cosh(a*t)*f(t), t, s) ==
(LaplaceTransform(f(t), t, -a + s)/2 +
LaplaceTransform(f(t), t, a + s)/2, -oo, True))
assert (LT(cosh(a*t)*t, t, s, simplify=True) ==
(1/(2*(a + s)**2) + 1/(2*(a - s)**2), a, True))
assert (LT(sin(a*t)*f(t), t, s, simplify=True) ==
(I*(-LaplaceTransform(f(t), t, -I*a + s) +
LaplaceTransform(f(t), t, I*a + s))/2, -oo, True))
assert (LT(sin(f(t)), t, s) ==
(LaplaceTransform(sin(f(t)), t, s), -oo, True))
assert (LT(sin(a*t)*t, t, s, simplify=True) ==
(2*a*s/(a**4 + 2*a**2*s**2 + s**4), 0, True))
assert (LT(cos(a*t)*f(t), t, s) ==
(LaplaceTransform(f(t), t, -I*a + s)/2 +
LaplaceTransform(f(t), t, I*a + s)/2, -oo, True))
assert (LT(cos(a*t)*t, t, s, simplify=True) ==
((-a**2 + s**2)/(a**4 + 2*a**2*s**2 + s**4), 0, True))
L, plane, _ = LT(sin(a*t+b)**2*f(t), t, s)
assert plane == -oo
assert (
-L + (
LaplaceTransform(f(t), t, s)/2 -
LaplaceTransform(f(t), t, -2*I*a + s)*exp(2*I*b)/4 -
LaplaceTransform(f(t), t, 2*I*a + s)*exp(-2*I*b)/4)) == 0
L = LT(sin(a*t+b)**2*f(t), t, s, noconds=True)
assert (
laplace_correspondence(L, {f: F}) ==
F(s)/2 - F(-2*I*a + s)*exp(2*I*b)/4 -
F(2*I*a + s)*exp(-2*I*b)/4)
L, plane, _ = LT(sin(a*t)**3*cosh(b*t), t, s)
assert plane == b
assert (
-L - 3*a/(8*(9*a**2 + b**2 + 2*b*s + s**2)) -
3*a/(8*(9*a**2 + b**2 - 2*b*s + s**2)) +
3*a/(8*(a**2 + b**2 + 2*b*s + s**2)) +
3*a/(8*(a**2 + b**2 - 2*b*s + s**2))).simplify() == 0
assert (LT(t**2*exp(-t**2), t, s) ==
(sqrt(pi)*s**2*exp(s**2/4)*erfc(s/2)/8 - s/4 +
sqrt(pi)*exp(s**2/4)*erfc(s/2)/4, 0, True))
assert (LT((a*t**2 + b*t + c)*f(t), t, s) ==
(a*Derivative(LaplaceTransform(f(t), t, s), (s, 2)) -
b*Derivative(LaplaceTransform(f(t), t, s), s) +
c*LaplaceTransform(f(t), t, s), -oo, True))
assert (LT(t**np*g(t), t, s) ==
((-1)**np*Derivative(LaplaceTransform(g(t), t, s), (s, np)),
-oo, True))
# The following tests check whether _piecewise_to_heaviside works:
x1 = Piecewise((0, t <= 0), (1, t <= 1), (0, True))
X1 = LT(x1, t, s)[0]
assert X1 == 1/s - exp(-s)/s
y1 = ILT(X1, s, t)
assert y1 == Heaviside(t) - Heaviside(t - 1)
x1 = Piecewise((0, t <= 0), (t, t <= 1), (2-t, t <= 2), (0, True))
X1 = LT(x1, t, s)[0].simplify()
assert X1 == (exp(2*s) - 2*exp(s) + 1)*exp(-2*s)/s**2
y1 = ILT(X1, s, t)
assert (
-y1 + t*Heaviside(t) + (t - 2)*Heaviside(t - 2) -
2*(t - 1)*Heaviside(t - 1)).simplify() == 0
x1 = Piecewise((exp(t), t <= 0), (1, t <= 1), (exp(-(t)), True))
X1 = LT(x1, t, s)[0]
assert X1 == exp(-1)*exp(-s)/(s + 1) + 1/s - exp(-s)/s
y1 = ILT(X1, s, t)
assert y1 == (
exp(-1)*exp(1 - t)*Heaviside(t - 1) + Heaviside(t) - Heaviside(t - 1))
x1 = Piecewise((0, x <= 0), (1, x <= 1), (0, True))
X1 = LT(x1, t, s)[0]
assert X1 == Piecewise((0, x <= 0), (1, x <= 1), (0, True))/s
x1 = [
a*Piecewise((1, And(t > 1, t <= 3)), (2, True)),
a*Piecewise((1, And(t >= 1, t <= 3)), (2, True)),
a*Piecewise((1, And(t >= 1, t < 3)), (2, True)),
a*Piecewise((1, And(t > 1, t < 3)), (2, True))]
for x2 in x1:
assert LT(x2, t, s)[0].expand() == 2*a/s - a*exp(-s)/s + a*exp(-3*s)/s
assert (
LT(Piecewise((1, Eq(t, 1)), (2, True)), t, s)[0] ==
LaplaceTransform(Piecewise((1, Eq(t, 1)), (2, True)), t, s))
# The following lines test whether _laplace_transform successfully
# removes Heaviside(1) before processing espressions. It fails if
# Heaviside(t) remains because then meijerg functions will appear.
X1 = 1/sqrt(a*s**2-b)
x1 = ILT(X1, s, t)
Y1 = LT(x1, t, s)[0]
Z1 = (Y1**2/X1**2).simplify()
assert Z1 == 1
# The following two lines test whether issues #5813 and #7176 are solved.
assert (LT(diff(f(t), (t, 1)), t, s, noconds=True) ==
s*LaplaceTransform(f(t), t, s) - f(0))
assert (LT(diff(f(t), (t, 3)), t, s, noconds=True) ==
s**3*LaplaceTransform(f(t), t, s) - s**2*f(0) -
s*Subs(Derivative(f(t), t), t, 0) -
Subs(Derivative(f(t), (t, 2)), t, 0))
# Issue #7219
assert (LT(diff(f(x, t, w), t, 2), t, s) ==
(s**2*LaplaceTransform(f(x, t, w), t, s) - s*f(x, 0, w) -
Subs(Derivative(f(x, t, w), t), t, 0), -oo, True))
# Issue #23307
assert (LT(10*diff(f(t), (t, 1)), t, s, noconds=True) ==
10*s*LaplaceTransform(f(t), t, s) - 10*f(0))
assert (LT(a*f(b*t)+g(c*t), t, s, noconds=True) ==
a*LaplaceTransform(f(t), t, s/b)/b +
LaplaceTransform(g(t), t, s/c)/c)
assert inverse_laplace_transform(
f(w), w, t, plane=0) == InverseLaplaceTransform(f(w), w, t, 0)
assert (LT(f(t)*g(t), t, s, noconds=True) ==
LaplaceTransform(f(t)*g(t), t, s))
# Issue #24294
assert (LT(b*f(a*t), t, s, noconds=True) ==
b*LaplaceTransform(f(t), t, s/a)/a)
assert LT(3*exp(t)*Heaviside(t), t, s) == (3/(s - 1), 1, True)
assert (LT(2*sin(t)*Heaviside(t), t, s, simplify=True) ==
(2/(s**2 + 1), 0, True))
# Issue #25293
assert (
LT((1/(t-1))*sin(4*pi*(t-1))*DiracDelta(t-1) *
(Heaviside(t-1/4) - Heaviside(t-2)), t, s)[0] == 4*pi*exp(-s))
# additional basic tests from wikipedia
assert (LT((t - a)**b*exp(-c*(t - a))*Heaviside(t - a), t, s) ==
((c + s)**(-b - 1)*exp(-a*s)*gamma(b + 1), -c, True))
assert (
LT((exp(2*t)-1)*exp(-b-t)*Heaviside(t)/2, t, s, noconds=True,
simplify=True) ==
exp(-b)/(s**2 - 1))
# DiracDelta function: standard cases
assert LT(DiracDelta(t), t, s) == (1, -oo, True)
assert LT(DiracDelta(a*t), t, s) == (1/a, -oo, True)
assert LT(DiracDelta(t/42), t, s) == (42, -oo, True)
assert LT(DiracDelta(t+42), t, s) == (0, -oo, True)
assert (LT(DiracDelta(t)+DiracDelta(t-42), t, s) ==
(1 + exp(-42*s), -oo, True))
assert (LT(DiracDelta(t)-a*exp(-a*t), t, s, simplify=True) ==
(s/(a + s), -a, True))
assert (
LT(exp(-t)*(DiracDelta(t)+DiracDelta(t-42)), t, s, simplify=True) ==
(exp(-42*s - 42) + 1, -oo, True))
assert LT(f(t)*DiracDelta(t-42), t, s) == (f(42)*exp(-42*s), -oo, True)
assert LT(f(t)*DiracDelta(b*t-a), t, s) == (f(a/b)*exp(-a*s/b)/b,
-oo, True)
assert LT(f(t)*DiracDelta(b*t+a), t, s) == (0, -oo, True)
# SingularityFunction
assert LT(SingularityFunction(t, a, -1), t, s)[0] == exp(-a*s)
assert LT(SingularityFunction(t, a, 1), t, s)[0] == exp(-a*s)/s**2
assert LT(SingularityFunction(t, a, x), t, s)[0] == (
LaplaceTransform(SingularityFunction(t, a, x), t, s))
# Collection of cases that cannot be fully evaluated and/or would catch
# some common implementation errors
assert (LT(DiracDelta(t**2), t, s, noconds=True) ==
LaplaceTransform(DiracDelta(t**2), t, s))
assert LT(DiracDelta(t**2 - 1), t, s) == (exp(-s)/2, -oo, True)
assert LT(DiracDelta(t*(1 - t)), t, s) == (1 - exp(-s), -oo, True)
assert (LT((DiracDelta(t) + 1)*(DiracDelta(t - 1) + 1), t, s) ==
(LaplaceTransform(DiracDelta(t)*DiracDelta(t - 1), t, s) +
1 + exp(-s) + 1/s, 0, True))
assert LT(DiracDelta(2*t-2*exp(a)), t, s) == (exp(-s*exp(a))/2, -oo, True)
assert LT(DiracDelta(-2*t+2*exp(a)), t, s) == (exp(-s*exp(a))/2, -oo, True)
# Heaviside tests
assert LT(Heaviside(t), t, s) == (1/s, 0, True)
assert LT(Heaviside(t - a), t, s) == (exp(-a*s)/s, 0, True)
assert LT(Heaviside(t-1), t, s) == (exp(-s)/s, 0, True)
assert LT(Heaviside(2*t-4), t, s) == (exp(-2*s)/s, 0, True)
assert LT(Heaviside(2*t+4), t, s) == (1/s, 0, True)
assert (LT(Heaviside(-2*t+4), t, s, simplify=True) ==
(1/s - exp(-2*s)/s, 0, True))
assert (LT(g(t)*Heaviside(t - w), t, s) ==
(LaplaceTransform(g(t)*Heaviside(t - w), t, s), -oo, True))
assert (
LT(Heaviside(t-a)*g(t), t, s) ==
(LaplaceTransform(g(a + t), t, s)*exp(-a*s), -oo, True))
assert (
LT(Heaviside(t+a)*g(t), t, s) ==
(LaplaceTransform(g(t), t, s), -oo, True))
assert (
LT(Heaviside(-t+a)*g(t), t, s) ==
(LaplaceTransform(g(t), t, s) -
LaplaceTransform(g(a + t), t, s)*exp(-a*s), -oo, True))
assert (
LT(Heaviside(-t-a)*g(t), t, s) == (0, 0, True))
# Fresnel functions
assert (laplace_transform(fresnels(t), t, s, simplify=True) ==
((-sin(s**2/(2*pi))*fresnels(s/pi) +
sqrt(2)*sin(s**2/(2*pi) + pi/4)/2 -
cos(s**2/(2*pi))*fresnelc(s/pi))/s, 0, True))
assert (laplace_transform(fresnelc(t), t, s, simplify=True) ==
((sin(s**2/(2*pi))*fresnelc(s/pi) -
cos(s**2/(2*pi))*fresnels(s/pi) +
sqrt(2)*cos(s**2/(2*pi) + pi/4)/2)/s, 0, True))
# Matrix tests
Mt = Matrix([[exp(t), t*exp(-t)], [t*exp(-t), exp(t)]])
Ms = Matrix([[1/(s - 1), (s + 1)**(-2)],
[(s + 1)**(-2), 1/(s - 1)]])
# The default behaviour for Laplace transform of a Matrix returns a Matrix
# of Tuples and is deprecated:
with warns_deprecated_sympy():
Ms_conds = Matrix(
[[(1/(s - 1), 1, True), ((s + 1)**(-2), -1, True)],
[((s + 1)**(-2), -1, True), (1/(s - 1), 1, True)]])
with warns_deprecated_sympy():
assert LT(Mt, t, s) == Ms_conds
# The new behavior is to return a tuple of a Matrix and the convergence
# conditions for the matrix as a whole:
assert LT(Mt, t, s, legacy_matrix=False) == (Ms, 1, True)
# With noconds=True the transformed matrix is returned without conditions
# either way:
assert LT(Mt, t, s, noconds=True) == Ms
assert LT(Mt, t, s, legacy_matrix=False, noconds=True) == Ms
@slow
def test_inverse_laplace_transform():
s = symbols('s')
k, n, t = symbols('k, n, t', real=True)
a, b, c, d = symbols('a, b, c, d', positive=True)
f = Function('f')
F = Function('F')
def ILT(g):
return inverse_laplace_transform(g, s, t)
def ILTS(g):
return inverse_laplace_transform(g, s, t, simplify=True)
def ILTF(g):
return laplace_correspondence(
inverse_laplace_transform(g, s, t), {f: F})
# Tests for the rules in Bateman54.
# Section 4.1: Some of the Laplace transform rules can also be used well
# in the inverse transform.
assert ILTF(exp(-a*s)*F(s)) == f(-a + t)
assert ILTF(k*F(s-a)) == k*f(t)*exp(-a*t)
assert ILTF(diff(F(s), s, 3)) == -t**3*f(t)
assert ILTF(diff(F(s), s, 4)) == t**4*f(t)
# Section 5.1: Most rules are impractical for a computer algebra system.
# Section 5.2: Rational functions
assert ILT(2) == 2*DiracDelta(t)
assert ILT(1/s) == Heaviside(t)
assert ILT(1/s**2) == t*Heaviside(t)
assert ILT(1/s**5) == t**4*Heaviside(t)/24
assert ILT(1/s**n) == t**(n - 1)*Heaviside(t)/gamma(n)
assert ILT(a/(a + s)) == a*exp(-a*t)*Heaviside(t)
assert ILT(s/(a + s)) == -a*exp(-a*t)*Heaviside(t) + DiracDelta(t)
assert (ILT(b*s/(s+a)**2) ==
b*(-a*t*exp(-a*t)*Heaviside(t) + exp(-a*t)*Heaviside(t)))
assert (ILTS(c/((s+a)*(s+b))) ==
c*(exp(a*t) - exp(b*t))*exp(-t*(a + b))*Heaviside(t)/(a - b))
assert (ILTS(c*s/((s+a)*(s+b))) ==
c*(a*exp(b*t) - b*exp(a*t))*exp(-t*(a + b))*Heaviside(t)/(a - b))
assert ILTS(s/(a + s)**3) == t*(-a*t + 2)*exp(-a*t)*Heaviside(t)/2
assert ILTS(1/(s*(a + s)**3)) == (
-a**2*t**2 - 2*a*t + 2*exp(a*t) - 2)*exp(-a*t)*Heaviside(t)/(2*a**3)
assert ILT(1/(s*(a + s)**n)) == (
Heaviside(t)*lowergamma(n, a*t)/(a**n*gamma(n)))
assert ILT((s-a)**(-b)) == t**(b - 1)*exp(a*t)*Heaviside(t)/gamma(b)
assert ILT((a + s)**(-2)) == t*exp(-a*t)*Heaviside(t)
assert ILT((a + s)**(-5)) == t**4*exp(-a*t)*Heaviside(t)/24
assert ILT(s**2/(s**2 + 1)) == -sin(t)*Heaviside(t) + DiracDelta(t)
assert ILT(1 - 1/(s**2 + 1)) == -sin(t)*Heaviside(t) + DiracDelta(t)
assert ILT(a/(a**2 + s**2)) == sin(a*t)*Heaviside(t)
assert ILT(s/(s**2 + a**2)) == cos(a*t)*Heaviside(t)
assert ILT(b/(b**2 + (a + s)**2)) == exp(-a*t)*sin(b*t)*Heaviside(t)
assert (ILT(b*s/(b**2 + (a + s)**2)) ==
b*(-a*exp(-a*t)*sin(b*t)/b + exp(-a*t)*cos(b*t))*Heaviside(t))
assert ILT(1/(s**2*(s**2 + 1))) == t*Heaviside(t) - sin(t)*Heaviside(t)
assert (ILTS(c*s/(d**2*(s+a)**2+b**2)) ==
c*(-a*d*sin(b*t/d) + b*cos(b*t/d))*exp(-a*t)*Heaviside(t)/(b*d**2))
assert ILTS((b*s**2 + d)/(a**2 + s**2)**2) == (
2*a**2*b*sin(a*t) + (a**2*b - d)*(a*t*cos(a*t) -
sin(a*t)))*Heaviside(t)/(2*a**3)
assert ILTS(b/(s**2-a**2)) == b*sinh(a*t)*Heaviside(t)/a
assert (ILT(b/(s**2-a**2)) ==
b*(exp(a*t)*Heaviside(t)/(2*a) - exp(-a*t)*Heaviside(t)/(2*a)))
assert ILTS(b*s/(s**2-a**2)) == b*cosh(a*t)*Heaviside(t)
assert (ILT(b/(s*(s+a))) ==
b*(Heaviside(t)/a - exp(-a*t)*Heaviside(t)/a))
# Issue #24424
assert (ILTS((s + 8)/((s + 2)*(s**2 + 2*s + 10))) ==
((8*sin(3*t) - 9*cos(3*t))*exp(t) + 9)*exp(-2*t)*Heaviside(t)/15)
# Issue #8514; this is not important anymore, since this function
# is not solved by integration anymore
assert (ILT(1/(a*s**2+b*s+c)) ==
2*exp(-b*t/(2*a))*sin(t*sqrt(4*a*c - b**2)/(2*a)) *
Heaviside(t)/sqrt(4*a*c - b**2))
# Section 5.3: Irrational algebraic functions
assert ( # (1)
ILT(1/sqrt(s)/(b*s-a)) ==
exp(a*t/b)*Heaviside(t)*erf(sqrt(a)*sqrt(t)/sqrt(b))/(sqrt(a)*sqrt(b)))
assert ( # (2)
ILT(1/sqrt(k*s)/(c*s-a)/s) ==
(-2*c*sqrt(t)/(sqrt(pi)*a) +
c**(S(3)/2)*exp(a*t/c)*erf(sqrt(a)*sqrt(t)/sqrt(c))/a**(S(3)/2)) *
Heaviside(t)/(c*sqrt(k)))
assert ( # (4)
ILT(1/(sqrt(c*s)+a)) == (-a*exp(a**2*t/c)*erfc(a*sqrt(t)/sqrt(c))/c +
1/(sqrt(pi)*sqrt(c)*sqrt(t)))*Heaviside(t))
assert ( # (5)
ILT(a/s/(b*sqrt(s)+a)) ==
(-exp(a**2*t/b**2)*erfc(a*sqrt(t)/b) + 1)*Heaviside(t))
assert ( # (6)
ILT((a-b)*sqrt(s)/(sqrt(s)+sqrt(a))/(s-b)) ==
(sqrt(a)*sqrt(b)*exp(b*t)*erfc(sqrt(b)*sqrt(t)) +
a*exp(a*t)*erfc(sqrt(a)*sqrt(t)) - b*exp(b*t))*Heaviside(t))
assert ( # (7)
ILT(1/sqrt(s)/(sqrt(b*s)+a)) ==
exp(a**2*t/b)*Heaviside(t)*erfc(a*sqrt(t)/sqrt(b))/sqrt(b))
assert ( # (8)
ILT(a**2/(sqrt(s)+a)/s**(S(3)/2)) ==
(2*a*sqrt(t)/sqrt(pi) + exp(a**2*t)*erfc(a*sqrt(t)) - 1) *
Heaviside(t))
assert ( # (9)
ILT((a-b)*sqrt(b)/(s-b)/sqrt(s)/(sqrt(s)+sqrt(a))) ==
(sqrt(a)*exp(b*t)*erf(sqrt(b)*sqrt(t)) +
sqrt(b)*exp(a*t)*erfc(sqrt(a)*sqrt(t)) -
sqrt(b)*exp(b*t))*Heaviside(t))
assert ( # (10)
ILT(1/(sqrt(s)+sqrt(a))**2) ==
(-2*sqrt(a)*sqrt(t)/sqrt(pi) +
(-2*a*t + 1)*(erf(sqrt(a)*sqrt(t)) -
1)*exp(a*t) + 1)*Heaviside(t))
assert ( # (11)
ILT(1/(sqrt(s)+sqrt(a))**2/s) ==
((2*t - 1/a)*exp(a*t)*erfc(sqrt(a)*sqrt(t)) + 1/a -
2*sqrt(t)/(sqrt(pi)*sqrt(a)))*Heaviside(t))
assert ( # (12)
ILT(1/(sqrt(s)+a)**2/sqrt(s)) ==
(-2*a*t*exp(a**2*t)*erfc(a*sqrt(t)) +
2*sqrt(t)/sqrt(pi))*Heaviside(t))
assert ( # (13)
ILT(1/(sqrt(s)+a)**3) ==
(-a*t*(2*a**2*t + 3)*exp(a**2*t)*erfc(a*sqrt(t)) +
2*sqrt(t)*(a**2*t + 1)/sqrt(pi))*Heaviside(t))
x = (
- ILT(sqrt(s)/(sqrt(s)+a)**3) +
2*(sqrt(pi)*a**2*t*(-2*sqrt(pi)*erfc(a*sqrt(t)) +
2*exp(-a**2*t)/(a*sqrt(t))) *
(-a**4*t**2 - 5*a**2*t/2 - S.Half) * exp(a**2*t)/2 +
sqrt(pi)*a*sqrt(t)*(a**2*t + 1)/2) *
Heaviside(t)/(pi*a**2*t)).simplify()
assert ( # (14)
x == 0)
x = (
- ILT(1/sqrt(s)/(sqrt(s)+a)**3) +
Heaviside(t)*(sqrt(t)*((2*a**2*t + 1) *
(sqrt(pi)*a*sqrt(t)*exp(a**2*t) *
erfc(a*sqrt(t)) - 1) + 1) /
(sqrt(pi)*a))).simplify()
assert ( # (15)
x == 0)
assert ( # (16)
factor_terms(ILT(3/(sqrt(s)+a)**4)) ==
3*(-2*a**3*t**(S(5)/2)*(2*a**2*t + 5)/(3*sqrt(pi)) +
t*(4*a**4*t**2 + 12*a**2*t + 3)*exp(a**2*t) *
erfc(a*sqrt(t))/3)*Heaviside(t))
assert ( # (17)
ILT((sqrt(s)-a)/(s*(sqrt(s)+a))) ==
(2*exp(a**2*t)*erfc(a*sqrt(t))-1)*Heaviside(t))
assert ( # (18)
ILT((sqrt(s)-a)**2/(s*(sqrt(s)+a)**2)) == (
1 + 8*a**2*t*exp(a**2*t)*erfc(a*sqrt(t)) -
8/sqrt(pi)*a*sqrt(t))*Heaviside(t))
assert ( # (19)
ILT((sqrt(s)-a)**3/(s*(sqrt(s)+a)**3)) == Heaviside(t)*(
2*(8*a**4*t**2+8*a**2*t+1)*exp(a**2*t) *
erfc(a*sqrt(t))-8/sqrt(pi)*a*sqrt(t)*(2*a**2*t+1)-1))
assert ( # (22)
ILT(sqrt(s+a)/(s+b)) == Heaviside(t)*(
exp(-a*t)/sqrt(t)/sqrt(pi) +
sqrt(a-b)*exp(-b*t)*erf(sqrt(a-b)*sqrt(t))))
assert ( # (23)
ILT(1/sqrt(s+b)/(s+a)) == Heaviside(t)*(
1/sqrt(b-a)*exp(-a*t)*erf(sqrt(b-a)*sqrt(t))))
assert ( # (35)
ILT(1/sqrt(s**2+a**2)) == Heaviside(t)*(
besselj(0, a*t)))
assert ( # (44)
ILT(1/sqrt(s**2-a**2)) == Heaviside(t)*(
besseli(0, a*t)))
# Miscellaneous tests
# Can _inverse_laplace_time_shift deal with positive exponents?
assert (
- ILT((s**2*exp(2*s) + 4*exp(s) - 4)*exp(-2*s)/(s*(s**2 + 1))) +
cos(t)*Heaviside(t) + 4*cos(t - 2)*Heaviside(t - 2) -
4*cos(t - 1)*Heaviside(t - 1) - 4*Heaviside(t - 2) +
4*Heaviside(t - 1)).simplify() == 0
@slow
def test_inverse_laplace_transform_old():
from sympy.functions.special.delta_functions import DiracDelta
ILT = inverse_laplace_transform
a, b, c, d = symbols('a b c d', positive=True)
n, r = symbols('n, r', real=True)
t, z = symbols('t z')
f = Function('f')
F = Function('F')
def simp_hyp(expr):
return factor_terms(expand_mul(expr)).rewrite(sin)
L = ILT(F(s), s, t)
assert laplace_correspondence(L, {f: F}) == f(t)
assert ILT(exp(-a*s)/s, s, t) == Heaviside(-a + t)
assert ILT(exp(-a*s)/(b + s), s, t) == exp(-b*(-a + t))*Heaviside(-a + t)
assert (ILT((b + s)/(a**2 + (b + s)**2), s, t) ==
exp(-b*t)*cos(a*t)*Heaviside(t))
assert (ILT(exp(-a*s)/s**b, s, t) ==
(-a + t)**(b - 1)*Heaviside(-a + t)/gamma(b))
assert (ILT(exp(-a*s)/sqrt(s**2 + 1), s, t) ==
Heaviside(-a + t)*besselj(0, a - t))
assert ILT(1/(s*sqrt(s + 1)), s, t) == Heaviside(t)*erf(sqrt(t))
# TODO sinh/cosh shifted come out a mess. also delayed trig is a mess
# TODO should this simplify further?
assert (ILT(exp(-a*s)/s**b, s, t) ==
(t - a)**(b - 1)*Heaviside(t - a)/gamma(b))
assert (ILT(exp(-a*s)/sqrt(1 + s**2), s, t) ==
Heaviside(t - a)*besselj(0, a - t)) # note: besselj(0, x) is even
# XXX ILT turns these branch factor into trig functions ...
assert (
simplify(ILT(a**b*(s + sqrt(s**2 - a**2))**(-b)/sqrt(s**2 - a**2),
s, t).rewrite(exp)) ==
Heaviside(t)*besseli(b, a*t))
assert (
ILT(a**b*(s + sqrt(s**2 + a**2))**(-b)/sqrt(s**2 + a**2),
s, t, simplify=True).rewrite(exp) ==
Heaviside(t)*besselj(b, a*t))
assert ILT(1/(s*sqrt(s + 1)), s, t) == Heaviside(t)*erf(sqrt(t))
# TODO can we make erf(t) work?
assert (ILT((s * eye(2) - Matrix([[1, 0], [0, 2]])).inv(), s, t) ==
Matrix([[exp(t)*Heaviside(t), 0], [0, exp(2*t)*Heaviside(t)]]))
# Test time_diff rule
assert (ILT(s**42*f(s), s, t) ==
Derivative(InverseLaplaceTransform(f(s), s, t, None), (t, 42)))
assert ILT(cos(s), s, t) == InverseLaplaceTransform(cos(s), s, t, None)
# Rules for testing different DiracDelta cases
assert (ILT(2*exp(3*s) - 5*exp(-7*s), s, t) ==
2*InverseLaplaceTransform(exp(3*s), s, t, None) -
5*DiracDelta(t - 7))
a = cos(sin(7)/2)
assert ILT(a*exp(-3*s), s, t) == a*DiracDelta(t - 3)
assert ILT(exp(2*s), s, t) == InverseLaplaceTransform(exp(2*s), s, t, None)
r = Symbol('r', real=True)
assert ILT(exp(r*s), s, t) == InverseLaplaceTransform(exp(r*s), s, t, None)
# Rules for testing whether Heaviside(t) is treated properly in diff rule
assert ILT(s**2/(a**2 + s**2), s, t) == (
-a*sin(a*t)*Heaviside(t) + DiracDelta(t))
assert ILT(s**2*(f(s) + 1/(a**2 + s**2)), s, t) == (
-a*sin(a*t)*Heaviside(t) + DiracDelta(t) +
Derivative(InverseLaplaceTransform(f(s), s, t, None), (t, 2)))
# Rules from the previous test_inverse_laplace_transform_delta_cond():
assert (ILT(exp(r*s), s, t, noconds=False) ==
(InverseLaplaceTransform(exp(r*s), s, t, None), True))
# inversion does not exist: verify it doesn't evaluate to DiracDelta
for z in (Symbol('z', extended_real=False),
Symbol('z', imaginary=True, zero=False)):
f = ILT(exp(z*s), s, t, noconds=False)
f = f[0] if isinstance(f, tuple) else f
assert f.func != DiracDelta
@slow
def test_expint():
x = Symbol('x')
a = Symbol('a')
u = Symbol('u', polar=True)
# TODO LT of Si, Shi, Chi is a mess ...
assert laplace_transform(Ci(x), x, s) == (-log(1 + s**2)/2/s, 0, True)
assert (laplace_transform(expint(a, x), x, s, simplify=True) ==
(lerchphi(s*exp_polar(I*pi), 1, a), 0, re(a) > S.Zero))
assert (laplace_transform(expint(1, x), x, s, simplify=True) ==
(log(s + 1)/s, 0, True))
assert (laplace_transform(expint(2, x), x, s, simplify=True) ==
((s - log(s + 1))/s**2, 0, True))
assert (inverse_laplace_transform(-log(1 + s**2)/2/s, s, u).expand() ==
Heaviside(u)*Ci(u))
assert (
inverse_laplace_transform(log(s + 1)/s, s, x,
simplify=True).rewrite(expint) ==
Heaviside(x)*E1(x))
assert (
inverse_laplace_transform(
(s - log(s + 1))/s**2, s, x,
simplify=True).rewrite(expint).expand() ==
(expint(2, x)*Heaviside(x)).rewrite(Ei).rewrite(expint).expand())

View File

@ -0,0 +1,13 @@
from sympy.core.numbers import E
from sympy.core.symbol import symbols
from sympy.functions.elementary.exponential import log
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.geometry.curve import Curve
from sympy.integrals.integrals import line_integrate
s, t, x, y, z = symbols('s,t,x,y,z')
def test_lineintegral():
c = Curve([E**t + 1, E**t - 1], (t, 0, log(2)))
assert line_integrate(x + y, c, [x, y]) == 3*sqrt(2)

View File

@ -0,0 +1,714 @@
from sympy.core.expr import Expr
from sympy.core.mul import Mul
from sympy.core.function import (Derivative, Function, diff, expand)
from sympy.core.numbers import (I, Rational, pi)
from sympy.core.relational import Ne
from sympy.core.singleton import S
from sympy.core.symbol import (Dummy, Symbol, symbols)
from sympy.functions.elementary.exponential import (exp, log)
from sympy.functions.elementary.hyperbolic import (asinh, csch, cosh, coth, sech, sinh, tanh)
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.functions.elementary.piecewise import Piecewise, piecewise_fold
from sympy.functions.elementary.trigonometric import (acos, acot, acsc, asec, asin, atan, cos, cot, csc, sec, sin, tan)
from sympy.functions.special.delta_functions import Heaviside, DiracDelta
from sympy.functions.special.elliptic_integrals import (elliptic_e, elliptic_f)
from sympy.functions.special.error_functions import (Chi, Ci, Ei, Shi, Si, erf, erfi, fresnelc, fresnels, li)
from sympy.functions.special.gamma_functions import uppergamma
from sympy.functions.special.polynomials import (assoc_laguerre, chebyshevt, chebyshevu, gegenbauer, hermite, jacobi, laguerre, legendre)
from sympy.functions.special.zeta_functions import polylog
from sympy.integrals.integrals import (Integral, integrate)
from sympy.logic.boolalg import And
from sympy.integrals.manualintegrate import (manualintegrate, find_substitutions,
_parts_rule, integral_steps, manual_subs)
from sympy.testing.pytest import raises, slow
x, y, z, u, n, a, b, c, d, e = symbols('x y z u n a b c d e')
f = Function('f')
def assert_is_integral_of(f: Expr, F: Expr):
assert manualintegrate(f, x) == F
assert F.diff(x).equals(f)
def test_find_substitutions():
assert find_substitutions((cot(x)**2 + 1)**2*csc(x)**2*cot(x)**2, x, u) == \
[(cot(x), 1, -u**6 - 2*u**4 - u**2)]
assert find_substitutions((sec(x)**2 + tan(x) * sec(x)) / (sec(x) + tan(x)),
x, u) == [(sec(x) + tan(x), 1, 1/u)]
assert (-x**2, Rational(-1, 2), exp(u)) in find_substitutions(x * exp(-x**2), x, u)
assert not find_substitutions(Derivative(f(x), x)**2, x, u)
def test_manualintegrate_polynomials():
assert manualintegrate(y, x) == x*y
assert manualintegrate(exp(2), x) == x * exp(2)
assert manualintegrate(x**2, x) == x**3 / 3
assert manualintegrate(3 * x**2 + 4 * x**3, x) == x**3 + x**4
assert manualintegrate((x + 2)**3, x) == (x + 2)**4 / 4
assert manualintegrate((3*x + 4)**2, x) == (3*x + 4)**3 / 9
assert manualintegrate((u + 2)**3, u) == (u + 2)**4 / 4
assert manualintegrate((3*u + 4)**2, u) == (3*u + 4)**3 / 9
def test_manualintegrate_exponentials():
assert manualintegrate(exp(2*x), x) == exp(2*x) / 2
assert manualintegrate(2**x, x) == (2 ** x) / log(2)
assert_is_integral_of(1/sqrt(1-exp(2*x)),
log(sqrt(1 - exp(2*x)) - 1)/2 - log(sqrt(1 - exp(2*x)) + 1)/2)
assert manualintegrate(1 / x, x) == log(x)
assert manualintegrate(1 / (2*x + 3), x) == log(2*x + 3) / 2
assert manualintegrate(log(x)**2 / x, x) == log(x)**3 / 3
assert_is_integral_of(x**x*(log(x)+1), x**x)
def test_manualintegrate_parts():
assert manualintegrate(exp(x) * sin(x), x) == \
(exp(x) * sin(x)) / 2 - (exp(x) * cos(x)) / 2
assert manualintegrate(2*x*cos(x), x) == 2*x*sin(x) + 2*cos(x)
assert manualintegrate(x * log(x), x) == x**2*log(x)/2 - x**2/4
assert manualintegrate(log(x), x) == x * log(x) - x
assert manualintegrate((3*x**2 + 5) * exp(x), x) == \
3*x**2*exp(x) - 6*x*exp(x) + 11*exp(x)
assert manualintegrate(atan(x), x) == x*atan(x) - log(x**2 + 1)/2
# Make sure _parts_rule doesn't pick u = constant but can pick dv =
# constant if necessary, e.g. for integrate(atan(x))
assert _parts_rule(cos(x), x) == None
assert _parts_rule(exp(x), x) == None
assert _parts_rule(x**2, x) == None
result = _parts_rule(atan(x), x)
assert result[0] == atan(x) and result[1] == 1
def test_manualintegrate_trigonometry():
assert manualintegrate(sin(x), x) == -cos(x)
assert manualintegrate(tan(x), x) == -log(cos(x))
assert manualintegrate(sec(x), x) == log(sec(x) + tan(x))
assert manualintegrate(csc(x), x) == -log(csc(x) + cot(x))
assert manualintegrate(sin(x) * cos(x), x) in [sin(x) ** 2 / 2, -cos(x)**2 / 2]
assert manualintegrate(-sec(x) * tan(x), x) == -sec(x)
assert manualintegrate(csc(x) * cot(x), x) == -csc(x)
assert manualintegrate(sec(x)**2, x) == tan(x)
assert manualintegrate(csc(x)**2, x) == -cot(x)
assert manualintegrate(x * sec(x**2), x) == log(tan(x**2) + sec(x**2))/2
assert manualintegrate(cos(x)*csc(sin(x)), x) == -log(cot(sin(x)) + csc(sin(x)))
assert manualintegrate(cos(3*x)*sec(x), x) == -x + sin(2*x)
assert manualintegrate(sin(3*x)*sec(x), x) == \
-3*log(cos(x)) + 2*log(cos(x)**2) - 2*cos(x)**2
assert_is_integral_of(sinh(2*x), cosh(2*x)/2)
assert_is_integral_of(x*cosh(x**2), sinh(x**2)/2)
assert_is_integral_of(tanh(x), log(cosh(x)))
assert_is_integral_of(coth(x), log(sinh(x)))
f, F = sech(x), 2*atan(tanh(x/2))
assert manualintegrate(f, x) == F
assert (F.diff(x) - f).rewrite(exp).simplify() == 0 # todo: equals returns None
f, F = csch(x), log(tanh(x/2))
assert manualintegrate(f, x) == F
assert (F.diff(x) - f).rewrite(exp).simplify() == 0
@slow
def test_manualintegrate_trigpowers():
assert manualintegrate(sin(x)**2 * cos(x), x) == sin(x)**3 / 3
assert manualintegrate(sin(x)**2 * cos(x) **2, x) == \
x / 8 - sin(4*x) / 32
assert manualintegrate(sin(x) * cos(x)**3, x) == -cos(x)**4 / 4
assert manualintegrate(sin(x)**3 * cos(x)**2, x) == \
cos(x)**5 / 5 - cos(x)**3 / 3
assert manualintegrate(tan(x)**3 * sec(x), x) == sec(x)**3/3 - sec(x)
assert manualintegrate(tan(x) * sec(x) **2, x) == sec(x)**2/2
assert manualintegrate(cot(x)**5 * csc(x), x) == \
-csc(x)**5/5 + 2*csc(x)**3/3 - csc(x)
assert manualintegrate(cot(x)**2 * csc(x)**6, x) == \
-cot(x)**7/7 - 2*cot(x)**5/5 - cot(x)**3/3
@slow
def test_manualintegrate_inversetrig():
# atan
assert manualintegrate(exp(x) / (1 + exp(2*x)), x) == atan(exp(x))
assert manualintegrate(1 / (4 + 9 * x**2), x) == atan(3 * x/2) / 6
assert manualintegrate(1 / (16 + 16 * x**2), x) == atan(x) / 16
assert manualintegrate(1 / (4 + x**2), x) == atan(x / 2) / 2
assert manualintegrate(1 / (1 + 4 * x**2), x) == atan(2*x) / 2
ra = Symbol('a', real=True)
rb = Symbol('b', real=True)
assert manualintegrate(1/(ra + rb*x**2), x) == \
Piecewise((atan(x/sqrt(ra/rb))/(rb*sqrt(ra/rb)), ra/rb > 0),
((log(x - sqrt(-ra/rb)) - log(x + sqrt(-ra/rb)))/(2*sqrt(rb)*sqrt(-ra)), True))
assert manualintegrate(1/(4 + rb*x**2), x) == \
Piecewise((atan(x/(2*sqrt(1/rb)))/(2*rb*sqrt(1/rb)), 1/rb > 0),
(-I*(log(x - 2*sqrt(-1/rb)) - log(x + 2*sqrt(-1/rb)))/(4*sqrt(rb)), True))
assert manualintegrate(1/(ra + 4*x**2), x) == \
Piecewise((atan(2*x/sqrt(ra))/(2*sqrt(ra)), ra > 0),
((log(x - sqrt(-ra)/2) - log(x + sqrt(-ra)/2))/(4*sqrt(-ra)), True))
assert manualintegrate(1/(4 + 4*x**2), x) == atan(x) / 4
assert manualintegrate(1/(a + b*x**2), x) == Piecewise((atan(x/sqrt(a/b))/(b*sqrt(a/b)), Ne(a, 0)),
(-1/(b*x), True))
# asin
assert manualintegrate(1/sqrt(1-x**2), x) == asin(x)
assert manualintegrate(1/sqrt(4-4*x**2), x) == asin(x)/2
assert manualintegrate(3/sqrt(1-9*x**2), x) == asin(3*x)
assert manualintegrate(1/sqrt(4-9*x**2), x) == asin(x*Rational(3, 2))/3
# asinh
assert manualintegrate(1/sqrt(x**2 + 1), x) == \
asinh(x)
assert manualintegrate(1/sqrt(x**2 + 4), x) == \
asinh(x/2)
assert manualintegrate(1/sqrt(4*x**2 + 4), x) == \
asinh(x)/2
assert manualintegrate(1/sqrt(4*x**2 + 1), x) == \
asinh(2*x)/2
assert manualintegrate(1/sqrt(ra*x**2 + 1), x) == \
Piecewise((asin(x*sqrt(-ra))/sqrt(-ra), ra < 0), (asinh(sqrt(ra)*x)/sqrt(ra), ra > 0), (x, True))
assert manualintegrate(1/sqrt(ra + x**2), x) == \
Piecewise((asinh(x*sqrt(1/ra)), ra > 0), (log(2*x + 2*sqrt(ra + x**2)), True))
# log
assert manualintegrate(1/sqrt(x**2 - 1), x) == log(2*x + 2*sqrt(x**2 - 1))
assert manualintegrate(1/sqrt(x**2 - 4), x) == log(2*x + 2*sqrt(x**2 - 4))
assert manualintegrate(1/sqrt(4*x**2 - 4), x) == log(8*x + 4*sqrt(4*x**2 - 4))/2
assert manualintegrate(1/sqrt(9*x**2 - 1), x) == log(18*x + 6*sqrt(9*x**2 - 1))/3
assert manualintegrate(1/sqrt(ra*x**2 - 4), x) == \
Piecewise((log(2*sqrt(ra)*sqrt(ra*x**2 - 4) + 2*ra*x)/sqrt(ra), Ne(ra, 0)), (-I*x/2, True))
assert manualintegrate(1/sqrt(-ra + 4*x**2), x) == \
Piecewise((asinh(2*x*sqrt(-1/ra))/2, ra < 0), (log(8*x + 4*sqrt(-ra + 4*x**2))/2, True))
# From https://www.wikiwand.com/en/List_of_integrals_of_inverse_trigonometric_functions
# asin
assert manualintegrate(asin(x), x) == x*asin(x) + sqrt(1 - x**2)
assert manualintegrate(asin(a*x), x) == Piecewise(((a*x*asin(a*x) + sqrt(-a**2*x**2 + 1))/a, Ne(a, 0)), (0, True))
assert manualintegrate(x*asin(a*x), x) == \
-a*Piecewise((-x*sqrt(-a**2*x**2 + 1)/(2*a**2) +
log(-2*a**2*x + 2*sqrt(-a**2)*sqrt(-a**2*x**2 + 1))/(2*a**2*sqrt(-a**2)), Ne(a**2, 0)),
(x**3/3, True))/2 + x**2*asin(a*x)/2
# acos
assert manualintegrate(acos(x), x) == x*acos(x) - sqrt(1 - x**2)
assert manualintegrate(acos(a*x), x) == Piecewise(((a*x*acos(a*x) - sqrt(-a**2*x**2 + 1))/a, Ne(a, 0)), (pi*x/2, True))
assert manualintegrate(x*acos(a*x), x) == \
a*Piecewise((-x*sqrt(-a**2*x**2 + 1)/(2*a**2) +
log(-2*a**2*x + 2*sqrt(-a**2)*sqrt(-a**2*x**2 + 1))/(2*a**2*sqrt(-a**2)), Ne(a**2, 0)),
(x**3/3, True))/2 + x**2*acos(a*x)/2
# atan
assert manualintegrate(atan(x), x) == x*atan(x) - log(x**2 + 1)/2
assert manualintegrate(atan(a*x), x) == Piecewise(((a*x*atan(a*x) - log(a**2*x**2 + 1)/2)/a, Ne(a, 0)), (0, True))
assert manualintegrate(x*atan(a*x), x) == -a*(x/a**2 - atan(x/sqrt(a**(-2)))/(a**4*sqrt(a**(-2))))/2 + x**2*atan(a*x)/2
# acsc
assert manualintegrate(acsc(x), x) == x*acsc(x) + Integral(1/(x*sqrt(1 - 1/x**2)), x)
assert manualintegrate(acsc(a*x), x) == x*acsc(a*x) + Integral(1/(x*sqrt(1 - 1/(a**2*x**2))), x)/a
assert manualintegrate(x*acsc(a*x), x) == x**2*acsc(a*x)/2 + Integral(1/sqrt(1 - 1/(a**2*x**2)), x)/(2*a)
# asec
assert manualintegrate(asec(x), x) == x*asec(x) - Integral(1/(x*sqrt(1 - 1/x**2)), x)
assert manualintegrate(asec(a*x), x) == x*asec(a*x) - Integral(1/(x*sqrt(1 - 1/(a**2*x**2))), x)/a
assert manualintegrate(x*asec(a*x), x) == x**2*asec(a*x)/2 - Integral(1/sqrt(1 - 1/(a**2*x**2)), x)/(2*a)
# acot
assert manualintegrate(acot(x), x) == x*acot(x) + log(x**2 + 1)/2
assert manualintegrate(acot(a*x), x) == Piecewise(((a*x*acot(a*x) + log(a**2*x**2 + 1)/2)/a, Ne(a, 0)), (pi*x/2, True))
assert manualintegrate(x*acot(a*x), x) == a*(x/a**2 - atan(x/sqrt(a**(-2)))/(a**4*sqrt(a**(-2))))/2 + x**2*acot(a*x)/2
# piecewise
assert manualintegrate(1/sqrt(ra-rb*x**2), x) == \
Piecewise((asin(x*sqrt(rb/ra))/sqrt(rb), And(-rb < 0, ra > 0)),
(asinh(x*sqrt(-rb/ra))/sqrt(-rb), And(-rb > 0, ra > 0)),
(log(-2*rb*x + 2*sqrt(-rb)*sqrt(ra - rb*x**2))/sqrt(-rb), Ne(rb, 0)),
(x/sqrt(ra), True))
assert manualintegrate(1/sqrt(ra + rb*x**2), x) == \
Piecewise((asin(x*sqrt(-rb/ra))/sqrt(-rb), And(ra > 0, rb < 0)),
(asinh(x*sqrt(rb/ra))/sqrt(rb), And(ra > 0, rb > 0)),
(log(2*sqrt(rb)*sqrt(ra + rb*x**2) + 2*rb*x)/sqrt(rb), Ne(rb, 0)),
(x/sqrt(ra), True))
def test_manualintegrate_trig_substitution():
assert manualintegrate(sqrt(16*x**2 - 9)/x, x) == \
Piecewise((sqrt(16*x**2 - 9) - 3*acos(3/(4*x)),
And(x < Rational(3, 4), x > Rational(-3, 4))))
assert manualintegrate(1/(x**4 * sqrt(25-x**2)), x) == \
Piecewise((-sqrt(-x**2/25 + 1)/(125*x) -
(-x**2/25 + 1)**(3*S.Half)/(15*x**3), And(x < 5, x > -5)))
assert manualintegrate(x**7/(49*x**2 + 1)**(3 * S.Half), x) == \
((49*x**2 + 1)**(5*S.Half)/28824005 -
(49*x**2 + 1)**(3*S.Half)/5764801 +
3*sqrt(49*x**2 + 1)/5764801 + 1/(5764801*sqrt(49*x**2 + 1)))
def test_manualintegrate_trivial_substitution():
assert manualintegrate((exp(x) - exp(-x))/x, x) == -Ei(-x) + Ei(x)
f = Function('f')
assert manualintegrate((f(x) - f(-x))/x, x) == \
-Integral(f(-x)/x, x) + Integral(f(x)/x, x)
def test_manualintegrate_rational():
assert manualintegrate(1/(4 - x**2), x) == -log(x - 2)/4 + log(x + 2)/4
assert manualintegrate(1/(-1 + x**2), x) == log(x - 1)/2 - log(x + 1)/2
def test_manualintegrate_special():
f, F = 4*exp(-x**2/3), 2*sqrt(3)*sqrt(pi)*erf(sqrt(3)*x/3)
assert_is_integral_of(f, F)
f, F = 3*exp(4*x**2), 3*sqrt(pi)*erfi(2*x)/4
assert_is_integral_of(f, F)
f, F = x**Rational(1, 3)*exp(-x/8), -16*uppergamma(Rational(4, 3), x/8)
assert_is_integral_of(f, F)
f, F = exp(2*x)/x, Ei(2*x)
assert_is_integral_of(f, F)
f, F = exp(1 + 2*x - x**2), sqrt(pi)*exp(2)*erf(x - 1)/2
assert_is_integral_of(f, F)
f = sin(x**2 + 4*x + 1)
F = (sqrt(2)*sqrt(pi)*(-sin(3)*fresnelc(sqrt(2)*(2*x + 4)/(2*sqrt(pi))) +
cos(3)*fresnels(sqrt(2)*(2*x + 4)/(2*sqrt(pi))))/2)
assert_is_integral_of(f, F)
f, F = cos(4*x**2), sqrt(2)*sqrt(pi)*fresnelc(2*sqrt(2)*x/sqrt(pi))/4
assert_is_integral_of(f, F)
f, F = sin(3*x + 2)/x, sin(2)*Ci(3*x) + cos(2)*Si(3*x)
assert_is_integral_of(f, F)
f, F = sinh(3*x - 2)/x, -sinh(2)*Chi(3*x) + cosh(2)*Shi(3*x)
assert_is_integral_of(f, F)
f, F = 5*cos(2*x - 3)/x, 5*cos(3)*Ci(2*x) + 5*sin(3)*Si(2*x)
assert_is_integral_of(f, F)
f, F = cosh(x/2)/x, Chi(x/2)
assert_is_integral_of(f, F)
f, F = cos(x**2)/x, Ci(x**2)/2
assert_is_integral_of(f, F)
f, F = 1/log(2*x + 1), li(2*x + 1)/2
assert_is_integral_of(f, F)
f, F = polylog(2, 5*x)/x, polylog(3, 5*x)
assert_is_integral_of(f, F)
f, F = 5/sqrt(3 - 2*sin(x)**2), 5*sqrt(3)*elliptic_f(x, Rational(2, 3))/3
assert_is_integral_of(f, F)
f, F = sqrt(4 + 9*sin(x)**2), 2*elliptic_e(x, Rational(-9, 4))
assert_is_integral_of(f, F)
def test_manualintegrate_derivative():
assert manualintegrate(pi * Derivative(x**2 + 2*x + 3), x) == \
pi * (x**2 + 2*x + 3)
assert manualintegrate(Derivative(x**2 + 2*x + 3, y), x) == \
Integral(Derivative(x**2 + 2*x + 3, y))
assert manualintegrate(Derivative(sin(x), x, x, x, y), x) == \
Derivative(sin(x), x, x, y)
def test_manualintegrate_Heaviside():
assert_is_integral_of(DiracDelta(3*x+2), Heaviside(3*x+2)/3)
assert_is_integral_of(DiracDelta(3*x, 0), Heaviside(3*x)/3)
assert manualintegrate(DiracDelta(a+b*x, 1), x) == \
Piecewise((DiracDelta(a + b*x)/b, Ne(b, 0)), (x*DiracDelta(a, 1), True))
assert_is_integral_of(DiracDelta(x/3-1, 2), 3*DiracDelta(x/3-1, 1))
assert manualintegrate(Heaviside(x), x) == x*Heaviside(x)
assert manualintegrate(x*Heaviside(2), x) == x**2/2
assert manualintegrate(x*Heaviside(-2), x) == 0
assert manualintegrate(x*Heaviside( x), x) == x**2*Heaviside( x)/2
assert manualintegrate(x*Heaviside(-x), x) == x**2*Heaviside(-x)/2
assert manualintegrate(Heaviside(2*x + 4), x) == (x+2)*Heaviside(2*x + 4)
assert manualintegrate(x*Heaviside(x), x) == x**2*Heaviside(x)/2
assert manualintegrate(Heaviside(x + 1)*Heaviside(1 - x)*x**2, x) == \
((x**3/3 + Rational(1, 3))*Heaviside(x + 1) - Rational(2, 3))*Heaviside(-x + 1)
y = Symbol('y')
assert manualintegrate(sin(7 + x)*Heaviside(3*x - 7), x) == \
(- cos(x + 7) + cos(Rational(28, 3)))*Heaviside(3*x - S(7))
assert manualintegrate(sin(y + x)*Heaviside(3*x - y), x) == \
(cos(y*Rational(4, 3)) - cos(x + y))*Heaviside(3*x - y)
def test_manualintegrate_orthogonal_poly():
n = symbols('n')
a, b = 7, Rational(5, 3)
polys = [jacobi(n, a, b, x), gegenbauer(n, a, x), chebyshevt(n, x),
chebyshevu(n, x), legendre(n, x), hermite(n, x), laguerre(n, x),
assoc_laguerre(n, a, x)]
for p in polys:
integral = manualintegrate(p, x)
for deg in [-2, -1, 0, 1, 3, 5, 8]:
# some accept negative "degree", some do not
try:
p_subbed = p.subs(n, deg)
except ValueError:
continue
assert (integral.subs(n, deg).diff(x) - p_subbed).expand() == 0
# can also integrate simple expressions with these polynomials
q = x*p.subs(x, 2*x + 1)
integral = manualintegrate(q, x)
for deg in [2, 4, 7]:
assert (integral.subs(n, deg).diff(x) - q.subs(n, deg)).expand() == 0
# cannot integrate with respect to any other parameter
t = symbols('t')
for i in range(len(p.args) - 1):
new_args = list(p.args)
new_args[i] = t
assert isinstance(manualintegrate(p.func(*new_args), t), Integral)
@slow
def test_issue_6799():
r, x, phi = map(Symbol, 'r x phi'.split())
n = Symbol('n', integer=True, positive=True)
integrand = (cos(n*(x-phi))*cos(n*x))
limits = (x, -pi, pi)
assert manualintegrate(integrand, x) == \
((n*x/2 + sin(2*n*x)/4)*cos(n*phi) - sin(n*phi)*cos(n*x)**2/2)/n
assert r * integrate(integrand, limits).trigsimp() / pi == r * cos(n * phi)
assert not integrate(integrand, limits).has(Dummy)
def test_issue_12251():
assert manualintegrate(x**y, x) == Piecewise(
(x**(y + 1)/(y + 1), Ne(y, -1)), (log(x), True))
def test_issue_3796():
assert manualintegrate(diff(exp(x + x**2)), x) == exp(x + x**2)
assert integrate(x * exp(x**4), x, risch=False) == -I*sqrt(pi)*erf(I*x**2)/4
def test_manual_true():
assert integrate(exp(x) * sin(x), x, manual=True) == \
(exp(x) * sin(x)) / 2 - (exp(x) * cos(x)) / 2
assert integrate(sin(x) * cos(x), x, manual=True) in \
[sin(x) ** 2 / 2, -cos(x)**2 / 2]
def test_issue_6746():
y = Symbol('y')
n = Symbol('n')
assert manualintegrate(y**x, x) == Piecewise(
(y**x/log(y), Ne(log(y), 0)), (x, True))
assert manualintegrate(y**(n*x), x) == Piecewise(
(Piecewise(
(y**(n*x)/log(y), Ne(log(y), 0)),
(n*x, True)
)/n, Ne(n, 0)),
(x, True))
assert manualintegrate(exp(n*x), x) == Piecewise(
(exp(n*x)/n, Ne(n, 0)), (x, True))
y = Symbol('y', positive=True)
assert manualintegrate((y + 1)**x, x) == (y + 1)**x/log(y + 1)
y = Symbol('y', zero=True)
assert manualintegrate((y + 1)**x, x) == x
y = Symbol('y')
n = Symbol('n', nonzero=True)
assert manualintegrate(y**(n*x), x) == Piecewise(
(y**(n*x)/log(y), Ne(log(y), 0)), (n*x, True))/n
y = Symbol('y', positive=True)
assert manualintegrate((y + 1)**(n*x), x) == \
(y + 1)**(n*x)/(n*log(y + 1))
a = Symbol('a', negative=True)
b = Symbol('b')
assert manualintegrate(1/(a + b*x**2), x) == atan(x/sqrt(a/b))/(b*sqrt(a/b))
b = Symbol('b', negative=True)
assert manualintegrate(1/(a + b*x**2), x) == \
atan(x/(sqrt(-a)*sqrt(-1/b)))/(b*sqrt(-a)*sqrt(-1/b))
assert manualintegrate(1/((x**a + y**b + 4)*sqrt(a*x**2 + 1)), x) == \
y**(-b)*Integral(x**(-a)/(y**(-b)*sqrt(a*x**2 + 1) +
x**(-a)*sqrt(a*x**2 + 1) + 4*x**(-a)*y**(-b)*sqrt(a*x**2 + 1)), x)
assert manualintegrate(1/((x**2 + 4)*sqrt(4*x**2 + 1)), x) == \
Integral(1/((x**2 + 4)*sqrt(4*x**2 + 1)), x)
assert manualintegrate(1/(x - a**x + x*b**2), x) == \
Integral(1/(-a**x + b**2*x + x), x)
@slow
def test_issue_2850():
assert manualintegrate(asin(x)*log(x), x) == -x*asin(x) - sqrt(-x**2 + 1) \
+ (x*asin(x) + sqrt(-x**2 + 1))*log(x) - Integral(sqrt(-x**2 + 1)/x, x)
assert manualintegrate(acos(x)*log(x), x) == -x*acos(x) + sqrt(-x**2 + 1) + \
(x*acos(x) - sqrt(-x**2 + 1))*log(x) + Integral(sqrt(-x**2 + 1)/x, x)
assert manualintegrate(atan(x)*log(x), x) == -x*atan(x) + (x*atan(x) - \
log(x**2 + 1)/2)*log(x) + log(x**2 + 1)/2 + Integral(log(x**2 + 1)/x, x)/2
def test_issue_9462():
assert manualintegrate(sin(2*x)*exp(x), x) == exp(x)*sin(2*x)/5 - 2*exp(x)*cos(2*x)/5
assert not integral_steps(sin(2*x)*exp(x), x).contains_dont_know()
assert manualintegrate((x - 3) / (x**2 - 2*x + 2)**2, x) == \
Integral(x/(x**4 - 4*x**3 + 8*x**2 - 8*x + 4), x) \
- 3*Integral(1/(x**4 - 4*x**3 + 8*x**2 - 8*x + 4), x)
def test_cyclic_parts():
f = cos(x)*exp(x/4)
F = 16*exp(x/4)*sin(x)/17 + 4*exp(x/4)*cos(x)/17
assert manualintegrate(f, x) == F and F.diff(x) == f
f = x*cos(x)*exp(x/4)
F = (x*(16*exp(x/4)*sin(x)/17 + 4*exp(x/4)*cos(x)/17) -
128*exp(x/4)*sin(x)/289 + 240*exp(x/4)*cos(x)/289)
assert manualintegrate(f, x) == F and F.diff(x) == f
@slow
def test_issue_10847_slow():
assert manualintegrate((4*x**4 + 4*x**3 + 16*x**2 + 12*x + 8)
/ (x**6 + 2*x**5 + 3*x**4 + 4*x**3 + 3*x**2 + 2*x + 1), x) == \
2*x/(x**2 + 1) + 3*atan(x) - 1/(x**2 + 1) - 3/(x + 1)
@slow
def test_issue_10847():
assert manualintegrate(x**2 / (x**2 - c), x) == \
c*Piecewise((atan(x/sqrt(-c))/sqrt(-c), Ne(c, 0)), (-1/x, True)) + x
rc = Symbol('c', real=True)
assert manualintegrate(x**2 / (x**2 - rc), x) == \
rc*Piecewise((atan(x/sqrt(-rc))/sqrt(-rc), rc < 0),
((log(-sqrt(rc) + x) - log(sqrt(rc) + x))/(2*sqrt(rc)), True)) + x
assert manualintegrate(sqrt(x - y) * log(z / x), x) == \
4*y**2*Piecewise((atan(sqrt(x - y)/sqrt(y))/sqrt(y), Ne(y, 0)),
(-1/sqrt(x - y), True))/3 - 4*y*sqrt(x - y)/3 + \
2*(x - y)**Rational(3, 2)*log(z/x)/3 + 4*(x - y)**Rational(3, 2)/9
ry = Symbol('y', real=True)
rz = Symbol('z', real=True)
assert manualintegrate(sqrt(x - ry) * log(rz / x), x) == \
4*ry**2*Piecewise((atan(sqrt(x - ry)/sqrt(ry))/sqrt(ry), ry > 0),
((log(-sqrt(-ry) + sqrt(x - ry)) - log(sqrt(-ry) + sqrt(x - ry)))/(2*sqrt(-ry)), True))/3 \
- 4*ry*sqrt(x - ry)/3 + 2*(x - ry)**Rational(3, 2)*log(rz/x)/3 \
+ 4*(x - ry)**Rational(3, 2)/9
assert manualintegrate(sqrt(x) * log(x), x) == 2*x**Rational(3, 2)*log(x)/3 - 4*x**Rational(3, 2)/9
result = manualintegrate(sqrt(a*x + b) / x, x)
assert result == Piecewise((-2*b*Piecewise(
(-atan(sqrt(a*x + b)/sqrt(-b))/sqrt(-b), Ne(b, 0)),
(1/sqrt(a*x + b), True)) + 2*sqrt(a*x + b), Ne(a, 0)),
(sqrt(b)*log(x), True))
assert piecewise_fold(result) == Piecewise(
(2*b*atan(sqrt(a*x + b)/sqrt(-b))/sqrt(-b) + 2*sqrt(a*x + b), Ne(a, 0) & Ne(b, 0)),
(-2*b/sqrt(a*x + b) + 2*sqrt(a*x + b), Ne(a, 0)),
(sqrt(b)*log(x), True))
ra = Symbol('a', real=True)
rb = Symbol('b', real=True)
assert manualintegrate(sqrt(ra*x + rb) / x, x) == \
Piecewise(
(-2*rb*Piecewise(
(-atan(sqrt(ra*x + rb)/sqrt(-rb))/sqrt(-rb), rb < 0),
(-I*(log(-sqrt(rb) + sqrt(ra*x + rb)) - log(sqrt(rb) + sqrt(ra*x + rb)))/(2*sqrt(-rb)), True)) +
2*sqrt(ra*x + rb), Ne(ra, 0)),
(sqrt(rb)*log(x), True))
assert expand(manualintegrate(sqrt(ra*x + rb) / (x + rc), x)) == \
Piecewise((-2*ra*rc*Piecewise((atan(sqrt(ra*x + rb)/sqrt(ra*rc - rb))/sqrt(ra*rc - rb), ra*rc - rb > 0),
(log(-sqrt(-ra*rc + rb) + sqrt(ra*x + rb))/(2*sqrt(-ra*rc + rb)) -
log(sqrt(-ra*rc + rb) + sqrt(ra*x + rb))/(2*sqrt(-ra*rc + rb)), True)) +
2*rb*Piecewise((atan(sqrt(ra*x + rb)/sqrt(ra*rc - rb))/sqrt(ra*rc - rb), ra*rc - rb > 0),
(log(-sqrt(-ra*rc + rb) + sqrt(ra*x + rb))/(2*sqrt(-ra*rc + rb)) -
log(sqrt(-ra*rc + rb) + sqrt(ra*x + rb))/(2*sqrt(-ra*rc + rb)), True)) +
2*sqrt(ra*x + rb), Ne(ra, 0)), (sqrt(rb)*log(rc + x), True))
assert manualintegrate(sqrt(2*x + 3) / (x + 1), x) == 2*sqrt(2*x + 3) - log(sqrt(2*x + 3) + 1) + log(sqrt(2*x + 3) - 1)
assert manualintegrate(sqrt(2*x + 3) / 2 * x, x) == (2*x + 3)**Rational(5, 2)/20 - (2*x + 3)**Rational(3, 2)/4
assert manualintegrate(x**Rational(3,2) * log(x), x) == 2*x**Rational(5,2)*log(x)/5 - 4*x**Rational(5,2)/25
assert manualintegrate(x**(-3) * log(x), x) == -log(x)/(2*x**2) - 1/(4*x**2)
assert manualintegrate(log(y)/(y**2*(1 - 1/y)), y) == \
log(y)*log(-1 + 1/y) - Integral(log(-1 + 1/y)/y, y)
def test_issue_12899():
assert manualintegrate(f(x,y).diff(x),y) == Integral(Derivative(f(x,y),x),y)
assert manualintegrate(f(x,y).diff(y).diff(x),y) == Derivative(f(x,y),x)
def test_constant_independent_of_symbol():
assert manualintegrate(Integral(y, (x, 1, 2)), x) == \
x*Integral(y, (x, 1, 2))
def test_issue_12641():
assert manualintegrate(sin(2*x), x) == -cos(2*x)/2
assert manualintegrate(cos(x)*sin(2*x), x) == -2*cos(x)**3/3
assert manualintegrate((sin(2*x)*cos(x))/(1 + cos(x)), x) == \
-2*log(cos(x) + 1) - cos(x)**2 + 2*cos(x)
@slow
def test_issue_13297():
assert manualintegrate(sin(x) * cos(x)**5, x) == -cos(x)**6 / 6
def test_issue_14470():
assert_is_integral_of(1/(x*sqrt(x + 1)), log(sqrt(x + 1) - 1) - log(sqrt(x + 1) + 1))
@slow
def test_issue_9858():
assert manualintegrate(exp(x)*cos(exp(x)), x) == sin(exp(x))
assert manualintegrate(exp(2*x)*cos(exp(x)), x) == \
exp(x)*sin(exp(x)) + cos(exp(x))
res = manualintegrate(exp(10*x)*sin(exp(x)), x)
assert not res.has(Integral)
assert res.diff(x) == exp(10*x)*sin(exp(x))
# an example with many similar integrations by parts
assert manualintegrate(sum(x*exp(k*x) for k in range(1, 8)), x) == (
x*exp(7*x)/7 + x*exp(6*x)/6 + x*exp(5*x)/5 + x*exp(4*x)/4 +
x*exp(3*x)/3 + x*exp(2*x)/2 + x*exp(x) - exp(7*x)/49 -exp(6*x)/36 -
exp(5*x)/25 - exp(4*x)/16 - exp(3*x)/9 - exp(2*x)/4 - exp(x))
def test_issue_8520():
assert manualintegrate(x/(x**4 + 1), x) == atan(x**2)/2
assert manualintegrate(x**2/(x**6 + 25), x) == atan(x**3/5)/15
f = x/(9*x**4 + 4)**2
assert manualintegrate(f, x).diff(x).factor() == f
def test_manual_subs():
x, y = symbols('x y')
expr = log(x) + exp(x)
# if log(x) is y, then exp(y) is x
assert manual_subs(expr, log(x), y) == y + exp(exp(y))
# if exp(x) is y, then log(y) need not be x
assert manual_subs(expr, exp(x), y) == log(x) + y
raises(ValueError, lambda: manual_subs(expr, x))
raises(ValueError, lambda: manual_subs(expr, exp(x), x, y))
@slow
def test_issue_15471():
f = log(x)*cos(log(x))/x**Rational(3, 4)
F = -128*x**Rational(1, 4)*sin(log(x))/289 + 240*x**Rational(1, 4)*cos(log(x))/289 + (16*x**Rational(1, 4)*sin(log(x))/17 + 4*x**Rational(1, 4)*cos(log(x))/17)*log(x)
assert_is_integral_of(f, F)
def test_quadratic_denom():
f = (5*x + 2)/(3*x**2 - 2*x + 8)
assert manualintegrate(f, x) == 5*log(3*x**2 - 2*x + 8)/6 + 11*sqrt(23)*atan(3*sqrt(23)*(x - Rational(1, 3))/23)/69
g = 3/(2*x**2 + 3*x + 1)
assert manualintegrate(g, x) == 3*log(4*x + 2) - 3*log(4*x + 4)
def test_issue_22757():
assert manualintegrate(sin(x), y) == y * sin(x)
def test_issue_23348():
steps = integral_steps(tan(x), x)
constant_times_step = steps.substep.substep
assert constant_times_step.integrand == constant_times_step.constant * constant_times_step.other
def test_issue_23566():
i = Integral(1/sqrt(x**2 - 1), (x, -2, -1)).doit(manual=True)
assert i == -log(4 - 2*sqrt(3)) + log(2)
assert str(i.n()) == '1.31695789692482'
def test_issue_25093():
ap = Symbol('ap', positive=True)
an = Symbol('an', negative=True)
assert manualintegrate(exp(a*x**2 + b), x) == sqrt(pi)*exp(b)*erfi(sqrt(a)*x)/(2*sqrt(a))
assert manualintegrate(exp(ap*x**2 + b), x) == sqrt(pi)*exp(b)*erfi(sqrt(ap)*x)/(2*sqrt(ap))
assert manualintegrate(exp(an*x**2 + b), x) == -sqrt(pi)*exp(b)*erf(an*x/sqrt(-an))/(2*sqrt(-an))
assert manualintegrate(sin(a*x**2 + b), x) == (
sqrt(2)*sqrt(pi)*(sin(b)*fresnelc(sqrt(2)*sqrt(a)*x/sqrt(pi))
+ cos(b)*fresnels(sqrt(2)*sqrt(a)*x/sqrt(pi)))/(2*sqrt(a)))
assert manualintegrate(cos(a*x**2 + b), x) == (
sqrt(2)*sqrt(pi)*(-sin(b)*fresnels(sqrt(2)*sqrt(a)*x/sqrt(pi))
+ cos(b)*fresnelc(sqrt(2)*sqrt(a)*x/sqrt(pi)))/(2*sqrt(a)))
def test_nested_pow():
assert_is_integral_of(sqrt(x**2), x*sqrt(x**2)/2)
assert_is_integral_of(sqrt(x**(S(5)/3)), 6*x*sqrt(x**(S(5)/3))/11)
assert_is_integral_of(1/sqrt(x**2), x*log(x)/sqrt(x**2))
assert_is_integral_of(x*sqrt(x**(-4)), x**2*sqrt(x**-4)*log(x))
f = (c*(a+b*x)**d)**e
F1 = (c*(a + b*x)**d)**e*(a/b + x)/(d*e + 1)
F2 = (c*(a + b*x)**d)**e*(a/b + x)*log(a/b + x)
assert manualintegrate(f, x) == \
Piecewise((Piecewise((F1, Ne(d*e, -1)), (F2, True)), Ne(b, 0)), (x*(a**d*c)**e, True))
assert F1.diff(x).equals(f)
assert F2.diff(x).subs(d*e, -1).equals(f)
def test_manualintegrate_sqrt_linear():
assert_is_integral_of((5*x**3+4)/sqrt(2+3*x),
10*(3*x + 2)**(S(7)/2)/567 - 4*(3*x + 2)**(S(5)/2)/27 +
40*(3*x + 2)**(S(3)/2)/81 + 136*sqrt(3*x + 2)/81)
assert manualintegrate(x/sqrt(a+b*x)**3, x) == \
Piecewise((Mul(2, b**-2, a/sqrt(a + b*x) + sqrt(a + b*x)), Ne(b, 0)), (x**2/(2*a**(S(3)/2)), True))
assert_is_integral_of((sqrt(3*x+3)+1)/((2*x+2)**(1/S(3))+1),
3*sqrt(6)*(2*x + 2)**(S(7)/6)/14 - 3*sqrt(6)*(2*x + 2)**(S(5)/6)/10 -
3*sqrt(6)*(2*x + 2)**(S.One/6)/2 + 3*(2*x + 2)**(S(2)/3)/4 - 3*(2*x + 2)**(S.One/3)/2 +
sqrt(6)*sqrt(2*x + 2)/2 + 3*log((2*x + 2)**(S.One/3) + 1)/2 +
3*sqrt(6)*atan((2*x + 2)**(S.One/6))/2)
assert_is_integral_of(sqrt(x+sqrt(x)),
2*sqrt(sqrt(x) + x)*(sqrt(x)/12 + x/3 - S(1)/8) + log(2*sqrt(x) + 2*sqrt(sqrt(x) + x) + 1)/8)
assert_is_integral_of(sqrt(2*x+3+sqrt(4*x+5))**3,
sqrt(2*x + sqrt(4*x + 5) + 3) *
(9*x/10 + 11*(4*x + 5)**(S(3)/2)/40 + sqrt(4*x + 5)/40 + (4*x + 5)**2/10 + S(11)/10)/2)
def test_manualintegrate_sqrt_quadratic():
assert_is_integral_of(1/sqrt((x - I)**2-1), log(2*x + 2*sqrt(x**2 - 2*I*x - 2) - 2*I))
assert_is_integral_of(1/sqrt(3*x**2+4*x+5), sqrt(3)*asinh(3*sqrt(11)*(x + S(2)/3)/11)/3)
assert_is_integral_of(1/sqrt(-3*x**2+4*x+5), sqrt(3)*asin(3*sqrt(19)*(x - S(2)/3)/19)/3)
assert_is_integral_of(1/sqrt(3*x**2+4*x-5), sqrt(3)*log(6*x + 2*sqrt(3)*sqrt(3*x**2 + 4*x - 5) + 4)/3)
assert_is_integral_of(1/sqrt(4*x**2-4*x+1), (x - S.Half)*log(x - S.Half)/(2*sqrt((x - S.Half)**2)))
assert manualintegrate(1/sqrt(a+b*x+c*x**2), x) == \
Piecewise((log(b + 2*sqrt(c)*sqrt(a + b*x + c*x**2) + 2*c*x)/sqrt(c), Ne(c, 0) & Ne(a - b**2/(4*c), 0)),
((b/(2*c) + x)*log(b/(2*c) + x)/sqrt(c*(b/(2*c) + x)**2), Ne(c, 0)),
(2*sqrt(a + b*x)/b, Ne(b, 0)), (x/sqrt(a), True))
assert_is_integral_of((7*x+6)/sqrt(3*x**2+4*x+5),
7*sqrt(3*x**2 + 4*x + 5)/3 + 4*sqrt(3)*asinh(3*sqrt(11)*(x + S(2)/3)/11)/9)
assert_is_integral_of((7*x+6)/sqrt(-3*x**2+4*x+5),
-7*sqrt(-3*x**2 + 4*x + 5)/3 + 32*sqrt(3)*asin(3*sqrt(19)*(x - S(2)/3)/19)/9)
assert_is_integral_of((7*x+6)/sqrt(3*x**2+4*x-5),
7*sqrt(3*x**2 + 4*x - 5)/3 + 4*sqrt(3)*log(6*x + 2*sqrt(3)*sqrt(3*x**2 + 4*x - 5) + 4)/9)
assert manualintegrate((d+e*x)/sqrt(a+b*x+c*x**2), x) == \
Piecewise(((-b*e/(2*c) + d) *
Piecewise((log(b + 2*sqrt(c)*sqrt(a + b*x + c*x**2) + 2*c*x)/sqrt(c), Ne(a - b**2/(4*c), 0)),
((b/(2*c) + x)*log(b/(2*c) + x)/sqrt(c*(b/(2*c) + x)**2), True)) +
e*sqrt(a + b*x + c*x**2)/c, Ne(c, 0)),
((2*d*sqrt(a + b*x) + 2*e*(-a*sqrt(a + b*x) + (a + b*x)**(S(3)/2)/3)/b)/b, Ne(b, 0)),
((d*x + e*x**2/2)/sqrt(a), True))
assert manualintegrate((3*x**3-x**2+2*x-4)/sqrt(x**2-3*x+2), x) == \
sqrt(x**2 - 3*x + 2)*(x**2 + 13*x/4 + S(101)/8) + 135*log(2*x + 2*sqrt(x**2 - 3*x + 2) - 3)/16
assert_is_integral_of(sqrt(53225*x**2-66732*x+23013),
(x/2 - S(16683)/53225)*sqrt(53225*x**2 - 66732*x + 23013) +
111576969*sqrt(2129)*asinh(53225*x/10563 - S(11122)/3521)/1133160250)
assert manualintegrate(sqrt(a+c*x**2), x) == \
Piecewise((a*Piecewise((log(2*sqrt(c)*sqrt(a + c*x**2) + 2*c*x)/sqrt(c), Ne(a, 0)),
(x*log(x)/sqrt(c*x**2), True))/2 + x*sqrt(a + c*x**2)/2, Ne(c, 0)),
(sqrt(a)*x, True))
assert manualintegrate(sqrt(a+b*x+c*x**2), x) == \
Piecewise(((a/2 - b**2/(8*c)) *
Piecewise((log(b + 2*sqrt(c)*sqrt(a + b*x + c*x**2) + 2*c*x)/sqrt(c), Ne(a - b**2/(4*c), 0)),
((b/(2*c) + x)*log(b/(2*c) + x)/sqrt(c*(b/(2*c) + x)**2), True)) +
(b/(4*c) + x/2)*sqrt(a + b*x + c*x**2), Ne(c, 0)),
(2*(a + b*x)**(S(3)/2)/(3*b), Ne(b, 0)),
(sqrt(a)*x, True))
assert_is_integral_of(x*sqrt(x**2+2*x+4),
(x**2/3 + x/6 + S(5)/6)*sqrt(x**2 + 2*x + 4) - 3*asinh(sqrt(3)*(x + 1)/3)/2)
def test_mul_pow_derivative():
assert_is_integral_of(x*sec(x)*tan(x), x*sec(x) - log(tan(x) + sec(x)))
assert_is_integral_of(x*sec(x)**2, x*tan(x) + log(cos(x)))
assert_is_integral_of(x**3*Derivative(f(x), (x, 4)),
x**3*Derivative(f(x), (x, 3)) - 3*x**2*Derivative(f(x), (x, 2)) +
6*x*Derivative(f(x), x) - 6*f(x))

View File

@ -0,0 +1,774 @@
from sympy.core.function import expand_func
from sympy.core.numbers import (I, Rational, oo, pi)
from sympy.core.singleton import S
from sympy.core.sorting import default_sort_key
from sympy.functions.elementary.complexes import Abs, arg, re, unpolarify
from sympy.functions.elementary.exponential import (exp, exp_polar, log)
from sympy.functions.elementary.hyperbolic import cosh, acosh, sinh
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.functions.elementary.piecewise import Piecewise, piecewise_fold
from sympy.functions.elementary.trigonometric import (cos, sin, sinc, asin)
from sympy.functions.special.error_functions import (erf, erfc)
from sympy.functions.special.gamma_functions import (gamma, polygamma)
from sympy.functions.special.hyper import (hyper, meijerg)
from sympy.integrals.integrals import (Integral, integrate)
from sympy.simplify.hyperexpand import hyperexpand
from sympy.simplify.simplify import simplify
from sympy.integrals.meijerint import (_rewrite_single, _rewrite1,
meijerint_indefinite, _inflate_g, _create_lookup_table,
meijerint_definite, meijerint_inversion)
from sympy.testing.pytest import slow
from sympy.core.random import (verify_numerically,
random_complex_number as randcplx)
from sympy.abc import x, y, a, b, c, d, s, t, z
def test_rewrite_single():
def t(expr, c, m):
e = _rewrite_single(meijerg([a], [b], [c], [d], expr), x)
assert e is not None
assert isinstance(e[0][0][2], meijerg)
assert e[0][0][2].argument.as_coeff_mul(x) == (c, (m,))
def tn(expr):
assert _rewrite_single(meijerg([a], [b], [c], [d], expr), x) is None
t(x, 1, x)
t(x**2, 1, x**2)
t(x**2 + y*x**2, y + 1, x**2)
tn(x**2 + x)
tn(x**y)
def u(expr, x):
from sympy.core.add import Add
r = _rewrite_single(expr, x)
e = Add(*[res[0]*res[2] for res in r[0]]).replace(
exp_polar, exp) # XXX Hack?
assert verify_numerically(e, expr, x)
u(exp(-x)*sin(x), x)
# The following has stopped working because hyperexpand changed slightly.
# It is probably not worth fixing
#u(exp(-x)*sin(x)*cos(x), x)
# This one cannot be done numerically, since it comes out as a g-function
# of argument 4*pi
# NOTE This also tests a bug in inverse mellin transform (which used to
# turn exp(4*pi*I*t) into a factor of exp(4*pi*I)**t instead of
# exp_polar).
#u(exp(x)*sin(x), x)
assert _rewrite_single(exp(x)*sin(x), x) == \
([(-sqrt(2)/(2*sqrt(pi)), 0,
meijerg(((Rational(-1, 2), 0, Rational(1, 4), S.Half, Rational(3, 4)), (1,)),
((), (Rational(-1, 2), 0)), 64*exp_polar(-4*I*pi)/x**4))], True)
def test_rewrite1():
assert _rewrite1(x**3*meijerg([a], [b], [c], [d], x**2 + y*x**2)*5, x) == \
(5, x**3, [(1, 0, meijerg([a], [b], [c], [d], x**2*(y + 1)))], True)
def test_meijerint_indefinite_numerically():
def t(fac, arg):
g = meijerg([a], [b], [c], [d], arg)*fac
subs = {a: randcplx()/10, b: randcplx()/10 + I,
c: randcplx(), d: randcplx()}
integral = meijerint_indefinite(g, x)
assert integral is not None
assert verify_numerically(g.subs(subs), integral.diff(x).subs(subs), x)
t(1, x)
t(2, x)
t(1, 2*x)
t(1, x**2)
t(5, x**S('3/2'))
t(x**3, x)
t(3*x**S('3/2'), 4*x**S('7/3'))
def test_meijerint_definite():
v, b = meijerint_definite(x, x, 0, 0)
assert v.is_zero and b is True
v, b = meijerint_definite(x, x, oo, oo)
assert v.is_zero and b is True
def test_inflate():
subs = {a: randcplx()/10, b: randcplx()/10 + I, c: randcplx(),
d: randcplx(), y: randcplx()/10}
def t(a, b, arg, n):
from sympy.core.mul import Mul
m1 = meijerg(a, b, arg)
m2 = Mul(*_inflate_g(m1, n))
# NOTE: (the random number)**9 must still be on the principal sheet.
# Thus make b&d small to create random numbers of small imaginary part.
return verify_numerically(m1.subs(subs), m2.subs(subs), x, b=0.1, d=-0.1)
assert t([[a], [b]], [[c], [d]], x, 3)
assert t([[a, y], [b]], [[c], [d]], x, 3)
assert t([[a], [b]], [[c, y], [d]], 2*x**3, 3)
def test_recursive():
from sympy.core.symbol import symbols
a, b, c = symbols('a b c', positive=True)
r = exp(-(x - a)**2)*exp(-(x - b)**2)
e = integrate(r, (x, 0, oo), meijerg=True)
assert simplify(e.expand()) == (
sqrt(2)*sqrt(pi)*(
(erf(sqrt(2)*(a + b)/2) + 1)*exp(-a**2/2 + a*b - b**2/2))/4)
e = integrate(exp(-(x - a)**2)*exp(-(x - b)**2)*exp(c*x), (x, 0, oo), meijerg=True)
assert simplify(e) == (
sqrt(2)*sqrt(pi)*(erf(sqrt(2)*(2*a + 2*b + c)/4) + 1)*exp(-a**2 - b**2
+ (2*a + 2*b + c)**2/8)/4)
assert simplify(integrate(exp(-(x - a - b - c)**2), (x, 0, oo), meijerg=True)) == \
sqrt(pi)/2*(1 + erf(a + b + c))
assert simplify(integrate(exp(-(x + a + b + c)**2), (x, 0, oo), meijerg=True)) == \
sqrt(pi)/2*(1 - erf(a + b + c))
@slow
def test_meijerint():
from sympy.core.function import expand
from sympy.core.symbol import symbols
s, t, mu = symbols('s t mu', real=True)
assert integrate(meijerg([], [], [0], [], s*t)
*meijerg([], [], [mu/2], [-mu/2], t**2/4),
(t, 0, oo)).is_Piecewise
s = symbols('s', positive=True)
assert integrate(x**s*meijerg([[], []], [[0], []], x), (x, 0, oo)) == \
gamma(s + 1)
assert integrate(x**s*meijerg([[], []], [[0], []], x), (x, 0, oo),
meijerg=True) == gamma(s + 1)
assert isinstance(integrate(x**s*meijerg([[], []], [[0], []], x),
(x, 0, oo), meijerg=False),
Integral)
assert meijerint_indefinite(exp(x), x) == exp(x)
# TODO what simplifications should be done automatically?
# This tests "extra case" for antecedents_1.
a, b = symbols('a b', positive=True)
assert simplify(meijerint_definite(x**a, x, 0, b)[0]) == \
b**(a + 1)/(a + 1)
# This tests various conditions and expansions:
assert meijerint_definite((x + 1)**3*exp(-x), x, 0, oo) == (16, True)
# Again, how about simplifications?
sigma, mu = symbols('sigma mu', positive=True)
i, c = meijerint_definite(exp(-((x - mu)/(2*sigma))**2), x, 0, oo)
assert simplify(i) == sqrt(pi)*sigma*(2 - erfc(mu/(2*sigma)))
assert c == True
i, _ = meijerint_definite(exp(-mu*x)*exp(sigma*x), x, 0, oo)
# TODO it would be nice to test the condition
assert simplify(i) == 1/(mu - sigma)
# Test substitutions to change limits
assert meijerint_definite(exp(x), x, -oo, 2) == (exp(2), True)
# Note: causes a NaN in _check_antecedents
assert expand(meijerint_definite(exp(x), x, 0, I)[0]) == exp(I) - 1
assert expand(meijerint_definite(exp(-x), x, 0, x)[0]) == \
1 - exp(-exp(I*arg(x))*abs(x))
# Test -oo to oo
assert meijerint_definite(exp(-x**2), x, -oo, oo) == (sqrt(pi), True)
assert meijerint_definite(exp(-abs(x)), x, -oo, oo) == (2, True)
assert meijerint_definite(exp(-(2*x - 3)**2), x, -oo, oo) == \
(sqrt(pi)/2, True)
assert meijerint_definite(exp(-abs(2*x - 3)), x, -oo, oo) == (1, True)
assert meijerint_definite(exp(-((x - mu)/sigma)**2/2)/sqrt(2*pi*sigma**2),
x, -oo, oo) == (1, True)
assert meijerint_definite(sinc(x)**2, x, -oo, oo) == (pi, True)
# Test one of the extra conditions for 2 g-functinos
assert meijerint_definite(exp(-x)*sin(x), x, 0, oo) == (S.Half, True)
# Test a bug
def res(n):
return (1/(1 + x**2)).diff(x, n).subs(x, 1)*(-1)**n
for n in range(6):
assert integrate(exp(-x)*sin(x)*x**n, (x, 0, oo), meijerg=True) == \
res(n)
# This used to test trigexpand... now it is done by linear substitution
assert simplify(integrate(exp(-x)*sin(x + a), (x, 0, oo), meijerg=True)
) == sqrt(2)*sin(a + pi/4)/2
# Test the condition 14 from prudnikov.
# (This is besselj*besselj in disguise, to stop the product from being
# recognised in the tables.)
a, b, s = symbols('a b s')
assert meijerint_definite(meijerg([], [], [a/2], [-a/2], x/4)
*meijerg([], [], [b/2], [-b/2], x/4)*x**(s - 1), x, 0, oo
) == (
(4*2**(2*s - 2)*gamma(-2*s + 1)*gamma(a/2 + b/2 + s)
/(gamma(-a/2 + b/2 - s + 1)*gamma(a/2 - b/2 - s + 1)
*gamma(a/2 + b/2 - s + 1)),
(re(s) < 1) & (re(s) < S(1)/2) & (re(a)/2 + re(b)/2 + re(s) > 0)))
# test a bug
assert integrate(sin(x**a)*sin(x**b), (x, 0, oo), meijerg=True) == \
Integral(sin(x**a)*sin(x**b), (x, 0, oo))
# test better hyperexpand
assert integrate(exp(-x**2)*log(x), (x, 0, oo), meijerg=True) == \
(sqrt(pi)*polygamma(0, S.Half)/4).expand()
# Test hyperexpand bug.
from sympy.functions.special.gamma_functions import lowergamma
n = symbols('n', integer=True)
assert simplify(integrate(exp(-x)*x**n, x, meijerg=True)) == \
lowergamma(n + 1, x)
# Test a bug with argument 1/x
alpha = symbols('alpha', positive=True)
assert meijerint_definite((2 - x)**alpha*sin(alpha/x), x, 0, 2) == \
(sqrt(pi)*alpha*gamma(alpha + 1)*meijerg(((), (alpha/2 + S.Half,
alpha/2 + 1)), ((0, 0, S.Half), (Rational(-1, 2),)), alpha**2/16)/4, True)
# test a bug related to 3016
a, s = symbols('a s', positive=True)
assert simplify(integrate(x**s*exp(-a*x**2), (x, -oo, oo))) == \
a**(-s/2 - S.Half)*((-1)**s + 1)*gamma(s/2 + S.Half)/2
def test_bessel():
from sympy.functions.special.bessel import (besseli, besselj)
assert simplify(integrate(besselj(a, z)*besselj(b, z)/z, (z, 0, oo),
meijerg=True, conds='none')) == \
2*sin(pi*(a/2 - b/2))/(pi*(a - b)*(a + b))
assert simplify(integrate(besselj(a, z)*besselj(a, z)/z, (z, 0, oo),
meijerg=True, conds='none')) == 1/(2*a)
# TODO more orthogonality integrals
assert simplify(integrate(sin(z*x)*(x**2 - 1)**(-(y + S.Half)),
(x, 1, oo), meijerg=True, conds='none')
*2/((z/2)**y*sqrt(pi)*gamma(S.Half - y))) == \
besselj(y, z)
# Werner Rosenheinrich
# SOME INDEFINITE INTEGRALS OF BESSEL FUNCTIONS
assert integrate(x*besselj(0, x), x, meijerg=True) == x*besselj(1, x)
assert integrate(x*besseli(0, x), x, meijerg=True) == x*besseli(1, x)
# TODO can do higher powers, but come out as high order ... should they be
# reduced to order 0, 1?
assert integrate(besselj(1, x), x, meijerg=True) == -besselj(0, x)
assert integrate(besselj(1, x)**2/x, x, meijerg=True) == \
-(besselj(0, x)**2 + besselj(1, x)**2)/2
# TODO more besseli when tables are extended or recursive mellin works
assert integrate(besselj(0, x)**2/x**2, x, meijerg=True) == \
-2*x*besselj(0, x)**2 - 2*x*besselj(1, x)**2 \
+ 2*besselj(0, x)*besselj(1, x) - besselj(0, x)**2/x
assert integrate(besselj(0, x)*besselj(1, x), x, meijerg=True) == \
-besselj(0, x)**2/2
assert integrate(x**2*besselj(0, x)*besselj(1, x), x, meijerg=True) == \
x**2*besselj(1, x)**2/2
assert integrate(besselj(0, x)*besselj(1, x)/x, x, meijerg=True) == \
(x*besselj(0, x)**2 + x*besselj(1, x)**2 -
besselj(0, x)*besselj(1, x))
# TODO how does besselj(0, a*x)*besselj(0, b*x) work?
# TODO how does besselj(0, x)**2*besselj(1, x)**2 work?
# TODO sin(x)*besselj(0, x) etc come out a mess
# TODO can x*log(x)*besselj(0, x) be done?
# TODO how does besselj(1, x)*besselj(0, x+a) work?
# TODO more indefinite integrals when struve functions etc are implemented
# test a substitution
assert integrate(besselj(1, x**2)*x, x, meijerg=True) == \
-besselj(0, x**2)/2
def test_inversion():
from sympy.functions.special.bessel import besselj
from sympy.functions.special.delta_functions import Heaviside
def inv(f):
return piecewise_fold(meijerint_inversion(f, s, t))
assert inv(1/(s**2 + 1)) == sin(t)*Heaviside(t)
assert inv(s/(s**2 + 1)) == cos(t)*Heaviside(t)
assert inv(exp(-s)/s) == Heaviside(t - 1)
assert inv(1/sqrt(1 + s**2)) == besselj(0, t)*Heaviside(t)
# Test some antcedents checking.
assert meijerint_inversion(sqrt(s)/sqrt(1 + s**2), s, t) is None
assert inv(exp(s**2)) is None
assert meijerint_inversion(exp(-s**2), s, t) is None
def test_inversion_conditional_output():
from sympy.core.symbol import Symbol
from sympy.integrals.transforms import InverseLaplaceTransform
a = Symbol('a', positive=True)
F = sqrt(pi/a)*exp(-2*sqrt(a)*sqrt(s))
f = meijerint_inversion(F, s, t)
assert not f.is_Piecewise
b = Symbol('b', real=True)
F = F.subs(a, b)
f2 = meijerint_inversion(F, s, t)
assert f2.is_Piecewise
# first piece is same as f
assert f2.args[0][0] == f.subs(a, b)
# last piece is an unevaluated transform
assert f2.args[-1][1]
ILT = InverseLaplaceTransform(F, s, t, None)
assert f2.args[-1][0] == ILT or f2.args[-1][0] == ILT.as_integral
def test_inversion_exp_real_nonreal_shift():
from sympy.core.symbol import Symbol
from sympy.functions.special.delta_functions import DiracDelta
r = Symbol('r', real=True)
c = Symbol('c', extended_real=False)
a = 1 + 2*I
z = Symbol('z')
assert not meijerint_inversion(exp(r*s), s, t).is_Piecewise
assert meijerint_inversion(exp(a*s), s, t) is None
assert meijerint_inversion(exp(c*s), s, t) is None
f = meijerint_inversion(exp(z*s), s, t)
assert f.is_Piecewise
assert isinstance(f.args[0][0], DiracDelta)
@slow
def test_lookup_table():
from sympy.core.random import uniform, randrange
from sympy.core.add import Add
from sympy.integrals.meijerint import z as z_dummy
table = {}
_create_lookup_table(table)
for l in table.values():
for formula, terms, cond, hint in sorted(l, key=default_sort_key):
subs = {}
for ai in list(formula.free_symbols) + [z_dummy]:
if hasattr(ai, 'properties') and ai.properties:
# these Wilds match positive integers
subs[ai] = randrange(1, 10)
else:
subs[ai] = uniform(1.5, 2.0)
if not isinstance(terms, list):
terms = terms(subs)
# First test that hyperexpand can do this.
expanded = [hyperexpand(g) for (_, g) in terms]
assert all(x.is_Piecewise or not x.has(meijerg) for x in expanded)
# Now test that the meijer g-function is indeed as advertised.
expanded = Add(*[f*x for (f, x) in terms])
a, b = formula.n(subs=subs), expanded.n(subs=subs)
r = min(abs(a), abs(b))
if r < 1:
assert abs(a - b).n() <= 1e-10
else:
assert (abs(a - b)/r).n() <= 1e-10
def test_branch_bug():
from sympy.functions.special.gamma_functions import lowergamma
from sympy.simplify.powsimp import powdenest
# TODO gammasimp cannot prove that the factor is unity
assert powdenest(integrate(erf(x**3), x, meijerg=True).diff(x),
polar=True) == 2*erf(x**3)*gamma(Rational(2, 3))/3/gamma(Rational(5, 3))
assert integrate(erf(x**3), x, meijerg=True) == \
2*x*erf(x**3)*gamma(Rational(2, 3))/(3*gamma(Rational(5, 3))) \
- 2*gamma(Rational(2, 3))*lowergamma(Rational(2, 3), x**6)/(3*sqrt(pi)*gamma(Rational(5, 3)))
def test_linear_subs():
from sympy.functions.special.bessel import besselj
assert integrate(sin(x - 1), x, meijerg=True) == -cos(1 - x)
assert integrate(besselj(1, x - 1), x, meijerg=True) == -besselj(0, 1 - x)
@slow
def test_probability():
# various integrals from probability theory
from sympy.core.function import expand_mul
from sympy.core.symbol import (Symbol, symbols)
from sympy.simplify.gammasimp import gammasimp
from sympy.simplify.powsimp import powsimp
mu1, mu2 = symbols('mu1 mu2', nonzero=True)
sigma1, sigma2 = symbols('sigma1 sigma2', positive=True)
rate = Symbol('lambda', positive=True)
def normal(x, mu, sigma):
return 1/sqrt(2*pi*sigma**2)*exp(-(x - mu)**2/2/sigma**2)
def exponential(x, rate):
return rate*exp(-rate*x)
assert integrate(normal(x, mu1, sigma1), (x, -oo, oo), meijerg=True) == 1
assert integrate(x*normal(x, mu1, sigma1), (x, -oo, oo), meijerg=True) == \
mu1
assert integrate(x**2*normal(x, mu1, sigma1), (x, -oo, oo), meijerg=True) \
== mu1**2 + sigma1**2
assert integrate(x**3*normal(x, mu1, sigma1), (x, -oo, oo), meijerg=True) \
== mu1**3 + 3*mu1*sigma1**2
assert integrate(normal(x, mu1, sigma1)*normal(y, mu2, sigma2),
(x, -oo, oo), (y, -oo, oo), meijerg=True) == 1
assert integrate(x*normal(x, mu1, sigma1)*normal(y, mu2, sigma2),
(x, -oo, oo), (y, -oo, oo), meijerg=True) == mu1
assert integrate(y*normal(x, mu1, sigma1)*normal(y, mu2, sigma2),
(x, -oo, oo), (y, -oo, oo), meijerg=True) == mu2
assert integrate(x*y*normal(x, mu1, sigma1)*normal(y, mu2, sigma2),
(x, -oo, oo), (y, -oo, oo), meijerg=True) == mu1*mu2
assert integrate((x + y + 1)*normal(x, mu1, sigma1)*normal(y, mu2, sigma2),
(x, -oo, oo), (y, -oo, oo), meijerg=True) == 1 + mu1 + mu2
assert integrate((x + y - 1)*normal(x, mu1, sigma1)*normal(y, mu2, sigma2),
(x, -oo, oo), (y, -oo, oo), meijerg=True) == \
-1 + mu1 + mu2
i = integrate(x**2*normal(x, mu1, sigma1)*normal(y, mu2, sigma2),
(x, -oo, oo), (y, -oo, oo), meijerg=True)
assert not i.has(Abs)
assert simplify(i) == mu1**2 + sigma1**2
assert integrate(y**2*normal(x, mu1, sigma1)*normal(y, mu2, sigma2),
(x, -oo, oo), (y, -oo, oo), meijerg=True) == \
sigma2**2 + mu2**2
assert integrate(exponential(x, rate), (x, 0, oo), meijerg=True) == 1
assert integrate(x*exponential(x, rate), (x, 0, oo), meijerg=True) == \
1/rate
assert integrate(x**2*exponential(x, rate), (x, 0, oo), meijerg=True) == \
2/rate**2
def E(expr):
res1 = integrate(expr*exponential(x, rate)*normal(y, mu1, sigma1),
(x, 0, oo), (y, -oo, oo), meijerg=True)
res2 = integrate(expr*exponential(x, rate)*normal(y, mu1, sigma1),
(y, -oo, oo), (x, 0, oo), meijerg=True)
assert expand_mul(res1) == expand_mul(res2)
return res1
assert E(1) == 1
assert E(x*y) == mu1/rate
assert E(x*y**2) == mu1**2/rate + sigma1**2/rate
ans = sigma1**2 + 1/rate**2
assert simplify(E((x + y + 1)**2) - E(x + y + 1)**2) == ans
assert simplify(E((x + y - 1)**2) - E(x + y - 1)**2) == ans
assert simplify(E((x + y)**2) - E(x + y)**2) == ans
# Beta' distribution
alpha, beta = symbols('alpha beta', positive=True)
betadist = x**(alpha - 1)*(1 + x)**(-alpha - beta)*gamma(alpha + beta) \
/gamma(alpha)/gamma(beta)
assert integrate(betadist, (x, 0, oo), meijerg=True) == 1
i = integrate(x*betadist, (x, 0, oo), meijerg=True, conds='separate')
assert (gammasimp(i[0]), i[1]) == (alpha/(beta - 1), 1 < beta)
j = integrate(x**2*betadist, (x, 0, oo), meijerg=True, conds='separate')
assert j[1] == (beta > 2)
assert gammasimp(j[0] - i[0]**2) == (alpha + beta - 1)*alpha \
/(beta - 2)/(beta - 1)**2
# Beta distribution
# NOTE: this is evaluated using antiderivatives. It also tests that
# meijerint_indefinite returns the simplest possible answer.
a, b = symbols('a b', positive=True)
betadist = x**(a - 1)*(-x + 1)**(b - 1)*gamma(a + b)/(gamma(a)*gamma(b))
assert simplify(integrate(betadist, (x, 0, 1), meijerg=True)) == 1
assert simplify(integrate(x*betadist, (x, 0, 1), meijerg=True)) == \
a/(a + b)
assert simplify(integrate(x**2*betadist, (x, 0, 1), meijerg=True)) == \
a*(a + 1)/(a + b)/(a + b + 1)
assert simplify(integrate(x**y*betadist, (x, 0, 1), meijerg=True)) == \
gamma(a + b)*gamma(a + y)/gamma(a)/gamma(a + b + y)
# Chi distribution
k = Symbol('k', integer=True, positive=True)
chi = 2**(1 - k/2)*x**(k - 1)*exp(-x**2/2)/gamma(k/2)
assert powsimp(integrate(chi, (x, 0, oo), meijerg=True)) == 1
assert simplify(integrate(x*chi, (x, 0, oo), meijerg=True)) == \
sqrt(2)*gamma((k + 1)/2)/gamma(k/2)
assert simplify(integrate(x**2*chi, (x, 0, oo), meijerg=True)) == k
# Chi^2 distribution
chisquared = 2**(-k/2)/gamma(k/2)*x**(k/2 - 1)*exp(-x/2)
assert powsimp(integrate(chisquared, (x, 0, oo), meijerg=True)) == 1
assert simplify(integrate(x*chisquared, (x, 0, oo), meijerg=True)) == k
assert simplify(integrate(x**2*chisquared, (x, 0, oo), meijerg=True)) == \
k*(k + 2)
assert gammasimp(integrate(((x - k)/sqrt(2*k))**3*chisquared, (x, 0, oo),
meijerg=True)) == 2*sqrt(2)/sqrt(k)
# Dagum distribution
a, b, p = symbols('a b p', positive=True)
# XXX (x/b)**a does not work
dagum = a*p/x*(x/b)**(a*p)/(1 + x**a/b**a)**(p + 1)
assert simplify(integrate(dagum, (x, 0, oo), meijerg=True)) == 1
# XXX conditions are a mess
arg = x*dagum
assert simplify(integrate(arg, (x, 0, oo), meijerg=True, conds='none')
) == a*b*gamma(1 - 1/a)*gamma(p + 1 + 1/a)/(
(a*p + 1)*gamma(p))
assert simplify(integrate(x*arg, (x, 0, oo), meijerg=True, conds='none')
) == a*b**2*gamma(1 - 2/a)*gamma(p + 1 + 2/a)/(
(a*p + 2)*gamma(p))
# F-distribution
d1, d2 = symbols('d1 d2', positive=True)
f = sqrt(((d1*x)**d1 * d2**d2)/(d1*x + d2)**(d1 + d2))/x \
/gamma(d1/2)/gamma(d2/2)*gamma((d1 + d2)/2)
assert simplify(integrate(f, (x, 0, oo), meijerg=True)) == 1
# TODO conditions are a mess
assert simplify(integrate(x*f, (x, 0, oo), meijerg=True, conds='none')
) == d2/(d2 - 2)
assert simplify(integrate(x**2*f, (x, 0, oo), meijerg=True, conds='none')
) == d2**2*(d1 + 2)/d1/(d2 - 4)/(d2 - 2)
# TODO gamma, rayleigh
# inverse gaussian
lamda, mu = symbols('lamda mu', positive=True)
dist = sqrt(lamda/2/pi)*x**(Rational(-3, 2))*exp(-lamda*(x - mu)**2/x/2/mu**2)
mysimp = lambda expr: simplify(expr.rewrite(exp))
assert mysimp(integrate(dist, (x, 0, oo))) == 1
assert mysimp(integrate(x*dist, (x, 0, oo))) == mu
assert mysimp(integrate((x - mu)**2*dist, (x, 0, oo))) == mu**3/lamda
assert mysimp(integrate((x - mu)**3*dist, (x, 0, oo))) == 3*mu**5/lamda**2
# Levi
c = Symbol('c', positive=True)
assert integrate(sqrt(c/2/pi)*exp(-c/2/(x - mu))/(x - mu)**S('3/2'),
(x, mu, oo)) == 1
# higher moments oo
# log-logistic
alpha, beta = symbols('alpha beta', positive=True)
distn = (beta/alpha)*x**(beta - 1)/alpha**(beta - 1)/ \
(1 + x**beta/alpha**beta)**2
# FIXME: If alpha, beta are not declared as finite the line below hangs
# after the changes in:
# https://github.com/sympy/sympy/pull/16603
assert simplify(integrate(distn, (x, 0, oo))) == 1
# NOTE the conditions are a mess, but correctly state beta > 1
assert simplify(integrate(x*distn, (x, 0, oo), conds='none')) == \
pi*alpha/beta/sin(pi/beta)
# (similar comment for conditions applies)
assert simplify(integrate(x**y*distn, (x, 0, oo), conds='none')) == \
pi*alpha**y*y/beta/sin(pi*y/beta)
# weibull
k = Symbol('k', positive=True)
n = Symbol('n', positive=True)
distn = k/lamda*(x/lamda)**(k - 1)*exp(-(x/lamda)**k)
assert simplify(integrate(distn, (x, 0, oo))) == 1
assert simplify(integrate(x**n*distn, (x, 0, oo))) == \
lamda**n*gamma(1 + n/k)
# rice distribution
from sympy.functions.special.bessel import besseli
nu, sigma = symbols('nu sigma', positive=True)
rice = x/sigma**2*exp(-(x**2 + nu**2)/2/sigma**2)*besseli(0, x*nu/sigma**2)
assert integrate(rice, (x, 0, oo), meijerg=True) == 1
# can someone verify higher moments?
# Laplace distribution
mu = Symbol('mu', real=True)
b = Symbol('b', positive=True)
laplace = exp(-abs(x - mu)/b)/2/b
assert integrate(laplace, (x, -oo, oo), meijerg=True) == 1
assert integrate(x*laplace, (x, -oo, oo), meijerg=True) == mu
assert integrate(x**2*laplace, (x, -oo, oo), meijerg=True) == \
2*b**2 + mu**2
# TODO are there other distributions supported on (-oo, oo) that we can do?
# misc tests
k = Symbol('k', positive=True)
assert gammasimp(expand_mul(integrate(log(x)*x**(k - 1)*exp(-x)/gamma(k),
(x, 0, oo)))) == polygamma(0, k)
@slow
def test_expint():
""" Test various exponential integrals. """
from sympy.core.symbol import Symbol
from sympy.functions.elementary.hyperbolic import sinh
from sympy.functions.special.error_functions import (Chi, Ci, Ei, Shi, Si, expint)
assert simplify(unpolarify(integrate(exp(-z*x)/x**y, (x, 1, oo),
meijerg=True, conds='none'
).rewrite(expint).expand(func=True))) == expint(y, z)
assert integrate(exp(-z*x)/x, (x, 1, oo), meijerg=True,
conds='none').rewrite(expint).expand() == \
expint(1, z)
assert integrate(exp(-z*x)/x**2, (x, 1, oo), meijerg=True,
conds='none').rewrite(expint).expand() == \
expint(2, z).rewrite(Ei).rewrite(expint)
assert integrate(exp(-z*x)/x**3, (x, 1, oo), meijerg=True,
conds='none').rewrite(expint).expand() == \
expint(3, z).rewrite(Ei).rewrite(expint).expand()
t = Symbol('t', positive=True)
assert integrate(-cos(x)/x, (x, t, oo), meijerg=True).expand() == Ci(t)
assert integrate(-sin(x)/x, (x, t, oo), meijerg=True).expand() == \
Si(t) - pi/2
assert integrate(sin(x)/x, (x, 0, z), meijerg=True) == Si(z)
assert integrate(sinh(x)/x, (x, 0, z), meijerg=True) == Shi(z)
assert integrate(exp(-x)/x, x, meijerg=True).expand().rewrite(expint) == \
I*pi - expint(1, x)
assert integrate(exp(-x)/x**2, x, meijerg=True).rewrite(expint).expand() \
== expint(1, x) - exp(-x)/x - I*pi
u = Symbol('u', polar=True)
assert integrate(cos(u)/u, u, meijerg=True).expand().as_independent(u)[1] \
== Ci(u)
assert integrate(cosh(u)/u, u, meijerg=True).expand().as_independent(u)[1] \
== Chi(u)
assert integrate(expint(1, x), x, meijerg=True
).rewrite(expint).expand() == x*expint(1, x) - exp(-x)
assert integrate(expint(2, x), x, meijerg=True
).rewrite(expint).expand() == \
-x**2*expint(1, x)/2 + x*exp(-x)/2 - exp(-x)/2
assert simplify(unpolarify(integrate(expint(y, x), x,
meijerg=True).rewrite(expint).expand(func=True))) == \
-expint(y + 1, x)
assert integrate(Si(x), x, meijerg=True) == x*Si(x) + cos(x)
assert integrate(Ci(u), u, meijerg=True).expand() == u*Ci(u) - sin(u)
assert integrate(Shi(x), x, meijerg=True) == x*Shi(x) - cosh(x)
assert integrate(Chi(u), u, meijerg=True).expand() == u*Chi(u) - sinh(u)
assert integrate(Si(x)*exp(-x), (x, 0, oo), meijerg=True) == pi/4
assert integrate(expint(1, x)*sin(x), (x, 0, oo), meijerg=True) == log(2)/2
def test_messy():
from sympy.functions.elementary.hyperbolic import (acosh, acoth)
from sympy.functions.elementary.trigonometric import (asin, atan)
from sympy.functions.special.bessel import besselj
from sympy.functions.special.error_functions import (Chi, E1, Shi, Si)
from sympy.integrals.transforms import (fourier_transform, laplace_transform)
assert (laplace_transform(Si(x), x, s, simplify=True) ==
((-atan(s) + pi/2)/s, 0, True))
assert laplace_transform(Shi(x), x, s, simplify=True) == (
acoth(s)/s, -oo, s**2 > 1)
# where should the logs be simplified?
assert laplace_transform(Chi(x), x, s, simplify=True) == (
(log(s**(-2)) - log(1 - 1/s**2))/(2*s), -oo, s**2 > 1)
# TODO maybe simplify the inequalities? when the simplification
# allows for generators instead of symbols this will work
assert laplace_transform(besselj(a, x), x, s)[1:] == \
(0, (re(a) > -2) & (re(a) > -1))
# NOTE s < 0 can be done, but argument reduction is not good enough yet
ans = fourier_transform(besselj(1, x)/x, x, s, noconds=False)
assert (ans[0].factor(deep=True).expand(), ans[1]) == \
(Piecewise((0, (s > 1/(2*pi)) | (s < -1/(2*pi))),
(2*sqrt(-4*pi**2*s**2 + 1), True)), s > 0)
# TODO FT(besselj(0,x)) - conditions are messy (but for acceptable reasons)
# - folding could be better
assert integrate(E1(x)*besselj(0, x), (x, 0, oo), meijerg=True) == \
log(1 + sqrt(2))
assert integrate(E1(x)*besselj(1, x), (x, 0, oo), meijerg=True) == \
log(S.Half + sqrt(2)/2)
assert integrate(1/x/sqrt(1 - x**2), x, meijerg=True) == \
Piecewise((-acosh(1/x), abs(x**(-2)) > 1), (I*asin(1/x), True))
def test_issue_6122():
assert integrate(exp(-I*x**2), (x, -oo, oo), meijerg=True) == \
-I*sqrt(pi)*exp(I*pi/4)
def test_issue_6252():
expr = 1/x/(a + b*x)**Rational(1, 3)
anti = integrate(expr, x, meijerg=True)
assert not anti.has(hyper)
# XXX the expression is a mess, but actually upon differentiation and
# putting in numerical values seems to work...
def test_issue_6348():
assert integrate(exp(I*x)/(1 + x**2), (x, -oo, oo)).simplify().rewrite(exp) \
== pi*exp(-1)
def test_fresnel():
from sympy.functions.special.error_functions import (fresnelc, fresnels)
assert expand_func(integrate(sin(pi*x**2/2), x)) == fresnels(x)
assert expand_func(integrate(cos(pi*x**2/2), x)) == fresnelc(x)
def test_issue_6860():
assert meijerint_indefinite(x**x**x, x) is None
def test_issue_7337():
f = meijerint_indefinite(x*sqrt(2*x + 3), x).together()
assert f == sqrt(2*x + 3)*(2*x**2 + x - 3)/5
assert f._eval_interval(x, S.NegativeOne, S.One) == Rational(2, 5)
def test_issue_8368():
assert meijerint_indefinite(cosh(x)*exp(-x*t), x) == (
(-t - 1)*exp(x) + (-t + 1)*exp(-x))*exp(-t*x)/2/(t**2 - 1)
def test_issue_10211():
from sympy.abc import h, w
assert integrate((1/sqrt((y-x)**2 + h**2)**3), (x,0,w), (y,0,w)) == \
2*sqrt(1 + w**2/h**2)/h - 2/h
def test_issue_11806():
from sympy.core.symbol import symbols
y, L = symbols('y L', positive=True)
assert integrate(1/sqrt(x**2 + y**2)**3, (x, -L, L)) == \
2*L/(y**2*sqrt(L**2 + y**2))
def test_issue_10681():
from sympy.polys.domains.realfield import RR
from sympy.abc import R, r
f = integrate(r**2*(R**2-r**2)**0.5, r, meijerg=True)
g = (1.0/3)*R**1.0*r**3*hyper((-0.5, Rational(3, 2)), (Rational(5, 2),),
r**2*exp_polar(2*I*pi)/R**2)
assert RR.almosteq((f/g).n(), 1.0, 1e-12)
def test_issue_13536():
from sympy.core.symbol import Symbol
a = Symbol('a', positive=True)
assert integrate(1/x**2, (x, oo, a)) == -1/a
def test_issue_6462():
from sympy.core.symbol import Symbol
x = Symbol('x')
n = Symbol('n')
# Not the actual issue, still wrong answer for n = 1, but that there is no
# exception
assert integrate(cos(x**n)/x**n, x, meijerg=True).subs(n, 2).equals(
integrate(cos(x**2)/x**2, x, meijerg=True))
def test_indefinite_1_bug():
assert integrate((b + t)**(-a), t, meijerg=True) == -b*(1 + t/b)**(1 - a)/(a*b**a - b**a)
def test_pr_23583():
# This result is wrong. Check whether new result is correct when this test fail.
assert integrate(1/sqrt((x - I)**2-1), meijerg=True) == \
Piecewise((acosh(x - I), Abs((x - I)**2) > 1), (-I*asin(x - I), True))
# 25786
def test_integrate_function_of_square_over_negatives():
assert integrate(exp(-x**2), (x,-5,0), meijerg=True) == sqrt(pi)/2 * erf(5)
def test_issue_25949():
from sympy.core.symbol import symbols
y = symbols("y", nonzero=True)
assert integrate(cosh(y*(x + 1)), (x, -1, -0.25), meijerg=True) == sinh(0.75*y)/y

View File

@ -0,0 +1,322 @@
"""Most of these tests come from the examples in Bronstein's book."""
from sympy.integrals.risch import DifferentialExtension, derivation
from sympy.integrals.prde import (prde_normal_denom, prde_special_denom,
prde_linear_constraints, constant_system, prde_spde, prde_no_cancel_b_large,
prde_no_cancel_b_small, limited_integrate_reduce, limited_integrate,
is_deriv_k, is_log_deriv_k_t_radical, parametric_log_deriv_heu,
is_log_deriv_k_t_radical_in_field, param_poly_rischDE, param_rischDE,
prde_cancel_liouvillian)
from sympy.polys.polymatrix import PolyMatrix as Matrix
from sympy.core.numbers import Rational
from sympy.core.singleton import S
from sympy.core.symbol import symbols
from sympy.polys.domains.rationalfield import QQ
from sympy.polys.polytools import Poly
from sympy.abc import x, t, n
t0, t1, t2, t3, k = symbols('t:4 k')
def test_prde_normal_denom():
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1 + t**2, t)]})
fa = Poly(1, t)
fd = Poly(x, t)
G = [(Poly(t, t), Poly(1 + t**2, t)), (Poly(1, t), Poly(x + x*t**2, t))]
assert prde_normal_denom(fa, fd, G, DE) == \
(Poly(x, t, domain='ZZ(x)'), (Poly(1, t, domain='ZZ(x)'), Poly(1, t,
domain='ZZ(x)')), [(Poly(x*t, t, domain='ZZ(x)'),
Poly(t**2 + 1, t, domain='ZZ(x)')), (Poly(1, t, domain='ZZ(x)'),
Poly(t**2 + 1, t, domain='ZZ(x)'))], Poly(1, t, domain='ZZ(x)'))
G = [(Poly(t, t), Poly(t**2 + 2*t + 1, t)), (Poly(x*t, t),
Poly(t**2 + 2*t + 1, t)), (Poly(x*t**2, t), Poly(t**2 + 2*t + 1, t))]
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]})
assert prde_normal_denom(Poly(x, t), Poly(1, t), G, DE) == \
(Poly(t + 1, t), (Poly((-1 + x)*t + x, t), Poly(1, t, domain='ZZ[x]')), [(Poly(t, t),
Poly(1, t)), (Poly(x*t, t), Poly(1, t, domain='ZZ[x]')), (Poly(x*t**2, t),
Poly(1, t, domain='ZZ[x]'))], Poly(t + 1, t))
def test_prde_special_denom():
a = Poly(t + 1, t)
ba = Poly(t**2, t)
bd = Poly(1, t)
G = [(Poly(t, t), Poly(1, t)), (Poly(t**2, t), Poly(1, t)), (Poly(t**3, t), Poly(1, t))]
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]})
assert prde_special_denom(a, ba, bd, G, DE) == \
(Poly(t + 1, t), Poly(t**2, t), [(Poly(t, t), Poly(1, t)),
(Poly(t**2, t), Poly(1, t)), (Poly(t**3, t), Poly(1, t))], Poly(1, t))
G = [(Poly(t, t), Poly(1, t)), (Poly(1, t), Poly(t, t))]
assert prde_special_denom(Poly(1, t), Poly(t**2, t), Poly(1, t), G, DE) == \
(Poly(1, t), Poly(t**2 - 1, t), [(Poly(t**2, t), Poly(1, t)),
(Poly(1, t), Poly(1, t))], Poly(t, t))
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(-2*x*t0, t0)]})
DE.decrement_level()
G = [(Poly(t, t), Poly(t**2, t)), (Poly(2*t, t), Poly(t, t))]
assert prde_special_denom(Poly(5*x*t + 1, t), Poly(t**2 + 2*x**3*t, t), Poly(t**3 + 2, t), G, DE) == \
(Poly(5*x*t + 1, t), Poly(0, t, domain='ZZ[x]'), [(Poly(t, t), Poly(t**2, t)),
(Poly(2*t, t), Poly(t, t))], Poly(1, x))
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly((t**2 + 1)*2*x, t)]})
G = [(Poly(t + x, t), Poly(t*x, t)), (Poly(2*t, t), Poly(x**2, x))]
assert prde_special_denom(Poly(5*x*t + 1, t), Poly(t**2 + 2*x**3*t, t), Poly(t**3, t), G, DE) == \
(Poly(5*x*t + 1, t), Poly(0, t, domain='ZZ[x]'), [(Poly(t + x, t), Poly(x*t, t)),
(Poly(2*t, t, x), Poly(x**2, t, x))], Poly(1, t))
assert prde_special_denom(Poly(t + 1, t), Poly(t**2, t), Poly(t**3, t), G, DE) == \
(Poly(t + 1, t), Poly(0, t, domain='ZZ[x]'), [(Poly(t + x, t), Poly(x*t, t)), (Poly(2*t, t, x),
Poly(x**2, t, x))], Poly(1, t))
def test_prde_linear_constraints():
DE = DifferentialExtension(extension={'D': [Poly(1, x)]})
G = [(Poly(2*x**3 + 3*x + 1, x), Poly(x**2 - 1, x)), (Poly(1, x), Poly(x - 1, x)),
(Poly(1, x), Poly(x + 1, x))]
assert prde_linear_constraints(Poly(1, x), Poly(0, x), G, DE) == \
((Poly(2*x, x, domain='QQ'), Poly(0, x, domain='QQ'), Poly(0, x, domain='QQ')),
Matrix([[1, 1, -1], [5, 1, 1]], x))
G = [(Poly(t, t), Poly(1, t)), (Poly(t**2, t), Poly(1, t)), (Poly(t**3, t), Poly(1, t))]
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]})
assert prde_linear_constraints(Poly(t + 1, t), Poly(t**2, t), G, DE) == \
((Poly(t, t, domain='QQ'), Poly(t**2, t, domain='QQ'), Poly(t**3, t, domain='QQ')),
Matrix(0, 3, [], t))
G = [(Poly(2*x, t), Poly(t, t)), (Poly(-x, t), Poly(t, t))]
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]})
assert prde_linear_constraints(Poly(1, t), Poly(0, t), G, DE) == \
((Poly(0, t, domain='QQ[x]'), Poly(0, t, domain='QQ[x]')), Matrix([[2*x, -x]], t))
def test_constant_system():
A = Matrix([[-(x + 3)/(x - 1), (x + 1)/(x - 1), 1],
[-x - 3, x + 1, x - 1],
[2*(x + 3)/(x - 1), 0, 0]], t)
u = Matrix([[(x + 1)/(x - 1)], [x + 1], [0]], t)
DE = DifferentialExtension(extension={'D': [Poly(1, x)]})
R = QQ.frac_field(x)[t]
assert constant_system(A, u, DE) == \
(Matrix([[1, 0, 0],
[0, 1, 0],
[0, 0, 0],
[0, 0, 1]], ring=R), Matrix([0, 1, 0, 0], ring=R))
def test_prde_spde():
D = [Poly(x, t), Poly(-x*t, t)]
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]})
# TODO: when bound_degree() can handle this, test degree bound from that too
assert prde_spde(Poly(t, t), Poly(-1/x, t), D, n, DE) == \
(Poly(t, t), Poly(0, t, domain='ZZ(x)'),
[Poly(2*x, t, domain='ZZ(x)'), Poly(-x, t, domain='ZZ(x)')],
[Poly(-x**2, t, domain='ZZ(x)'), Poly(0, t, domain='ZZ(x)')], n - 1)
def test_prde_no_cancel():
# b large
DE = DifferentialExtension(extension={'D': [Poly(1, x)]})
assert prde_no_cancel_b_large(Poly(1, x), [Poly(x**2, x), Poly(1, x)], 2, DE) == \
([Poly(x**2 - 2*x + 2, x), Poly(1, x)], Matrix([[1, 0, -1, 0],
[0, 1, 0, -1]], x))
assert prde_no_cancel_b_large(Poly(1, x), [Poly(x**3, x), Poly(1, x)], 3, DE) == \
([Poly(x**3 - 3*x**2 + 6*x - 6, x), Poly(1, x)], Matrix([[1, 0, -1, 0],
[0, 1, 0, -1]], x))
assert prde_no_cancel_b_large(Poly(x, x), [Poly(x**2, x), Poly(1, x)], 1, DE) == \
([Poly(x, x, domain='ZZ'), Poly(0, x, domain='ZZ')], Matrix([[1, -1, 0, 0],
[1, 0, -1, 0],
[0, 1, 0, -1]], x))
# b small
# XXX: Is there a better example of a monomial with D.degree() > 2?
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t**3 + 1, t)]})
# My original q was t**4 + t + 1, but this solution implies q == t**4
# (c1 = 4), with some of the ci for the original q equal to 0.
G = [Poly(t**6, t), Poly(x*t**5, t), Poly(t**3, t), Poly(x*t**2, t), Poly(1 + x, t)]
R = QQ.frac_field(x)[t]
assert prde_no_cancel_b_small(Poly(x*t, t), G, 4, DE) == \
([Poly(t**4/4 - x/12*t**3 + x**2/24*t**2 + (Rational(-11, 12) - x**3/24)*t + x/24, t),
Poly(x/3*t**3 - x**2/6*t**2 + (Rational(-1, 3) + x**3/6)*t - x/6, t), Poly(t, t),
Poly(0, t), Poly(0, t)], Matrix([[1, 0, -1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, Rational(-1, 4), 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 0, -1, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, -1, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, -1, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0, -1, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, -1]], ring=R))
# TODO: Add test for deg(b) <= 0 with b small
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1 + t**2, t)]})
b = Poly(-1/x**2, t, field=True) # deg(b) == 0
q = [Poly(x**i*t**j, t, field=True) for i in range(2) for j in range(3)]
h, A = prde_no_cancel_b_small(b, q, 3, DE)
V = A.nullspace()
R = QQ.frac_field(x)[t]
assert len(V) == 1
assert V[0] == Matrix([Rational(-1, 2), 0, 0, 1, 0, 0]*3, ring=R)
assert (Matrix([h])*V[0][6:, :])[0] == Poly(x**2/2, t, domain='QQ(x)')
assert (Matrix([q])*V[0][:6, :])[0] == Poly(x - S.Half, t, domain='QQ(x)')
def test_prde_cancel_liouvillian():
### 1. case == 'primitive'
# used when integrating f = log(x) - log(x - 1)
# Not taken from 'the' book
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]})
p0 = Poly(0, t, field=True)
p1 = Poly((x - 1)*t, t, domain='ZZ(x)')
p2 = Poly(x - 1, t, domain='ZZ(x)')
p3 = Poly(-x**2 + x, t, domain='ZZ(x)')
h, A = prde_cancel_liouvillian(Poly(-1/(x - 1), t), [Poly(-x + 1, t), Poly(1, t)], 1, DE)
V = A.nullspace()
assert h == [p0, p0, p1, p0, p0, p0, p0, p0, p0, p0, p2, p3, p0, p0, p0, p0]
assert A.rank() == 16
assert (Matrix([h])*V[0][:16, :]) == Matrix([[Poly(0, t, domain='QQ(x)')]])
### 2. case == 'exp'
# used when integrating log(x/exp(x) + 1)
# Not taken from book
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(-t, t)]})
assert prde_cancel_liouvillian(Poly(0, t, domain='QQ[x]'), [Poly(1, t, domain='QQ(x)')], 0, DE) == \
([Poly(1, t, domain='QQ'), Poly(x, t, domain='ZZ(x)')], Matrix([[-1, 0, 1]], DE.t))
def test_param_poly_rischDE():
DE = DifferentialExtension(extension={'D': [Poly(1, x)]})
a = Poly(x**2 - x, x, field=True)
b = Poly(1, x, field=True)
q = [Poly(x, x, field=True), Poly(x**2, x, field=True)]
h, A = param_poly_rischDE(a, b, q, 3, DE)
assert A.nullspace() == [Matrix([0, 1, 1, 1], DE.t)] # c1, c2, d1, d2
# Solution of a*Dp + b*p = c1*q1 + c2*q2 = q2 = x**2
# is d1*h1 + d2*h2 = h1 + h2 = x.
assert h[0] + h[1] == Poly(x, x, domain='QQ')
# a*Dp + b*p = q1 = x has no solution.
a = Poly(x**2 - x, x, field=True)
b = Poly(x**2 - 5*x + 3, x, field=True)
q = [Poly(1, x, field=True), Poly(x, x, field=True),
Poly(x**2, x, field=True)]
h, A = param_poly_rischDE(a, b, q, 3, DE)
assert A.nullspace() == [Matrix([3, -5, 1, -5, 1, 1], DE.t)]
p = -Poly(5, DE.t)*h[0] + h[1] + h[2] # Poly(1, x)
assert a*derivation(p, DE) + b*p == Poly(x**2 - 5*x + 3, x, domain='QQ')
def test_param_rischDE():
DE = DifferentialExtension(extension={'D': [Poly(1, x)]})
p1, px = Poly(1, x, field=True), Poly(x, x, field=True)
G = [(p1, px), (p1, p1), (px, p1)] # [1/x, 1, x]
h, A = param_rischDE(-p1, Poly(x**2, x, field=True), G, DE)
assert len(h) == 3
p = [hi[0].as_expr()/hi[1].as_expr() for hi in h]
V = A.nullspace()
assert len(V) == 2
assert V[0] == Matrix([-1, 1, 0, -1, 1, 0], DE.t)
y = -p[0] + p[1] + 0*p[2] # x
assert y.diff(x) - y/x**2 == 1 - 1/x # Dy + f*y == -G0 + G1 + 0*G2
# the below test computation takes place while computing the integral
# of 'f = log(log(x + exp(x)))'
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]})
G = [(Poly(t + x, t, domain='ZZ(x)'), Poly(1, t, domain='QQ')), (Poly(0, t, domain='QQ'), Poly(1, t, domain='QQ'))]
h, A = param_rischDE(Poly(-t - 1, t, field=True), Poly(t + x, t, field=True), G, DE)
assert len(h) == 5
p = [hi[0].as_expr()/hi[1].as_expr() for hi in h]
V = A.nullspace()
assert len(V) == 3
assert V[0] == Matrix([0, 0, 0, 0, 1, 0, 0], DE.t)
y = 0*p[0] + 0*p[1] + 1*p[2] + 0*p[3] + 0*p[4]
assert y.diff(t) - y/(t + x) == 0 # Dy + f*y = 0*G0 + 0*G1
def test_limited_integrate_reduce():
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]})
assert limited_integrate_reduce(Poly(x, t), Poly(t**2, t), [(Poly(x, t),
Poly(t, t))], DE) == \
(Poly(t, t), Poly(-1/x, t), Poly(t, t), 1, (Poly(x, t), Poly(1, t, domain='ZZ[x]')),
[(Poly(-x*t, t), Poly(1, t, domain='ZZ[x]'))])
def test_limited_integrate():
DE = DifferentialExtension(extension={'D': [Poly(1, x)]})
G = [(Poly(x, x), Poly(x + 1, x))]
assert limited_integrate(Poly(-(1 + x + 5*x**2 - 3*x**3), x),
Poly(1 - x - x**2 + x**3, x), G, DE) == \
((Poly(x**2 - x + 2, x), Poly(x - 1, x, domain='QQ')), [2])
G = [(Poly(1, x), Poly(x, x))]
assert limited_integrate(Poly(5*x**2, x), Poly(3, x), G, DE) == \
((Poly(5*x**3/9, x), Poly(1, x, domain='QQ')), [0])
def test_is_log_deriv_k_t_radical():
DE = DifferentialExtension(extension={'D': [Poly(1, x)], 'exts': [None],
'extargs': [None]})
assert is_log_deriv_k_t_radical(Poly(2*x, x), Poly(1, x), DE) is None
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(2*t1, t1), Poly(1/x, t2)],
'exts': [None, 'exp', 'log'], 'extargs': [None, 2*x, x]})
assert is_log_deriv_k_t_radical(Poly(x + t2/2, t2), Poly(1, t2), DE) == \
([(t1, 1), (x, 1)], t1*x, 2, 0)
# TODO: Add more tests
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t0, t0), Poly(1/x, t)],
'exts': [None, 'exp', 'log'], 'extargs': [None, x, x]})
assert is_log_deriv_k_t_radical(Poly(x + t/2 + 3, t), Poly(1, t), DE) == \
([(t0, 2), (x, 1)], x*t0**2, 2, 3)
def test_is_deriv_k():
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t1), Poly(1/(x + 1), t2)],
'exts': [None, 'log', 'log'], 'extargs': [None, x, x + 1]})
assert is_deriv_k(Poly(2*x**2 + 2*x, t2), Poly(1, t2), DE) == \
([(t1, 1), (t2, 1)], t1 + t2, 2)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t1), Poly(t2, t2)],
'exts': [None, 'log', 'exp'], 'extargs': [None, x, x]})
assert is_deriv_k(Poly(x**2*t2**3, t2), Poly(1, t2), DE) == \
([(x, 3), (t1, 2)], 2*t1 + 3*x, 1)
# TODO: Add more tests, including ones with exponentials
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(2/x, t1)],
'exts': [None, 'log'], 'extargs': [None, x**2]})
assert is_deriv_k(Poly(x, t1), Poly(1, t1), DE) == \
([(t1, S.Half)], t1/2, 1)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(2/(1 + x), t0)],
'exts': [None, 'log'], 'extargs': [None, x**2 + 2*x + 1]})
assert is_deriv_k(Poly(1 + x, t0), Poly(1, t0), DE) == \
([(t0, S.Half)], t0/2, 1)
# Issue 10798
# DE = DifferentialExtension(log(1/x), x)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(-1/x, t)],
'exts': [None, 'log'], 'extargs': [None, 1/x]})
assert is_deriv_k(Poly(1, t), Poly(x, t), DE) == ([(t, 1)], t, 1)
def test_is_log_deriv_k_t_radical_in_field():
# NOTE: any potential constant factor in the second element of the result
# doesn't matter, because it cancels in Da/a.
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]})
assert is_log_deriv_k_t_radical_in_field(Poly(5*t + 1, t), Poly(2*t*x, t), DE) == \
(2, t*x**5)
assert is_log_deriv_k_t_radical_in_field(Poly(2 + 3*t, t), Poly(5*x*t, t), DE) == \
(5, x**3*t**2)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(-t/x**2, t)]})
assert is_log_deriv_k_t_radical_in_field(Poly(-(1 + 2*t), t),
Poly(2*x**2 + 2*x**2*t, t), DE) == \
(2, t + t**2)
assert is_log_deriv_k_t_radical_in_field(Poly(-1, t), Poly(x**2, t), DE) == \
(1, t)
assert is_log_deriv_k_t_radical_in_field(Poly(1, t), Poly(2*x**2, t), DE) == \
(2, 1/t)
def test_parametric_log_deriv():
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]})
assert parametric_log_deriv_heu(Poly(5*t**2 + t - 6, t), Poly(2*x*t**2, t),
Poly(-1, t), Poly(x*t**2, t), DE) == \
(2, 6, t*x**5)

View File

@ -0,0 +1,601 @@
from sympy.core import S, Rational
from sympy.integrals.quadrature import (gauss_legendre, gauss_laguerre,
gauss_hermite, gauss_gen_laguerre,
gauss_chebyshev_t, gauss_chebyshev_u,
gauss_jacobi, gauss_lobatto)
def test_legendre():
x, w = gauss_legendre(1, 17)
assert [str(r) for r in x] == ['0']
assert [str(r) for r in w] == ['2.0000000000000000']
x, w = gauss_legendre(2, 17)
assert [str(r) for r in x] == [
'-0.57735026918962576',
'0.57735026918962576']
assert [str(r) for r in w] == [
'1.0000000000000000',
'1.0000000000000000']
x, w = gauss_legendre(3, 17)
assert [str(r) for r in x] == [
'-0.77459666924148338',
'0',
'0.77459666924148338']
assert [str(r) for r in w] == [
'0.55555555555555556',
'0.88888888888888889',
'0.55555555555555556']
x, w = gauss_legendre(4, 17)
assert [str(r) for r in x] == [
'-0.86113631159405258',
'-0.33998104358485626',
'0.33998104358485626',
'0.86113631159405258']
assert [str(r) for r in w] == [
'0.34785484513745386',
'0.65214515486254614',
'0.65214515486254614',
'0.34785484513745386']
def test_legendre_precise():
x, w = gauss_legendre(3, 40)
assert [str(r) for r in x] == [
'-0.7745966692414833770358530799564799221666',
'0',
'0.7745966692414833770358530799564799221666']
assert [str(r) for r in w] == [
'0.5555555555555555555555555555555555555556',
'0.8888888888888888888888888888888888888889',
'0.5555555555555555555555555555555555555556']
def test_laguerre():
x, w = gauss_laguerre(1, 17)
assert [str(r) for r in x] == ['1.0000000000000000']
assert [str(r) for r in w] == ['1.0000000000000000']
x, w = gauss_laguerre(2, 17)
assert [str(r) for r in x] == [
'0.58578643762690495',
'3.4142135623730950']
assert [str(r) for r in w] == [
'0.85355339059327376',
'0.14644660940672624']
x, w = gauss_laguerre(3, 17)
assert [str(r) for r in x] == [
'0.41577455678347908',
'2.2942803602790417',
'6.2899450829374792',
]
assert [str(r) for r in w] == [
'0.71109300992917302',
'0.27851773356924085',
'0.010389256501586136',
]
x, w = gauss_laguerre(4, 17)
assert [str(r) for r in x] == [
'0.32254768961939231',
'1.7457611011583466',
'4.5366202969211280',
'9.3950709123011331']
assert [str(r) for r in w] == [
'0.60315410434163360',
'0.35741869243779969',
'0.038887908515005384',
'0.00053929470556132745']
x, w = gauss_laguerre(5, 17)
assert [str(r) for r in x] == [
'0.26356031971814091',
'1.4134030591065168',
'3.5964257710407221',
'7.0858100058588376',
'12.640800844275783']
assert [str(r) for r in w] == [
'0.52175561058280865',
'0.39866681108317593',
'0.075942449681707595',
'0.0036117586799220485',
'2.3369972385776228e-5']
def test_laguerre_precise():
x, w = gauss_laguerre(3, 40)
assert [str(r) for r in x] == [
'0.4157745567834790833115338731282744735466',
'2.294280360279041719822050361359593868960',
'6.289945082937479196866415765512131657493']
assert [str(r) for r in w] == [
'0.7110930099291730154495901911425944313094',
'0.2785177335692408488014448884567264810349',
'0.01038925650158613574896492040067908765572']
def test_hermite():
x, w = gauss_hermite(1, 17)
assert [str(r) for r in x] == ['0']
assert [str(r) for r in w] == ['1.7724538509055160']
x, w = gauss_hermite(2, 17)
assert [str(r) for r in x] == [
'-0.70710678118654752',
'0.70710678118654752']
assert [str(r) for r in w] == [
'0.88622692545275801',
'0.88622692545275801']
x, w = gauss_hermite(3, 17)
assert [str(r) for r in x] == [
'-1.2247448713915890',
'0',
'1.2247448713915890']
assert [str(r) for r in w] == [
'0.29540897515091934',
'1.1816359006036774',
'0.29540897515091934']
x, w = gauss_hermite(4, 17)
assert [str(r) for r in x] == [
'-1.6506801238857846',
'-0.52464762327529032',
'0.52464762327529032',
'1.6506801238857846']
assert [str(r) for r in w] == [
'0.081312835447245177',
'0.80491409000551284',
'0.80491409000551284',
'0.081312835447245177']
x, w = gauss_hermite(5, 17)
assert [str(r) for r in x] == [
'-2.0201828704560856',
'-0.95857246461381851',
'0',
'0.95857246461381851',
'2.0201828704560856']
assert [str(r) for r in w] == [
'0.019953242059045913',
'0.39361932315224116',
'0.94530872048294188',
'0.39361932315224116',
'0.019953242059045913']
def test_hermite_precise():
x, w = gauss_hermite(3, 40)
assert [str(r) for r in x] == [
'-1.224744871391589049098642037352945695983',
'0',
'1.224744871391589049098642037352945695983']
assert [str(r) for r in w] == [
'0.2954089751509193378830279138901908637996',
'1.181635900603677351532111655560763455198',
'0.2954089751509193378830279138901908637996']
def test_gen_laguerre():
x, w = gauss_gen_laguerre(1, Rational(-1, 2), 17)
assert [str(r) for r in x] == ['0.50000000000000000']
assert [str(r) for r in w] == ['1.7724538509055160']
x, w = gauss_gen_laguerre(2, Rational(-1, 2), 17)
assert [str(r) for r in x] == [
'0.27525512860841095',
'2.7247448713915890']
assert [str(r) for r in w] == [
'1.6098281800110257',
'0.16262567089449035']
x, w = gauss_gen_laguerre(3, Rational(-1, 2), 17)
assert [str(r) for r in x] == [
'0.19016350919348813',
'1.7844927485432516',
'5.5253437422632603']
assert [str(r) for r in w] == [
'1.4492591904487850',
'0.31413464064571329',
'0.0090600198110176913']
x, w = gauss_gen_laguerre(4, Rational(-1, 2), 17)
assert [str(r) for r in x] == [
'0.14530352150331709',
'1.3390972881263614',
'3.9269635013582872',
'8.5886356890120343']
assert [str(r) for r in w] == [
'1.3222940251164826',
'0.41560465162978376',
'0.034155966014826951',
'0.00039920814442273524']
x, w = gauss_gen_laguerre(5, Rational(-1, 2), 17)
assert [str(r) for r in x] == [
'0.11758132021177814',
'1.0745620124369040',
'3.0859374437175500',
'6.4147297336620305',
'11.807189489971737']
assert [str(r) for r in w] == [
'1.2217252674706516',
'0.48027722216462937',
'0.067748788910962126',
'0.0026872914935624654',
'1.5280865710465241e-5']
x, w = gauss_gen_laguerre(1, 2, 17)
assert [str(r) for r in x] == ['3.0000000000000000']
assert [str(r) for r in w] == ['2.0000000000000000']
x, w = gauss_gen_laguerre(2, 2, 17)
assert [str(r) for r in x] == [
'2.0000000000000000',
'6.0000000000000000']
assert [str(r) for r in w] == [
'1.5000000000000000',
'0.50000000000000000']
x, w = gauss_gen_laguerre(3, 2, 17)
assert [str(r) for r in x] == [
'1.5173870806774125',
'4.3115831337195203',
'9.1710297856030672']
assert [str(r) for r in w] == [
'1.0374949614904253',
'0.90575000470306537',
'0.056755033806509347']
x, w = gauss_gen_laguerre(4, 2, 17)
assert [str(r) for r in x] == [
'1.2267632635003021',
'3.4125073586969460',
'6.9026926058516134',
'12.458036771951139']
assert [str(r) for r in w] == [
'0.72552499769865438',
'1.0634242919791946',
'0.20669613102835355',
'0.0043545792937974889']
x, w = gauss_gen_laguerre(5, 2, 17)
assert [str(r) for r in x] == [
'1.0311091440933816',
'2.8372128239538217',
'5.6202942725987079',
'9.6829098376640271',
'15.828473921690062']
assert [str(r) for r in w] == [
'0.52091739683509184',
'1.0667059331592211',
'0.38354972366693113',
'0.028564233532974658',
'0.00026271280578124935']
def test_gen_laguerre_precise():
x, w = gauss_gen_laguerre(3, Rational(-1, 2), 40)
assert [str(r) for r in x] == [
'0.1901635091934881328718554276203028970878',
'1.784492748543251591186722461957367638500',
'5.525343742263260275941422110422329464413']
assert [str(r) for r in w] == [
'1.449259190448785048183829411195134343108',
'0.3141346406457132878326231270167565378246',
'0.009060019811017691281714945129254301865020']
x, w = gauss_gen_laguerre(3, 2, 40)
assert [str(r) for r in x] == [
'1.517387080677412495020323111016672547482',
'4.311583133719520302881184669723530562299',
'9.171029785603067202098492219259796890218']
assert [str(r) for r in w] == [
'1.037494961490425285817554606541269153041',
'0.9057500047030653669269785048806009945254',
'0.05675503380650934725546688857812985243312']
def test_chebyshev_t():
x, w = gauss_chebyshev_t(1, 17)
assert [str(r) for r in x] == ['0']
assert [str(r) for r in w] == ['3.1415926535897932']
x, w = gauss_chebyshev_t(2, 17)
assert [str(r) for r in x] == [
'0.70710678118654752',
'-0.70710678118654752']
assert [str(r) for r in w] == [
'1.5707963267948966',
'1.5707963267948966']
x, w = gauss_chebyshev_t(3, 17)
assert [str(r) for r in x] == [
'0.86602540378443865',
'0',
'-0.86602540378443865']
assert [str(r) for r in w] == [
'1.0471975511965977',
'1.0471975511965977',
'1.0471975511965977']
x, w = gauss_chebyshev_t(4, 17)
assert [str(r) for r in x] == [
'0.92387953251128676',
'0.38268343236508977',
'-0.38268343236508977',
'-0.92387953251128676']
assert [str(r) for r in w] == [
'0.78539816339744831',
'0.78539816339744831',
'0.78539816339744831',
'0.78539816339744831']
x, w = gauss_chebyshev_t(5, 17)
assert [str(r) for r in x] == [
'0.95105651629515357',
'0.58778525229247313',
'0',
'-0.58778525229247313',
'-0.95105651629515357']
assert [str(r) for r in w] == [
'0.62831853071795865',
'0.62831853071795865',
'0.62831853071795865',
'0.62831853071795865',
'0.62831853071795865']
def test_chebyshev_t_precise():
x, w = gauss_chebyshev_t(3, 40)
assert [str(r) for r in x] == [
'0.8660254037844386467637231707529361834714',
'0',
'-0.8660254037844386467637231707529361834714']
assert [str(r) for r in w] == [
'1.047197551196597746154214461093167628066',
'1.047197551196597746154214461093167628066',
'1.047197551196597746154214461093167628066']
def test_chebyshev_u():
x, w = gauss_chebyshev_u(1, 17)
assert [str(r) for r in x] == ['0']
assert [str(r) for r in w] == ['1.5707963267948966']
x, w = gauss_chebyshev_u(2, 17)
assert [str(r) for r in x] == [
'0.50000000000000000',
'-0.50000000000000000']
assert [str(r) for r in w] == [
'0.78539816339744831',
'0.78539816339744831']
x, w = gauss_chebyshev_u(3, 17)
assert [str(r) for r in x] == [
'0.70710678118654752',
'0',
'-0.70710678118654752']
assert [str(r) for r in w] == [
'0.39269908169872415',
'0.78539816339744831',
'0.39269908169872415']
x, w = gauss_chebyshev_u(4, 17)
assert [str(r) for r in x] == [
'0.80901699437494742',
'0.30901699437494742',
'-0.30901699437494742',
'-0.80901699437494742']
assert [str(r) for r in w] == [
'0.21707871342270599',
'0.56831944997474231',
'0.56831944997474231',
'0.21707871342270599']
x, w = gauss_chebyshev_u(5, 17)
assert [str(r) for r in x] == [
'0.86602540378443865',
'0.50000000000000000',
'0',
'-0.50000000000000000',
'-0.86602540378443865']
assert [str(r) for r in w] == [
'0.13089969389957472',
'0.39269908169872415',
'0.52359877559829887',
'0.39269908169872415',
'0.13089969389957472']
def test_chebyshev_u_precise():
x, w = gauss_chebyshev_u(3, 40)
assert [str(r) for r in x] == [
'0.7071067811865475244008443621048490392848',
'0',
'-0.7071067811865475244008443621048490392848']
assert [str(r) for r in w] == [
'0.3926990816987241548078304229099378605246',
'0.7853981633974483096156608458198757210493',
'0.3926990816987241548078304229099378605246']
def test_jacobi():
x, w = gauss_jacobi(1, Rational(-1, 2), S.Half, 17)
assert [str(r) for r in x] == ['0.50000000000000000']
assert [str(r) for r in w] == ['3.1415926535897932']
x, w = gauss_jacobi(2, Rational(-1, 2), S.Half, 17)
assert [str(r) for r in x] == [
'-0.30901699437494742',
'0.80901699437494742']
assert [str(r) for r in w] == [
'0.86831485369082398',
'2.2732777998989693']
x, w = gauss_jacobi(3, Rational(-1, 2), S.Half, 17)
assert [str(r) for r in x] == [
'-0.62348980185873353',
'0.22252093395631440',
'0.90096886790241913']
assert [str(r) for r in w] == [
'0.33795476356635433',
'1.0973322242791115',
'1.7063056657443274']
x, w = gauss_jacobi(4, Rational(-1, 2), S.Half, 17)
assert [str(r) for r in x] == [
'-0.76604444311897804',
'-0.17364817766693035',
'0.50000000000000000',
'0.93969262078590838']
assert [str(r) for r in w] == [
'0.16333179083642836',
'0.57690240318269103',
'1.0471975511965977',
'1.3541609083740761']
x, w = gauss_jacobi(5, Rational(-1, 2), S.Half, 17)
assert [str(r) for r in x] == [
'-0.84125353283118117',
'-0.41541501300188643',
'0.14231483827328514',
'0.65486073394528506',
'0.95949297361449739']
assert [str(r) for r in w] == [
'0.090675770007435372',
'0.33391416373675607',
'0.65248870981926643',
'0.94525424081394926',
'1.1192597692123861']
x, w = gauss_jacobi(1, 2, 3, 17)
assert [str(r) for r in x] == ['0.14285714285714286']
assert [str(r) for r in w] == ['1.0666666666666667']
x, w = gauss_jacobi(2, 2, 3, 17)
assert [str(r) for r in x] == [
'-0.24025307335204215',
'0.46247529557426437']
assert [str(r) for r in w] == [
'0.48514624517838660',
'0.58152042148828007']
x, w = gauss_jacobi(3, 2, 3, 17)
assert [str(r) for r in x] == [
'-0.46115870378089762',
'0.10438533038323902',
'0.62950064612493132']
assert [str(r) for r in w] == [
'0.17937613502213266',
'0.61595640991147154',
'0.27133412173306246']
x, w = gauss_jacobi(4, 2, 3, 17)
assert [str(r) for r in x] == [
'-0.59903470850824782',
'-0.14761105199952565',
'0.32554377081188859',
'0.72879429738819258']
assert [str(r) for r in w] == [
'0.067809641836772187',
'0.38956404952032481',
'0.47995970868024150',
'0.12933326662932816']
x, w = gauss_jacobi(5, 2, 3, 17)
assert [str(r) for r in x] == [
'-0.69045775012676106',
'-0.32651993134900065',
'0.082337849552034905',
'0.47517887061283164',
'0.79279429464422850']
assert [str(r) for r in w] == [
'0.027410178066337099',
'0.21291786060364828',
'0.43908437944395081',
'0.32220656547221822',
'0.065047683080512268']
def test_jacobi_precise():
x, w = gauss_jacobi(3, Rational(-1, 2), S.Half, 40)
assert [str(r) for r in x] == [
'-0.6234898018587335305250048840042398106323',
'0.2225209339563144042889025644967947594664',
'0.9009688679024191262361023195074450511659']
assert [str(r) for r in w] == [
'0.3379547635663543330553835737094171534907',
'1.097332224279111467485302294320899710461',
'1.706305665744327437921957515249186020246']
x, w = gauss_jacobi(3, 2, 3, 40)
assert [str(r) for r in x] == [
'-0.4611587037808976179121958105554375981274',
'0.1043853303832390210914918407615869143233',
'0.6295006461249313240934312425211234110769']
assert [str(r) for r in w] == [
'0.1793761350221326596137764371503859752628',
'0.6159564099114715430909548532229749439714',
'0.2713341217330624639619353762933057474325']
def test_lobatto():
x, w = gauss_lobatto(2, 17)
assert [str(r) for r in x] == [
'-1',
'1']
assert [str(r) for r in w] == [
'1.0000000000000000',
'1.0000000000000000']
x, w = gauss_lobatto(3, 17)
assert [str(r) for r in x] == [
'-1',
'0',
'1']
assert [str(r) for r in w] == [
'0.33333333333333333',
'1.3333333333333333',
'0.33333333333333333']
x, w = gauss_lobatto(4, 17)
assert [str(r) for r in x] == [
'-1',
'-0.44721359549995794',
'0.44721359549995794',
'1']
assert [str(r) for r in w] == [
'0.16666666666666667',
'0.83333333333333333',
'0.83333333333333333',
'0.16666666666666667']
x, w = gauss_lobatto(5, 17)
assert [str(r) for r in x] == [
'-1',
'-0.65465367070797714',
'0',
'0.65465367070797714',
'1']
assert [str(r) for r in w] == [
'0.10000000000000000',
'0.54444444444444444',
'0.71111111111111111',
'0.54444444444444444',
'0.10000000000000000']
def test_lobatto_precise():
x, w = gauss_lobatto(3, 40)
assert [str(r) for r in x] == [
'-1',
'0',
'1']
assert [str(r) for r in w] == [
'0.3333333333333333333333333333333333333333',
'1.333333333333333333333333333333333333333',
'0.3333333333333333333333333333333333333333']

View File

@ -0,0 +1,183 @@
from sympy.core.numbers import (I, Rational)
from sympy.core.singleton import S
from sympy.core.symbol import (Dummy, symbols)
from sympy.functions.elementary.exponential import log
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.functions.elementary.trigonometric import atan
from sympy.integrals.integrals import integrate
from sympy.polys.polytools import Poly
from sympy.simplify.simplify import simplify
from sympy.integrals.rationaltools import ratint, ratint_logpart, log_to_atan
from sympy.abc import a, b, x, t
half = S.Half
def test_ratint():
assert ratint(S.Zero, x) == 0
assert ratint(S(7), x) == 7*x
assert ratint(x, x) == x**2/2
assert ratint(2*x, x) == x**2
assert ratint(-2*x, x) == -x**2
assert ratint(8*x**7 + 2*x + 1, x) == x**8 + x**2 + x
f = S.One
g = x + 1
assert ratint(f / g, x) == log(x + 1)
assert ratint((f, g), x) == log(x + 1)
f = x**3 - x
g = x - 1
assert ratint(f/g, x) == x**3/3 + x**2/2
f = x
g = (x - a)*(x + a)
assert ratint(f/g, x) == log(x**2 - a**2)/2
f = S.One
g = x**2 + 1
assert ratint(f/g, x, real=None) == atan(x)
assert ratint(f/g, x, real=True) == atan(x)
assert ratint(f/g, x, real=False) == I*log(x + I)/2 - I*log(x - I)/2
f = S(36)
g = x**5 - 2*x**4 - 2*x**3 + 4*x**2 + x - 2
assert ratint(f/g, x) == \
-4*log(x + 1) + 4*log(x - 2) + (12*x + 6)/(x**2 - 1)
f = x**4 - 3*x**2 + 6
g = x**6 - 5*x**4 + 5*x**2 + 4
assert ratint(f/g, x) == \
atan(x) + atan(x**3) + atan(x/2 - Rational(3, 2)*x**3 + S.Half*x**5)
f = x**7 - 24*x**4 - 4*x**2 + 8*x - 8
g = x**8 + 6*x**6 + 12*x**4 + 8*x**2
assert ratint(f/g, x) == \
(4 + 6*x + 8*x**2 + 3*x**3)/(4*x + 4*x**3 + x**5) + log(x)
assert ratint((x**3*f)/(x*g), x) == \
-(12 - 16*x + 6*x**2 - 14*x**3)/(4 + 4*x**2 + x**4) - \
5*sqrt(2)*atan(x*sqrt(2)/2) + S.Half*x**2 - 3*log(2 + x**2)
f = x**5 - x**4 + 4*x**3 + x**2 - x + 5
g = x**4 - 2*x**3 + 5*x**2 - 4*x + 4
assert ratint(f/g, x) == \
x + S.Half*x**2 + S.Half*log(2 - x + x**2) + (9 - 4*x)/(7*x**2 - 7*x + 14) + \
13*sqrt(7)*atan(Rational(-1, 7)*sqrt(7) + 2*x*sqrt(7)/7)/49
assert ratint(1/(x**2 + x + 1), x) == \
2*sqrt(3)*atan(sqrt(3)/3 + 2*x*sqrt(3)/3)/3
assert ratint(1/(x**3 + 1), x) == \
-log(1 - x + x**2)/6 + log(1 + x)/3 + sqrt(3)*atan(-sqrt(3)
/3 + 2*x*sqrt(3)/3)/3
assert ratint(1/(x**2 + x + 1), x, real=False) == \
-I*3**half*log(half + x - half*I*3**half)/3 + \
I*3**half*log(half + x + half*I*3**half)/3
assert ratint(1/(x**3 + 1), x, real=False) == log(1 + x)/3 + \
(Rational(-1, 6) + I*3**half/6)*log(-half + x + I*3**half/2) + \
(Rational(-1, 6) - I*3**half/6)*log(-half + x - I*3**half/2)
# issue 4991
assert ratint(1/(x*(a + b*x)**3), x) == \
(3*a + 2*b*x)/(2*a**4 + 4*a**3*b*x + 2*a**2*b**2*x**2) + (
log(x) - log(a/b + x))/a**3
assert ratint(x/(1 - x**2), x) == -log(x**2 - 1)/2
assert ratint(-x/(1 - x**2), x) == log(x**2 - 1)/2
assert ratint((x/4 - 4/(1 - x)).diff(x), x) == x/4 + 4/(x - 1)
ans = atan(x)
assert ratint(1/(x**2 + 1), x, symbol=x) == ans
assert ratint(1/(x**2 + 1), x, symbol='x') == ans
assert ratint(1/(x**2 + 1), x, symbol=a) == ans
# this asserts that as_dummy must return a unique symbol
# even if the symbol is already a Dummy
d = Dummy()
assert ratint(1/(d**2 + 1), d, symbol=d) == atan(d)
def test_ratint_logpart():
assert ratint_logpart(x, x**2 - 9, x, t) == \
[(Poly(x**2 - 9, x), Poly(-2*t + 1, t))]
assert ratint_logpart(x**2, x**3 - 5, x, t) == \
[(Poly(x**3 - 5, x), Poly(-3*t + 1, t))]
def test_issue_5414():
assert ratint(1/(x**2 + 16), x) == atan(x/4)/4
def test_issue_5249():
assert ratint(
1/(x**2 + a**2), x) == (-I*log(-I*a + x)/2 + I*log(I*a + x)/2)/a
def test_issue_5817():
a, b, c = symbols('a,b,c', positive=True)
assert simplify(ratint(a/(b*c*x**2 + a**2 + b*a), x)) == \
sqrt(a)*atan(sqrt(
b)*sqrt(c)*x/(sqrt(a)*sqrt(a + b)))/(sqrt(b)*sqrt(c)*sqrt(a + b))
def test_issue_5981():
u = symbols('u')
assert integrate(1/(u**2 + 1)) == atan(u)
def test_issue_10488():
a,b,c,x = symbols('a b c x', positive=True)
assert integrate(x/(a*x+b),x) == x/a - b*log(a*x + b)/a**2
def test_issues_8246_12050_13501_14080():
a = symbols('a', nonzero=True)
assert integrate(a/(x**2 + a**2), x) == atan(x/a)
assert integrate(1/(x**2 + a**2), x) == atan(x/a)/a
assert integrate(1/(1 + a**2*x**2), x) == atan(a*x)/a
def test_issue_6308():
k, a0 = symbols('k a0', real=True)
assert integrate((x**2 + 1 - k**2)/(x**2 + 1 + a0**2), x) == \
x - (a0**2 + k**2)*atan(x/sqrt(a0**2 + 1))/sqrt(a0**2 + 1)
def test_issue_5907():
a = symbols('a', nonzero=True)
assert integrate(1/(x**2 + a**2)**2, x) == \
x/(2*a**4 + 2*a**2*x**2) + atan(x/a)/(2*a**3)
def test_log_to_atan():
f, g = (Poly(x + S.Half, x, domain='QQ'), Poly(sqrt(3)/2, x, domain='EX'))
fg_ans = 2*atan(2*sqrt(3)*x/3 + sqrt(3)/3)
assert log_to_atan(f, g) == fg_ans
assert log_to_atan(g, f) == -fg_ans
def test_issue_25896():
# for both tests, C = 0 in log_to_real
# but this only has a log result
e = (2*x + 1)/(x**2 + x + 1) + 1/x
assert ratint(e, x) == log(x**3 + x**2 + x)
# while this has more
assert ratint((4*x + 7)/(x**2 + 4*x + 6) + 2/x, x) == (
2*log(x) + 2*log(x**2 + 4*x + 6) - sqrt(2)*atan(
sqrt(2)*x/2 + sqrt(2))/2)

View File

@ -0,0 +1,202 @@
"""Most of these tests come from the examples in Bronstein's book."""
from sympy.core.numbers import (I, Rational, oo)
from sympy.core.symbol import symbols
from sympy.polys.polytools import Poly
from sympy.integrals.risch import (DifferentialExtension,
NonElementaryIntegralException)
from sympy.integrals.rde import (order_at, order_at_oo, weak_normalizer,
normal_denom, special_denom, bound_degree, spde, solve_poly_rde,
no_cancel_equal, cancel_primitive, cancel_exp, rischDE)
from sympy.testing.pytest import raises
from sympy.abc import x, t, z, n
t0, t1, t2, k = symbols('t:3 k')
def test_order_at():
a = Poly(t**4, t)
b = Poly((t**2 + 1)**3*t, t)
c = Poly((t**2 + 1)**6*t, t)
d = Poly((t**2 + 1)**10*t**10, t)
e = Poly((t**2 + 1)**100*t**37, t)
p1 = Poly(t, t)
p2 = Poly(1 + t**2, t)
assert order_at(a, p1, t) == 4
assert order_at(b, p1, t) == 1
assert order_at(c, p1, t) == 1
assert order_at(d, p1, t) == 10
assert order_at(e, p1, t) == 37
assert order_at(a, p2, t) == 0
assert order_at(b, p2, t) == 3
assert order_at(c, p2, t) == 6
assert order_at(d, p1, t) == 10
assert order_at(e, p2, t) == 100
assert order_at(Poly(0, t), Poly(t, t), t) is oo
assert order_at_oo(Poly(t**2 - 1, t), Poly(t + 1), t) == \
order_at_oo(Poly(t - 1, t), Poly(1, t), t) == -1
assert order_at_oo(Poly(0, t), Poly(1, t), t) is oo
def test_weak_normalizer():
a = Poly((1 + x)*t**5 + 4*t**4 + (-1 - 3*x)*t**3 - 4*t**2 + (-2 + 2*x)*t, t)
d = Poly(t**4 - 3*t**2 + 2, t)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]})
r = weak_normalizer(a, d, DE, z)
assert r == (Poly(t**5 - t**4 - 4*t**3 + 4*t**2 + 4*t - 4, t, domain='ZZ[x]'),
(Poly((1 + x)*t**2 + x*t, t, domain='ZZ[x]'),
Poly(t + 1, t, domain='ZZ[x]')))
assert weak_normalizer(r[1][0], r[1][1], DE) == (Poly(1, t), r[1])
r = weak_normalizer(Poly(1 + t**2), Poly(t**2 - 1, t), DE, z)
assert r == (Poly(t**4 - 2*t**2 + 1, t), (Poly(-3*t**2 + 1, t), Poly(t**2 - 1, t)))
assert weak_normalizer(r[1][0], r[1][1], DE, z) == (Poly(1, t), r[1])
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1 + t**2)]})
r = weak_normalizer(Poly(1 + t**2), Poly(t, t), DE, z)
assert r == (Poly(t, t), (Poly(0, t), Poly(1, t)))
assert weak_normalizer(r[1][0], r[1][1], DE, z) == (Poly(1, t), r[1])
def test_normal_denom():
DE = DifferentialExtension(extension={'D': [Poly(1, x)]})
raises(NonElementaryIntegralException, lambda: normal_denom(Poly(1, x), Poly(1, x),
Poly(1, x), Poly(x, x), DE))
fa, fd = Poly(t**2 + 1, t), Poly(1, t)
ga, gd = Poly(1, t), Poly(t**2, t)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t**2 + 1, t)]})
assert normal_denom(fa, fd, ga, gd, DE) == \
(Poly(t, t), (Poly(t**3 - t**2 + t - 1, t), Poly(1, t)), (Poly(1, t),
Poly(1, t)), Poly(t, t))
def test_special_denom():
# TODO: add more tests here
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]})
assert special_denom(Poly(1, t), Poly(t**2, t), Poly(1, t), Poly(t**2 - 1, t),
Poly(t, t), DE) == \
(Poly(1, t), Poly(t**2 - 1, t), Poly(t**2 - 1, t), Poly(t, t))
# assert special_denom(Poly(1, t), Poly(2*x, t), Poly((1 + 2*x)*t, t), DE) == 1
# issue 3940
# Note, this isn't a very good test, because the denominator is just 1,
# but at least it tests the exp cancellation case
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(-2*x*t0, t0),
Poly(I*k*t1, t1)]})
DE.decrement_level()
assert special_denom(Poly(1, t0), Poly(I*k, t0), Poly(1, t0), Poly(t0, t0),
Poly(1, t0), DE) == \
(Poly(1, t0, domain='ZZ'), Poly(I*k, t0, domain='ZZ_I[k,x]'),
Poly(t0, t0, domain='ZZ'), Poly(1, t0, domain='ZZ'))
assert special_denom(Poly(1, t), Poly(t**2, t), Poly(1, t), Poly(t**2 - 1, t),
Poly(t, t), DE, case='tan') == \
(Poly(1, t, t0, domain='ZZ'), Poly(t**2, t0, t, domain='ZZ[x]'),
Poly(t, t, t0, domain='ZZ'), Poly(1, t0, domain='ZZ'))
raises(ValueError, lambda: special_denom(Poly(1, t), Poly(t**2, t), Poly(1, t), Poly(t**2 - 1, t),
Poly(t, t), DE, case='unrecognized_case'))
def test_bound_degree_fail():
# Primitive
DE = DifferentialExtension(extension={'D': [Poly(1, x),
Poly(t0/x**2, t0), Poly(1/x, t)]})
assert bound_degree(Poly(t**2, t), Poly(-(1/x**2*t**2 + 1/x), t),
Poly((2*x - 1)*t**4 + (t0 + x)/x*t**3 - (t0 + 4*x**2)/2*x*t**2 + x*t,
t), DE) == 3
def test_bound_degree():
# Base
DE = DifferentialExtension(extension={'D': [Poly(1, x)]})
assert bound_degree(Poly(1, x), Poly(-2*x, x), Poly(1, x), DE) == 0
# Primitive (see above test_bound_degree_fail)
# TODO: Add test for when the degree bound becomes larger after limited_integrate
# TODO: Add test for db == da - 1 case
# Exp
# TODO: Add tests
# TODO: Add test for when the degree becomes larger after parametric_log_deriv()
# Nonlinear
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t**2 + 1, t)]})
assert bound_degree(Poly(t, t), Poly((t - 1)*(t**2 + 1), t), Poly(1, t), DE) == 0
def test_spde():
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t**2 + 1, t)]})
raises(NonElementaryIntegralException, lambda: spde(Poly(t, t), Poly((t - 1)*(t**2 + 1), t), Poly(1, t), 0, DE))
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]})
assert spde(Poly(t**2 + x*t*2 + x**2, t), Poly(t**2/x**2 + (2/x - 1)*t, t),
Poly(t**2/x**2 + (2/x - 1)*t, t), 0, DE) == \
(Poly(0, t), Poly(0, t), 0, Poly(0, t), Poly(1, t, domain='ZZ(x)'))
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t0/x**2, t0), Poly(1/x, t)]})
assert spde(Poly(t**2, t), Poly(-t**2/x**2 - 1/x, t),
Poly((2*x - 1)*t**4 + (t0 + x)/x*t**3 - (t0 + 4*x**2)/(2*x)*t**2 + x*t, t), 3, DE) == \
(Poly(0, t), Poly(0, t), 0, Poly(0, t),
Poly(t0*t**2/2 + x**2*t**2 - x**2*t, t, domain='ZZ(x,t0)'))
DE = DifferentialExtension(extension={'D': [Poly(1, x)]})
assert spde(Poly(x**2 + x + 1, x), Poly(-2*x - 1, x), Poly(x**5/2 +
3*x**4/4 + x**3 - x**2 + 1, x), 4, DE) == \
(Poly(0, x, domain='QQ'), Poly(x/2 - Rational(1, 4), x), 2, Poly(x**2 + x + 1, x), Poly(x*Rational(5, 4), x))
assert spde(Poly(x**2 + x + 1, x), Poly(-2*x - 1, x), Poly(x**5/2 +
3*x**4/4 + x**3 - x**2 + 1, x), n, DE) == \
(Poly(0, x, domain='QQ'), Poly(x/2 - Rational(1, 4), x), -2 + n, Poly(x**2 + x + 1, x), Poly(x*Rational(5, 4), x))
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1, t)]})
raises(NonElementaryIntegralException, lambda: spde(Poly((t - 1)*(t**2 + 1)**2, t), Poly((t - 1)*(t**2 + 1), t), Poly(1, t), 0, DE))
DE = DifferentialExtension(extension={'D': [Poly(1, x)]})
assert spde(Poly(x**2 - x, x), Poly(1, x), Poly(9*x**4 - 10*x**3 + 2*x**2, x), 4, DE) == \
(Poly(0, x, domain='ZZ'), Poly(0, x), 0, Poly(0, x), Poly(3*x**3 - 2*x**2, x, domain='QQ'))
assert spde(Poly(x**2 - x, x), Poly(x**2 - 5*x + 3, x), Poly(x**7 - x**6 - 2*x**4 + 3*x**3 - x**2, x), 5, DE) == \
(Poly(1, x, domain='QQ'), Poly(x + 1, x, domain='QQ'), 1, Poly(x**4 - x**3, x), Poly(x**3 - x**2, x, domain='QQ'))
def test_solve_poly_rde_no_cancel():
# deg(b) large
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1 + t**2, t)]})
assert solve_poly_rde(Poly(t**2 + 1, t), Poly(t**3 + (x + 1)*t**2 + t + x + 2, t),
oo, DE) == Poly(t + x, t)
# deg(b) small
DE = DifferentialExtension(extension={'D': [Poly(1, x)]})
assert solve_poly_rde(Poly(0, x), Poly(x/2 - Rational(1, 4), x), oo, DE) == \
Poly(x**2/4 - x/4, x)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t**2 + 1, t)]})
assert solve_poly_rde(Poly(2, t), Poly(t**2 + 2*t + 3, t), 1, DE) == \
Poly(t + 1, t, x)
# deg(b) == deg(D) - 1
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t**2 + 1, t)]})
assert no_cancel_equal(Poly(1 - t, t),
Poly(t**3 + t**2 - 2*x*t - 2*x, t), oo, DE) == \
(Poly(t**2, t), 1, Poly((-2 - 2*x)*t - 2*x, t))
def test_solve_poly_rde_cancel():
# exp
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]})
assert cancel_exp(Poly(2*x, t), Poly(2*x, t), 0, DE) == \
Poly(1, t)
assert cancel_exp(Poly(2*x, t), Poly((1 + 2*x)*t, t), 1, DE) == \
Poly(t, t)
# TODO: Add more exp tests, including tests that require is_deriv_in_field()
# primitive
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]})
# If the DecrementLevel context manager is working correctly, this shouldn't
# cause any problems with the further tests.
raises(NonElementaryIntegralException, lambda: cancel_primitive(Poly(1, t), Poly(t, t), oo, DE))
assert cancel_primitive(Poly(1, t), Poly(t + 1/x, t), 2, DE) == \
Poly(t, t)
assert cancel_primitive(Poly(4*x, t), Poly(4*x*t**2 + 2*t/x, t), 3, DE) == \
Poly(t**2, t)
# TODO: Add more primitive tests, including tests that require is_deriv_in_field()
def test_rischDE():
# TODO: Add more tests for rischDE, including ones from the text
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]})
DE.decrement_level()
assert rischDE(Poly(-2*x, x), Poly(1, x), Poly(1 - 2*x - 2*x**2, x),
Poly(1, x), DE) == \
(Poly(x + 1, x), Poly(1, x))

View File

@ -0,0 +1,763 @@
"""Most of these tests come from the examples in Bronstein's book."""
from sympy.core.function import (Function, Lambda, diff, expand_log)
from sympy.core.numbers import (I, Rational, pi)
from sympy.core.relational import Ne
from sympy.core.singleton import S
from sympy.core.symbol import (Symbol, symbols)
from sympy.functions.elementary.exponential import (exp, log)
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.functions.elementary.piecewise import Piecewise
from sympy.functions.elementary.trigonometric import (atan, sin, tan)
from sympy.polys.polytools import (Poly, cancel, factor)
from sympy.integrals.risch import (gcdex_diophantine, frac_in, as_poly_1t,
derivation, splitfactor, splitfactor_sqf, canonical_representation,
hermite_reduce, polynomial_reduce, residue_reduce, residue_reduce_to_basic,
integrate_primitive, integrate_hyperexponential_polynomial,
integrate_hyperexponential, integrate_hypertangent_polynomial,
integrate_nonlinear_no_specials, integer_powers, DifferentialExtension,
risch_integrate, DecrementLevel, NonElementaryIntegral, recognize_log_derivative,
recognize_derivative, laurent_series)
from sympy.testing.pytest import raises
from sympy.abc import x, t, nu, z, a, y
t0, t1, t2 = symbols('t:3')
i = Symbol('i')
def test_gcdex_diophantine():
assert gcdex_diophantine(Poly(x**4 - 2*x**3 - 6*x**2 + 12*x + 15),
Poly(x**3 + x**2 - 4*x - 4), Poly(x**2 - 1)) == \
(Poly((-x**2 + 4*x - 3)/5), Poly((x**3 - 7*x**2 + 16*x - 10)/5))
assert gcdex_diophantine(Poly(x**3 + 6*x + 7), Poly(x**2 + 3*x + 2), Poly(x + 1)) == \
(Poly(1/13, x, domain='QQ'), Poly(-1/13*x + 3/13, x, domain='QQ'))
def test_frac_in():
assert frac_in(Poly((x + 1)/x*t, t), x) == \
(Poly(t*x + t, x), Poly(x, x))
assert frac_in((x + 1)/x*t, x) == \
(Poly(t*x + t, x), Poly(x, x))
assert frac_in((Poly((x + 1)/x*t, t), Poly(t + 1, t)), x) == \
(Poly(t*x + t, x), Poly((1 + t)*x, x))
raises(ValueError, lambda: frac_in((x + 1)/log(x)*t, x))
assert frac_in(Poly((2 + 2*x + x*(1 + x))/(1 + x)**2, t), x, cancel=True) == \
(Poly(x + 2, x), Poly(x + 1, x))
def test_as_poly_1t():
assert as_poly_1t(2/t + t, t, z) in [
Poly(t + 2*z, t, z), Poly(t + 2*z, z, t)]
assert as_poly_1t(2/t + 3/t**2, t, z) in [
Poly(2*z + 3*z**2, t, z), Poly(2*z + 3*z**2, z, t)]
assert as_poly_1t(2/((exp(2) + 1)*t), t, z) in [
Poly(2/(exp(2) + 1)*z, t, z), Poly(2/(exp(2) + 1)*z, z, t)]
assert as_poly_1t(2/((exp(2) + 1)*t) + t, t, z) in [
Poly(t + 2/(exp(2) + 1)*z, t, z), Poly(t + 2/(exp(2) + 1)*z, z, t)]
assert as_poly_1t(S.Zero, t, z) == Poly(0, t, z)
def test_derivation():
p = Poly(4*x**4*t**5 + (-4*x**3 - 4*x**4)*t**4 + (-3*x**2 + 2*x**3)*t**3 +
(2*x + 7*x**2 + 2*x**3)*t**2 + (1 - 4*x - 4*x**2)*t - 1 + 2*x, t)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(-t**2 - 3/(2*x)*t + 1/(2*x), t)]})
assert derivation(p, DE) == Poly(-20*x**4*t**6 + (2*x**3 + 16*x**4)*t**5 +
(21*x**2 + 12*x**3)*t**4 + (x*Rational(7, 2) - 25*x**2 - 12*x**3)*t**3 +
(-5 - x*Rational(15, 2) + 7*x**2)*t**2 - (3 - 8*x - 10*x**2 - 4*x**3)/(2*x)*t +
(1 - 4*x**2)/(2*x), t)
assert derivation(Poly(1, t), DE) == Poly(0, t)
assert derivation(Poly(t, t), DE) == DE.d
assert derivation(Poly(t**2 + 1/x*t + (1 - 2*x)/(4*x**2), t), DE) == \
Poly(-2*t**3 - 4/x*t**2 - (5 - 2*x)/(2*x**2)*t - (1 - 2*x)/(2*x**3), t, domain='ZZ(x)')
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t1), Poly(t, t)]})
assert derivation(Poly(x*t*t1, t), DE) == Poly(t*t1 + x*t*t1 + t, t)
assert derivation(Poly(x*t*t1, t), DE, coefficientD=True) == \
Poly((1 + t1)*t, t)
DE = DifferentialExtension(extension={'D': [Poly(1, x)]})
assert derivation(Poly(x, x), DE) == Poly(1, x)
# Test basic option
assert derivation((x + 1)/(x - 1), DE, basic=True) == -2/(1 - 2*x + x**2)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]})
assert derivation((t + 1)/(t - 1), DE, basic=True) == -2*t/(1 - 2*t + t**2)
assert derivation(t + 1, DE, basic=True) == t
def test_splitfactor():
p = Poly(4*x**4*t**5 + (-4*x**3 - 4*x**4)*t**4 + (-3*x**2 + 2*x**3)*t**3 +
(2*x + 7*x**2 + 2*x**3)*t**2 + (1 - 4*x - 4*x**2)*t - 1 + 2*x, t, field=True)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(-t**2 - 3/(2*x)*t + 1/(2*x), t)]})
assert splitfactor(p, DE) == (Poly(4*x**4*t**3 + (-8*x**3 - 4*x**4)*t**2 +
(4*x**2 + 8*x**3)*t - 4*x**2, t, domain='ZZ(x)'),
Poly(t**2 + 1/x*t + (1 - 2*x)/(4*x**2), t, domain='ZZ(x)'))
assert splitfactor(Poly(x, t), DE) == (Poly(x, t), Poly(1, t))
r = Poly(-4*x**4*z**2 + 4*x**6*z**2 - z*x**3 - 4*x**5*z**3 + 4*x**3*z**3 + x**4 + z*x**5 - x**6, t)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]})
assert splitfactor(r, DE, coefficientD=True) == \
(Poly(x*z - x**2 - z*x**3 + x**4, t), Poly(-x**2 + 4*x**2*z**2, t))
assert splitfactor_sqf(r, DE, coefficientD=True) == \
(((Poly(x*z - x**2 - z*x**3 + x**4, t), 1),), ((Poly(-x**2 + 4*x**2*z**2, t), 1),))
assert splitfactor(Poly(0, t), DE) == (Poly(0, t), Poly(1, t))
assert splitfactor_sqf(Poly(0, t), DE) == (((Poly(0, t), 1),), ())
def test_canonical_representation():
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1 + t**2, t)]})
assert canonical_representation(Poly(x - t, t), Poly(t**2, t), DE) == \
(Poly(0, t, domain='ZZ[x]'), (Poly(0, t, domain='QQ[x]'),
Poly(1, t, domain='ZZ')), (Poly(-t + x, t, domain='QQ[x]'),
Poly(t**2, t)))
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t**2 + 1, t)]})
assert canonical_representation(Poly(t**5 + t**3 + x**2*t + 1, t),
Poly((t**2 + 1)**3, t), DE) == \
(Poly(0, t, domain='ZZ[x]'), (Poly(t**5 + t**3 + x**2*t + 1, t, domain='QQ[x]'),
Poly(t**6 + 3*t**4 + 3*t**2 + 1, t, domain='QQ')),
(Poly(0, t, domain='QQ[x]'), Poly(1, t, domain='QQ')))
def test_hermite_reduce():
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t**2 + 1, t)]})
assert hermite_reduce(Poly(x - t, t), Poly(t**2, t), DE) == \
((Poly(-x, t, domain='QQ[x]'), Poly(t, t, domain='QQ[x]')),
(Poly(0, t, domain='QQ[x]'), Poly(1, t, domain='QQ[x]')),
(Poly(-x, t, domain='QQ[x]'), Poly(1, t, domain='QQ[x]')))
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(-t**2 - t/x - (1 - nu**2/x**2), t)]})
assert hermite_reduce(
Poly(x**2*t**5 + x*t**4 - nu**2*t**3 - x*(x**2 + 1)*t**2 - (x**2 - nu**2)*t - x**5/4, t),
Poly(x**2*t**4 + x**2*(x**2 + 2)*t**2 + x**2 + x**4 + x**6/4, t), DE) == \
((Poly(-x**2 - 4, t, domain='ZZ(x,nu)'), Poly(4*t**2 + 2*x**2 + 4, t, domain='ZZ(x,nu)')),
(Poly((-2*nu**2 - x**4)*t - (2*x**3 + 2*x), t, domain='ZZ(x,nu)'),
Poly(2*x**2*t**2 + x**4 + 2*x**2, t, domain='ZZ(x,nu)')),
(Poly(x*t + 1, t, domain='ZZ(x,nu)'), Poly(x, t, domain='ZZ(x,nu)')))
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]})
a = Poly((-2 + 3*x)*t**3 + (-1 + x)*t**2 + (-4*x + 2*x**2)*t + x**2, t)
d = Poly(x*t**6 - 4*x**2*t**5 + 6*x**3*t**4 - 4*x**4*t**3 + x**5*t**2, t)
assert hermite_reduce(a, d, DE) == \
((Poly(3*t**2 + t + 3*x, t, domain='ZZ(x)'),
Poly(3*t**4 - 9*x*t**3 + 9*x**2*t**2 - 3*x**3*t, t, domain='ZZ(x)')),
(Poly(0, t, domain='ZZ(x)'), Poly(1, t, domain='ZZ(x)')),
(Poly(0, t, domain='ZZ(x)'), Poly(1, t, domain='ZZ(x)')))
assert hermite_reduce(
Poly(-t**2 + 2*t + 2, t, domain='ZZ(x)'),
Poly(-x*t**2 + 2*x*t - x, t, domain='ZZ(x)'), DE) == \
((Poly(3, t, domain='ZZ(x)'), Poly(t - 1, t, domain='ZZ(x)')),
(Poly(0, t, domain='ZZ(x)'), Poly(1, t, domain='ZZ(x)')),
(Poly(1, t, domain='ZZ(x)'), Poly(x, t, domain='ZZ(x)')))
assert hermite_reduce(
Poly(-x**2*t**6 + (-1 - 2*x**3 + x**4)*t**3 + (-3 - 3*x**4)*t**2 -
2*x*t - x - 3*x**2, t, domain='ZZ(x)'),
Poly(x**4*t**6 - 2*x**2*t**3 + 1, t, domain='ZZ(x)'), DE) == \
((Poly(x**3*t + x**4 + 1, t, domain='ZZ(x)'), Poly(x**3*t**3 - x, t, domain='ZZ(x)')),
(Poly(0, t, domain='ZZ(x)'), Poly(1, t, domain='ZZ(x)')),
(Poly(-1, t, domain='ZZ(x)'), Poly(x**2, t, domain='ZZ(x)')))
assert hermite_reduce(
Poly((-2 + 3*x)*t**3 + (-1 + x)*t**2 + (-4*x + 2*x**2)*t + x**2, t),
Poly(x*t**6 - 4*x**2*t**5 + 6*x**3*t**4 - 4*x**4*t**3 + x**5*t**2, t), DE) == \
((Poly(3*t**2 + t + 3*x, t, domain='ZZ(x)'),
Poly(3*t**4 - 9*x*t**3 + 9*x**2*t**2 - 3*x**3*t, t, domain='ZZ(x)')),
(Poly(0, t, domain='ZZ(x)'), Poly(1, t, domain='ZZ(x)')),
(Poly(0, t, domain='ZZ(x)'), Poly(1, t, domain='ZZ(x)')))
def test_polynomial_reduce():
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1 + t**2, t)]})
assert polynomial_reduce(Poly(1 + x*t + t**2, t), DE) == \
(Poly(t, t), Poly(x*t, t))
assert polynomial_reduce(Poly(0, t), DE) == \
(Poly(0, t), Poly(0, t))
def test_laurent_series():
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1, t)]})
a = Poly(36, t)
d = Poly((t - 2)*(t**2 - 1)**2, t)
F = Poly(t**2 - 1, t)
n = 2
assert laurent_series(a, d, F, n, DE) == \
(Poly(-3*t**3 + 3*t**2 - 6*t - 8, t), Poly(t**5 + t**4 - 2*t**3 - 2*t**2 + t + 1, t),
[Poly(-3*t**3 - 6*t**2, t, domain='QQ'), Poly(2*t**6 + 6*t**5 - 8*t**3, t, domain='QQ')])
def test_recognize_derivative():
DE = DifferentialExtension(extension={'D': [Poly(1, t)]})
a = Poly(36, t)
d = Poly((t - 2)*(t**2 - 1)**2, t)
assert recognize_derivative(a, d, DE) == False
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]})
a = Poly(2, t)
d = Poly(t**2 - 1, t)
assert recognize_derivative(a, d, DE) == False
assert recognize_derivative(Poly(x*t, t), Poly(1, t), DE) == True
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t**2 + 1, t)]})
assert recognize_derivative(Poly(t, t), Poly(1, t), DE) == True
def test_recognize_log_derivative():
a = Poly(2*x**2 + 4*x*t - 2*t - x**2*t, t)
d = Poly((2*x + t)*(t + x**2), t)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]})
assert recognize_log_derivative(a, d, DE, z) == True
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)]})
assert recognize_log_derivative(Poly(t + 1, t), Poly(t + x, t), DE) == True
assert recognize_log_derivative(Poly(2, t), Poly(t**2 - 1, t), DE) == True
DE = DifferentialExtension(extension={'D': [Poly(1, x)]})
assert recognize_log_derivative(Poly(1, x), Poly(x**2 - 2, x), DE) == False
assert recognize_log_derivative(Poly(1, x), Poly(x**2 + x, x), DE) == True
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t**2 + 1, t)]})
assert recognize_log_derivative(Poly(1, t), Poly(t**2 - 2, t), DE) == False
assert recognize_log_derivative(Poly(1, t), Poly(t**2 + t, t), DE) == False
def test_residue_reduce():
a = Poly(2*t**2 - t - x**2, t)
d = Poly(t**3 - x**2*t, t)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)], 'Tfuncs': [log]})
assert residue_reduce(a, d, DE, z, invert=False) == \
([(Poly(z**2 - Rational(1, 4), z, domain='ZZ(x)'),
Poly((1 + 3*x*z - 6*z**2 - 2*x**2 + 4*x**2*z**2)*t - x*z + x**2 +
2*x**2*z**2 - 2*z*x**3, t, domain='ZZ(z, x)'))], False)
assert residue_reduce(a, d, DE, z, invert=True) == \
([(Poly(z**2 - Rational(1, 4), z, domain='ZZ(x)'), Poly(t + 2*x*z, t))], False)
assert residue_reduce(Poly(-2/x, t), Poly(t**2 - 1, t,), DE, z, invert=False) == \
([(Poly(z**2 - 1, z, domain='QQ'), Poly(-2*z*t/x - 2/x, t, domain='ZZ(z,x)'))], True)
ans = residue_reduce(Poly(-2/x, t), Poly(t**2 - 1, t), DE, z, invert=True)
assert ans == ([(Poly(z**2 - 1, z, domain='QQ'), Poly(t + z, t))], True)
assert residue_reduce_to_basic(ans[0], DE, z) == -log(-1 + log(x)) + log(1 + log(x))
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(-t**2 - t/x - (1 - nu**2/x**2), t)]})
# TODO: Skip or make faster
assert residue_reduce(Poly((-2*nu**2 - x**4)/(2*x**2)*t - (1 + x**2)/x, t),
Poly(t**2 + 1 + x**2/2, t), DE, z) == \
([(Poly(z + S.Half, z, domain='QQ'), Poly(t**2 + 1 + x**2/2, t,
domain='ZZ(x,nu)'))], True)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1 + t**2, t)]})
assert residue_reduce(Poly(-2*x*t + 1 - x**2, t),
Poly(t**2 + 2*x*t + 1 + x**2, t), DE, z) == \
([(Poly(z**2 + Rational(1, 4), z), Poly(t + x + 2*z, t))], True)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]})
assert residue_reduce(Poly(t, t), Poly(t + sqrt(2), t), DE, z) == \
([(Poly(z - 1, z, domain='QQ'), Poly(t + sqrt(2), t))], True)
def test_integrate_hyperexponential():
# TODO: Add tests for integrate_hyperexponential() from the book
a = Poly((1 + 2*t1 + t1**2 + 2*t1**3)*t**2 + (1 + t1**2)*t + 1 + t1**2, t)
d = Poly(1, t)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1 + t1**2, t1),
Poly(t*(1 + t1**2), t)], 'Tfuncs': [tan, Lambda(i, exp(tan(i)))]})
assert integrate_hyperexponential(a, d, DE) == \
(exp(2*tan(x))*tan(x) + exp(tan(x)), 1 + t1**2, True)
a = Poly((t1**3 + (x + 1)*t1**2 + t1 + x + 2)*t, t)
assert integrate_hyperexponential(a, d, DE) == \
((x + tan(x))*exp(tan(x)), 0, True)
a = Poly(t, t)
d = Poly(1, t)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(2*x*t, t)],
'Tfuncs': [Lambda(i, exp(x**2))]})
assert integrate_hyperexponential(a, d, DE) == \
(0, NonElementaryIntegral(exp(x**2), x), False)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)], 'Tfuncs': [exp]})
assert integrate_hyperexponential(a, d, DE) == (exp(x), 0, True)
a = Poly(25*t**6 - 10*t**5 + 7*t**4 - 8*t**3 + 13*t**2 + 2*t - 1, t)
d = Poly(25*t**6 + 35*t**4 + 11*t**2 + 1, t)
assert integrate_hyperexponential(a, d, DE) == \
(-(11 - 10*exp(x))/(5 + 25*exp(2*x)) + log(1 + exp(2*x)), -1, True)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t0, t0), Poly(t0*t, t)],
'Tfuncs': [exp, Lambda(i, exp(exp(i)))]})
assert integrate_hyperexponential(Poly(2*t0*t**2, t), Poly(1, t), DE) == (exp(2*exp(x)), 0, True)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t0, t0), Poly(-t0*t, t)],
'Tfuncs': [exp, Lambda(i, exp(-exp(i)))]})
assert integrate_hyperexponential(Poly(-27*exp(9) - 162*t0*exp(9) +
27*x*t0*exp(9), t), Poly((36*exp(18) + x**2*exp(18) - 12*x*exp(18))*t, t), DE) == \
(27*exp(exp(x))/(-6*exp(9) + x*exp(9)), 0, True)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)], 'Tfuncs': [exp]})
assert integrate_hyperexponential(Poly(x**2/2*t, t), Poly(1, t), DE) == \
((2 - 2*x + x**2)*exp(x)/2, 0, True)
assert integrate_hyperexponential(Poly(1 + t, t), Poly(t, t), DE) == \
(-exp(-x), 1, True) # x - exp(-x)
assert integrate_hyperexponential(Poly(x, t), Poly(t + 1, t), DE) == \
(0, NonElementaryIntegral(x/(1 + exp(x)), x), False)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t0), Poly(2*x*t1, t1)],
'Tfuncs': [log, Lambda(i, exp(i**2))]})
elem, nonelem, b = integrate_hyperexponential(Poly((8*x**7 - 12*x**5 + 6*x**3 - x)*t1**4 +
(8*t0*x**7 - 8*t0*x**6 - 4*t0*x**5 + 2*t0*x**3 + 2*t0*x**2 - t0*x +
24*x**8 - 36*x**6 - 4*x**5 + 22*x**4 + 4*x**3 - 7*x**2 - x + 1)*t1**3
+ (8*t0*x**8 - 4*t0*x**6 - 16*t0*x**5 - 2*t0*x**4 + 12*t0*x**3 +
t0*x**2 - 2*t0*x + 24*x**9 - 36*x**7 - 8*x**6 + 22*x**5 + 12*x**4 -
7*x**3 - 6*x**2 + x + 1)*t1**2 + (8*t0*x**8 - 8*t0*x**6 - 16*t0*x**5 +
6*t0*x**4 + 10*t0*x**3 - 2*t0*x**2 - t0*x + 8*x**10 - 12*x**8 - 4*x**7
+ 2*x**6 + 12*x**5 + 3*x**4 - 9*x**3 - x**2 + 2*x)*t1 + 8*t0*x**7 -
12*t0*x**6 - 4*t0*x**5 + 8*t0*x**4 - t0*x**2 - 4*x**7 + 4*x**6 +
4*x**5 - 4*x**4 - x**3 + x**2, t1), Poly((8*x**7 - 12*x**5 + 6*x**3 -
x)*t1**4 + (24*x**8 + 8*x**7 - 36*x**6 - 12*x**5 + 18*x**4 + 6*x**3 -
3*x**2 - x)*t1**3 + (24*x**9 + 24*x**8 - 36*x**7 - 36*x**6 + 18*x**5 +
18*x**4 - 3*x**3 - 3*x**2)*t1**2 + (8*x**10 + 24*x**9 - 12*x**8 -
36*x**7 + 6*x**6 + 18*x**5 - x**4 - 3*x**3)*t1 + 8*x**10 - 12*x**8 +
6*x**6 - x**4, t1), DE)
assert factor(elem) == -((x - 1)*log(x)/((x + exp(x**2))*(2*x**2 - 1)))
assert (nonelem, b) == (NonElementaryIntegral(exp(x**2)/(exp(x**2) + 1), x), False)
def test_integrate_hyperexponential_polynomial():
# Without proper cancellation within integrate_hyperexponential_polynomial(),
# this will take a long time to complete, and will return a complicated
# expression
p = Poly((-28*x**11*t0 - 6*x**8*t0 + 6*x**9*t0 - 15*x**8*t0**2 +
15*x**7*t0**2 + 84*x**10*t0**2 - 140*x**9*t0**3 - 20*x**6*t0**3 +
20*x**7*t0**3 - 15*x**6*t0**4 + 15*x**5*t0**4 + 140*x**8*t0**4 -
84*x**7*t0**5 - 6*x**4*t0**5 + 6*x**5*t0**5 + x**3*t0**6 - x**4*t0**6 +
28*x**6*t0**6 - 4*x**5*t0**7 + x**9 - x**10 + 4*x**12)/(-8*x**11*t0 +
28*x**10*t0**2 - 56*x**9*t0**3 + 70*x**8*t0**4 - 56*x**7*t0**5 +
28*x**6*t0**6 - 8*x**5*t0**7 + x**4*t0**8 + x**12)*t1**2 +
(-28*x**11*t0 - 12*x**8*t0 + 12*x**9*t0 - 30*x**8*t0**2 +
30*x**7*t0**2 + 84*x**10*t0**2 - 140*x**9*t0**3 - 40*x**6*t0**3 +
40*x**7*t0**3 - 30*x**6*t0**4 + 30*x**5*t0**4 + 140*x**8*t0**4 -
84*x**7*t0**5 - 12*x**4*t0**5 + 12*x**5*t0**5 - 2*x**4*t0**6 +
2*x**3*t0**6 + 28*x**6*t0**6 - 4*x**5*t0**7 + 2*x**9 - 2*x**10 +
4*x**12)/(-8*x**11*t0 + 28*x**10*t0**2 - 56*x**9*t0**3 +
70*x**8*t0**4 - 56*x**7*t0**5 + 28*x**6*t0**6 - 8*x**5*t0**7 +
x**4*t0**8 + x**12)*t1 + (-2*x**2*t0 + 2*x**3*t0 + x*t0**2 -
x**2*t0**2 + x**3 - x**4)/(-4*x**5*t0 + 6*x**4*t0**2 - 4*x**3*t0**3 +
x**2*t0**4 + x**6), t1, z, expand=False)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t0), Poly(2*x*t1, t1)]})
assert integrate_hyperexponential_polynomial(p, DE, z) == (
Poly((x - t0)*t1**2 + (-2*t0 + 2*x)*t1, t1), Poly(-2*x*t0 + x**2 +
t0**2, t1), True)
DE = DifferentialExtension(extension={'D':[Poly(1, x), Poly(t0, t0)]})
assert integrate_hyperexponential_polynomial(Poly(0, t0), DE, z) == (
Poly(0, t0), Poly(1, t0), True)
def test_integrate_hyperexponential_returns_piecewise():
a, b = symbols('a b')
DE = DifferentialExtension(a**x, x)
assert integrate_hyperexponential(DE.fa, DE.fd, DE) == (Piecewise(
(exp(x*log(a))/log(a), Ne(log(a), 0)), (x, True)), 0, True)
DE = DifferentialExtension(a**(b*x), x)
assert integrate_hyperexponential(DE.fa, DE.fd, DE) == (Piecewise(
(exp(b*x*log(a))/(b*log(a)), Ne(b*log(a), 0)), (x, True)), 0, True)
DE = DifferentialExtension(exp(a*x), x)
assert integrate_hyperexponential(DE.fa, DE.fd, DE) == (Piecewise(
(exp(a*x)/a, Ne(a, 0)), (x, True)), 0, True)
DE = DifferentialExtension(x*exp(a*x), x)
assert integrate_hyperexponential(DE.fa, DE.fd, DE) == (Piecewise(
((a*x - 1)*exp(a*x)/a**2, Ne(a**2, 0)), (x**2/2, True)), 0, True)
DE = DifferentialExtension(x**2*exp(a*x), x)
assert integrate_hyperexponential(DE.fa, DE.fd, DE) == (Piecewise(
((x**2*a**2 - 2*a*x + 2)*exp(a*x)/a**3, Ne(a**3, 0)),
(x**3/3, True)), 0, True)
DE = DifferentialExtension(x**y + z, y)
assert integrate_hyperexponential(DE.fa, DE.fd, DE) == (Piecewise(
(exp(log(x)*y)/log(x), Ne(log(x), 0)), (y, True)), z, True)
DE = DifferentialExtension(x**y + z + x**(2*y), y)
assert integrate_hyperexponential(DE.fa, DE.fd, DE) == (Piecewise(
((exp(2*log(x)*y)*log(x) +
2*exp(log(x)*y)*log(x))/(2*log(x)**2), Ne(2*log(x)**2, 0)),
(2*y, True),
), z, True)
# TODO: Add a test where two different parts of the extension use a
# Piecewise, like y**x + z**x.
def test_issue_13947():
a, t, s = symbols('a t s')
assert risch_integrate(2**(-pi)/(2**t + 1), t) == \
2**(-pi)*t - 2**(-pi)*log(2**t + 1)/log(2)
assert risch_integrate(a**(t - s)/(a**t + 1), t) == \
exp(-s*log(a))*log(a**t + 1)/log(a)
def test_integrate_primitive():
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t)],
'Tfuncs': [log]})
assert integrate_primitive(Poly(t, t), Poly(1, t), DE) == (x*log(x), -1, True)
assert integrate_primitive(Poly(x, t), Poly(t, t), DE) == (0, NonElementaryIntegral(x/log(x), x), False)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t1), Poly(1/(x + 1), t2)],
'Tfuncs': [log, Lambda(i, log(i + 1))]})
assert integrate_primitive(Poly(t1, t2), Poly(t2, t2), DE) == \
(0, NonElementaryIntegral(log(x)/log(1 + x), x), False)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t1), Poly(1/(x*t1), t2)],
'Tfuncs': [log, Lambda(i, log(log(i)))]})
assert integrate_primitive(Poly(t2, t2), Poly(t1, t2), DE) == \
(0, NonElementaryIntegral(log(log(x))/log(x), x), False)
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(1/x, t0)],
'Tfuncs': [log]})
assert integrate_primitive(Poly(x**2*t0**3 + (3*x**2 + x)*t0**2 + (3*x**2
+ 2*x)*t0 + x**2 + x, t0), Poly(x**2*t0**4 + 4*x**2*t0**3 + 6*x**2*t0**2 +
4*x**2*t0 + x**2, t0), DE) == \
(-1/(log(x) + 1), NonElementaryIntegral(1/(log(x) + 1), x), False)
def test_integrate_hypertangent_polynomial():
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t**2 + 1, t)]})
assert integrate_hypertangent_polynomial(Poly(t**2 + x*t + 1, t), DE) == \
(Poly(t, t), Poly(x/2, t))
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(a*(t**2 + 1), t)]})
assert integrate_hypertangent_polynomial(Poly(t**5, t), DE) == \
(Poly(1/(4*a)*t**4 - 1/(2*a)*t**2, t), Poly(1/(2*a), t))
def test_integrate_nonlinear_no_specials():
a, d, = Poly(x**2*t**5 + x*t**4 - nu**2*t**3 - x*(x**2 + 1)*t**2 - (x**2 -
nu**2)*t - x**5/4, t), Poly(x**2*t**4 + x**2*(x**2 + 2)*t**2 + x**2 + x**4 + x**6/4, t)
# f(x) == phi_nu(x), the logarithmic derivative of J_v, the Bessel function,
# which has no specials (see Chapter 5, note 4 of Bronstein's book).
f = Function('phi_nu')
DE = DifferentialExtension(extension={'D': [Poly(1, x),
Poly(-t**2 - t/x - (1 - nu**2/x**2), t)], 'Tfuncs': [f]})
assert integrate_nonlinear_no_specials(a, d, DE) == \
(-log(1 + f(x)**2 + x**2/2)/2 + (- 4 - x**2)/(4 + 2*x**2 + 4*f(x)**2), True)
assert integrate_nonlinear_no_specials(Poly(t, t), Poly(1, t), DE) == \
(0, False)
def test_integer_powers():
assert integer_powers([x, x/2, x**2 + 1, x*Rational(2, 3)]) == [
(x/6, [(x, 6), (x/2, 3), (x*Rational(2, 3), 4)]),
(1 + x**2, [(1 + x**2, 1)])]
def test_DifferentialExtension_exp():
assert DifferentialExtension(exp(x) + exp(x**2), x)._important_attrs == \
(Poly(t1 + t0, t1), Poly(1, t1), [Poly(1, x,), Poly(t0, t0),
Poly(2*x*t1, t1)], [x, t0, t1], [Lambda(i, exp(i)),
Lambda(i, exp(i**2))], [], [None, 'exp', 'exp'], [None, x, x**2])
assert DifferentialExtension(exp(x) + exp(2*x), x)._important_attrs == \
(Poly(t0**2 + t0, t0), Poly(1, t0), [Poly(1, x), Poly(t0, t0)], [x, t0],
[Lambda(i, exp(i))], [], [None, 'exp'], [None, x])
assert DifferentialExtension(exp(x) + exp(x/2), x)._important_attrs == \
(Poly(t0**2 + t0, t0), Poly(1, t0), [Poly(1, x), Poly(t0/2, t0)],
[x, t0], [Lambda(i, exp(i/2))], [], [None, 'exp'], [None, x/2])
assert DifferentialExtension(exp(x) + exp(x**2) + exp(x + x**2), x)._important_attrs == \
(Poly((1 + t0)*t1 + t0, t1), Poly(1, t1), [Poly(1, x), Poly(t0, t0),
Poly(2*x*t1, t1)], [x, t0, t1], [Lambda(i, exp(i)),
Lambda(i, exp(i**2))], [], [None, 'exp', 'exp'], [None, x, x**2])
assert DifferentialExtension(exp(x) + exp(x**2) + exp(x + x**2 + 1), x)._important_attrs == \
(Poly((1 + S.Exp1*t0)*t1 + t0, t1), Poly(1, t1), [Poly(1, x),
Poly(t0, t0), Poly(2*x*t1, t1)], [x, t0, t1], [Lambda(i, exp(i)),
Lambda(i, exp(i**2))], [], [None, 'exp', 'exp'], [None, x, x**2])
assert DifferentialExtension(exp(x) + exp(x**2) + exp(x/2 + x**2), x)._important_attrs == \
(Poly((t0 + 1)*t1 + t0**2, t1), Poly(1, t1), [Poly(1, x),
Poly(t0/2, t0), Poly(2*x*t1, t1)], [x, t0, t1],
[Lambda(i, exp(i/2)), Lambda(i, exp(i**2))],
[(exp(x/2), sqrt(exp(x)))], [None, 'exp', 'exp'], [None, x/2, x**2])
assert DifferentialExtension(exp(x) + exp(x**2) + exp(x/2 + x**2 + 3), x)._important_attrs == \
(Poly((t0*exp(3) + 1)*t1 + t0**2, t1), Poly(1, t1), [Poly(1, x),
Poly(t0/2, t0), Poly(2*x*t1, t1)], [x, t0, t1], [Lambda(i, exp(i/2)),
Lambda(i, exp(i**2))], [(exp(x/2), sqrt(exp(x)))], [None, 'exp', 'exp'],
[None, x/2, x**2])
assert DifferentialExtension(sqrt(exp(x)), x)._important_attrs == \
(Poly(t0, t0), Poly(1, t0), [Poly(1, x), Poly(t0/2, t0)], [x, t0],
[Lambda(i, exp(i/2))], [(exp(x/2), sqrt(exp(x)))], [None, 'exp'], [None, x/2])
assert DifferentialExtension(exp(x/2), x)._important_attrs == \
(Poly(t0, t0), Poly(1, t0), [Poly(1, x), Poly(t0/2, t0)], [x, t0],
[Lambda(i, exp(i/2))], [], [None, 'exp'], [None, x/2])
def test_DifferentialExtension_log():
assert DifferentialExtension(log(x)*log(x + 1)*log(2*x**2 + 2*x), x)._important_attrs == \
(Poly(t0*t1**2 + (t0*log(2) + t0**2)*t1, t1), Poly(1, t1),
[Poly(1, x), Poly(1/x, t0),
Poly(1/(x + 1), t1, expand=False)], [x, t0, t1],
[Lambda(i, log(i)), Lambda(i, log(i + 1))], [], [None, 'log', 'log'],
[None, x, x + 1])
assert DifferentialExtension(x**x*log(x), x)._important_attrs == \
(Poly(t0*t1, t1), Poly(1, t1), [Poly(1, x), Poly(1/x, t0),
Poly((1 + t0)*t1, t1)], [x, t0, t1], [Lambda(i, log(i)),
Lambda(i, exp(t0*i))], [(exp(x*log(x)), x**x)], [None, 'log', 'exp'],
[None, x, t0*x])
def test_DifferentialExtension_symlog():
# See comment on test_risch_integrate below
assert DifferentialExtension(log(x**x), x)._important_attrs == \
(Poly(t0*x, t1), Poly(1, t1), [Poly(1, x), Poly(1/x, t0), Poly((t0 +
1)*t1, t1)], [x, t0, t1], [Lambda(i, log(i)), Lambda(i, exp(i*t0))],
[(exp(x*log(x)), x**x)], [None, 'log', 'exp'], [None, x, t0*x])
assert DifferentialExtension(log(x**y), x)._important_attrs == \
(Poly(y*t0, t0), Poly(1, t0), [Poly(1, x), Poly(1/x, t0)], [x, t0],
[Lambda(i, log(i))], [(y*log(x), log(x**y))], [None, 'log'],
[None, x])
assert DifferentialExtension(log(sqrt(x)), x)._important_attrs == \
(Poly(t0, t0), Poly(2, t0), [Poly(1, x), Poly(1/x, t0)], [x, t0],
[Lambda(i, log(i))], [(log(x)/2, log(sqrt(x)))], [None, 'log'],
[None, x])
def test_DifferentialExtension_handle_first():
assert DifferentialExtension(exp(x)*log(x), x, handle_first='log')._important_attrs == \
(Poly(t0*t1, t1), Poly(1, t1), [Poly(1, x), Poly(1/x, t0),
Poly(t1, t1)], [x, t0, t1], [Lambda(i, log(i)), Lambda(i, exp(i))],
[], [None, 'log', 'exp'], [None, x, x])
assert DifferentialExtension(exp(x)*log(x), x, handle_first='exp')._important_attrs == \
(Poly(t0*t1, t1), Poly(1, t1), [Poly(1, x), Poly(t0, t0),
Poly(1/x, t1)], [x, t0, t1], [Lambda(i, exp(i)), Lambda(i, log(i))],
[], [None, 'exp', 'log'], [None, x, x])
# This one must have the log first, regardless of what we set it to
# (because the log is inside of the exponential: x**x == exp(x*log(x)))
assert DifferentialExtension(-x**x*log(x)**2 + x**x - x**x/x, x,
handle_first='exp')._important_attrs == \
DifferentialExtension(-x**x*log(x)**2 + x**x - x**x/x, x,
handle_first='log')._important_attrs == \
(Poly((-1 + x - x*t0**2)*t1, t1), Poly(x, t1),
[Poly(1, x), Poly(1/x, t0), Poly((1 + t0)*t1, t1)], [x, t0, t1],
[Lambda(i, log(i)), Lambda(i, exp(t0*i))], [(exp(x*log(x)), x**x)],
[None, 'log', 'exp'], [None, x, t0*x])
def test_DifferentialExtension_all_attrs():
# Test 'unimportant' attributes
DE = DifferentialExtension(exp(x)*log(x), x, handle_first='exp')
assert DE.f == exp(x)*log(x)
assert DE.newf == t0*t1
assert DE.x == x
assert DE.cases == ['base', 'exp', 'primitive']
assert DE.case == 'primitive'
assert DE.level == -1
assert DE.t == t1 == DE.T[DE.level]
assert DE.d == Poly(1/x, t1) == DE.D[DE.level]
raises(ValueError, lambda: DE.increment_level())
DE.decrement_level()
assert DE.level == -2
assert DE.t == t0 == DE.T[DE.level]
assert DE.d == Poly(t0, t0) == DE.D[DE.level]
assert DE.case == 'exp'
DE.decrement_level()
assert DE.level == -3
assert DE.t == x == DE.T[DE.level] == DE.x
assert DE.d == Poly(1, x) == DE.D[DE.level]
assert DE.case == 'base'
raises(ValueError, lambda: DE.decrement_level())
DE.increment_level()
DE.increment_level()
assert DE.level == -1
assert DE.t == t1 == DE.T[DE.level]
assert DE.d == Poly(1/x, t1) == DE.D[DE.level]
assert DE.case == 'primitive'
# Test methods
assert DE.indices('log') == [2]
assert DE.indices('exp') == [1]
def test_DifferentialExtension_extension_flag():
raises(ValueError, lambda: DifferentialExtension(extension={'T': [x, t]}))
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)]})
assert DE._important_attrs == (None, None, [Poly(1, x), Poly(t, t)], [x, t],
None, None, None, None)
assert DE.d == Poly(t, t)
assert DE.t == t
assert DE.level == -1
assert DE.cases == ['base', 'exp']
assert DE.x == x
assert DE.case == 'exp'
DE = DifferentialExtension(extension={'D': [Poly(1, x), Poly(t, t)],
'exts': [None, 'exp'], 'extargs': [None, x]})
assert DE._important_attrs == (None, None, [Poly(1, x), Poly(t, t)], [x, t],
None, None, [None, 'exp'], [None, x])
raises(ValueError, lambda: DifferentialExtension())
def test_DifferentialExtension_misc():
# Odd ends
assert DifferentialExtension(sin(y)*exp(x), x)._important_attrs == \
(Poly(sin(y)*t0, t0, domain='ZZ[sin(y)]'), Poly(1, t0, domain='ZZ'),
[Poly(1, x, domain='ZZ'), Poly(t0, t0, domain='ZZ')], [x, t0],
[Lambda(i, exp(i))], [], [None, 'exp'], [None, x])
raises(NotImplementedError, lambda: DifferentialExtension(sin(x), x))
assert DifferentialExtension(10**x, x)._important_attrs == \
(Poly(t0, t0), Poly(1, t0), [Poly(1, x), Poly(log(10)*t0, t0)], [x, t0],
[Lambda(i, exp(i*log(10)))], [(exp(x*log(10)), 10**x)], [None, 'exp'],
[None, x*log(10)])
assert DifferentialExtension(log(x) + log(x**2), x)._important_attrs in [
(Poly(3*t0, t0), Poly(2, t0), [Poly(1, x), Poly(2/x, t0)], [x, t0],
[Lambda(i, log(i**2))], [], [None, ], [], [1], [x**2]),
(Poly(3*t0, t0), Poly(1, t0), [Poly(1, x), Poly(1/x, t0)], [x, t0],
[Lambda(i, log(i))], [], [None, 'log'], [None, x])]
assert DifferentialExtension(S.Zero, x)._important_attrs == \
(Poly(0, x), Poly(1, x), [Poly(1, x)], [x], [], [], [None], [None])
assert DifferentialExtension(tan(atan(x).rewrite(log)), x)._important_attrs == \
(Poly(x, x), Poly(1, x), [Poly(1, x)], [x], [], [], [None], [None])
def test_DifferentialExtension_Rothstein():
# Rothstein's integral
f = (2581284541*exp(x) + 1757211400)/(39916800*exp(3*x) +
119750400*exp(x)**2 + 119750400*exp(x) + 39916800)*exp(1/(exp(x) + 1) - 10*x)
assert DifferentialExtension(f, x)._important_attrs == \
(Poly((1757211400 + 2581284541*t0)*t1, t1), Poly(39916800 +
119750400*t0 + 119750400*t0**2 + 39916800*t0**3, t1),
[Poly(1, x), Poly(t0, t0), Poly(-(10 + 21*t0 + 10*t0**2)/(1 + 2*t0 +
t0**2)*t1, t1, domain='ZZ(t0)')], [x, t0, t1],
[Lambda(i, exp(i)), Lambda(i, exp(1/(t0 + 1) - 10*i))], [],
[None, 'exp', 'exp'], [None, x, 1/(t0 + 1) - 10*x])
class _TestingException(Exception):
"""Dummy Exception class for testing."""
pass
def test_DecrementLevel():
DE = DifferentialExtension(x*log(exp(x) + 1), x)
assert DE.level == -1
assert DE.t == t1
assert DE.d == Poly(t0/(t0 + 1), t1)
assert DE.case == 'primitive'
with DecrementLevel(DE):
assert DE.level == -2
assert DE.t == t0
assert DE.d == Poly(t0, t0)
assert DE.case == 'exp'
with DecrementLevel(DE):
assert DE.level == -3
assert DE.t == x
assert DE.d == Poly(1, x)
assert DE.case == 'base'
assert DE.level == -2
assert DE.t == t0
assert DE.d == Poly(t0, t0)
assert DE.case == 'exp'
assert DE.level == -1
assert DE.t == t1
assert DE.d == Poly(t0/(t0 + 1), t1)
assert DE.case == 'primitive'
# Test that __exit__ is called after an exception correctly
try:
with DecrementLevel(DE):
raise _TestingException
except _TestingException:
pass
else:
raise AssertionError("Did not raise.")
assert DE.level == -1
assert DE.t == t1
assert DE.d == Poly(t0/(t0 + 1), t1)
assert DE.case == 'primitive'
def test_risch_integrate():
assert risch_integrate(t0*exp(x), x) == t0*exp(x)
assert risch_integrate(sin(x), x, rewrite_complex=True) == -exp(I*x)/2 - exp(-I*x)/2
# From my GSoC writeup
assert risch_integrate((1 + 2*x**2 + x**4 + 2*x**3*exp(2*x**2))/
(x**4*exp(x**2) + 2*x**2*exp(x**2) + exp(x**2)), x) == \
NonElementaryIntegral(exp(-x**2), x) + exp(x**2)/(1 + x**2)
assert risch_integrate(0, x) == 0
# also tests prde_cancel()
e1 = log(x/exp(x) + 1)
ans1 = risch_integrate(e1, x)
assert ans1 == (x*log(x*exp(-x) + 1) + NonElementaryIntegral((x**2 - x)/(x + exp(x)), x))
assert cancel(diff(ans1, x) - e1) == 0
# also tests issue #10798
e2 = (log(-1/y)/2 - log(1/y)/2)/y - (log(1 - 1/y)/2 - log(1 + 1/y)/2)/y
ans2 = risch_integrate(e2, y)
assert ans2 == log(1/y)*log(1 - 1/y)/2 - log(1/y)*log(1 + 1/y)/2 + \
NonElementaryIntegral((I*pi*y**2 - 2*y*log(1/y) - I*pi)/(2*y**3 - 2*y), y)
assert expand_log(cancel(diff(ans2, y) - e2), force=True) == 0
# These are tested here in addition to in test_DifferentialExtension above
# (symlogs) to test that backsubs works correctly. The integrals should be
# written in terms of the original logarithms in the integrands.
# XXX: Unfortunately, making backsubs work on this one is a little
# trickier, because x**x is converted to exp(x*log(x)), and so log(x**x)
# is converted to x*log(x). (x**2*log(x)).subs(x*log(x), log(x**x)) is
# smart enough, the issue is that these splits happen at different places
# in the algorithm. Maybe a heuristic is in order
assert risch_integrate(log(x**x), x) == x**2*log(x)/2 - x**2/4
assert risch_integrate(log(x**y), x) == x*log(x**y) - x*y
assert risch_integrate(log(sqrt(x)), x) == x*log(sqrt(x)) - x/2
def test_risch_integrate_float():
assert risch_integrate((-60*exp(x) - 19.2*exp(4*x))*exp(4*x), x) == -2.4*exp(8*x) - 12.0*exp(5*x)
def test_NonElementaryIntegral():
assert isinstance(risch_integrate(exp(x**2), x), NonElementaryIntegral)
assert isinstance(risch_integrate(x**x*log(x), x), NonElementaryIntegral)
# Make sure methods of Integral still give back a NonElementaryIntegral
assert isinstance(NonElementaryIntegral(x**x*t0, x).subs(t0, log(x)), NonElementaryIntegral)
def test_xtothex():
a = risch_integrate(x**x, x)
assert a == NonElementaryIntegral(x**x, x)
assert isinstance(a, NonElementaryIntegral)
def test_DifferentialExtension_equality():
DE1 = DE2 = DifferentialExtension(log(x), x)
assert DE1 == DE2
def test_DifferentialExtension_printing():
DE = DifferentialExtension(exp(2*x**2) + log(exp(x**2) + 1), x)
assert repr(DE) == ("DifferentialExtension(dict([('f', exp(2*x**2) + log(exp(x**2) + 1)), "
"('x', x), ('T', [x, t0, t1]), ('D', [Poly(1, x, domain='ZZ'), Poly(2*x*t0, t0, domain='ZZ[x]'), "
"Poly(2*t0*x/(t0 + 1), t1, domain='ZZ(x,t0)')]), ('fa', Poly(t1 + t0**2, t1, domain='ZZ[t0]')), "
"('fd', Poly(1, t1, domain='ZZ')), ('Tfuncs', [Lambda(i, exp(i**2)), Lambda(i, log(t0 + 1))]), "
"('backsubs', []), ('exts', [None, 'exp', 'log']), ('extargs', [None, x**2, t0 + 1]), "
"('cases', ['base', 'exp', 'primitive']), ('case', 'primitive'), ('t', t1), "
"('d', Poly(2*t0*x/(t0 + 1), t1, domain='ZZ(x,t0)')), ('newf', t0**2 + t1), ('level', -1), "
"('dummy', False)]))")
assert str(DE) == ("DifferentialExtension({fa=Poly(t1 + t0**2, t1, domain='ZZ[t0]'), "
"fd=Poly(1, t1, domain='ZZ'), D=[Poly(1, x, domain='ZZ'), Poly(2*x*t0, t0, domain='ZZ[x]'), "
"Poly(2*t0*x/(t0 + 1), t1, domain='ZZ(x,t0)')]})")
def test_issue_23948():
f = (
( (-2*x**5 + 28*x**4 - 144*x**3 + 324*x**2 - 270*x)*log(x)**2
+(-4*x**6 + 56*x**5 - 288*x**4 + 648*x**3 - 540*x**2)*log(x)
+(2*x**5 - 28*x**4 + 144*x**3 - 324*x**2 + 270*x)*exp(x)
+(2*x**5 - 28*x**4 + 144*x**3 - 324*x**2 + 270*x)*log(5)
-2*x**7 + 26*x**6 - 116*x**5 + 180*x**4 + 54*x**3 - 270*x**2
)*log(-log(x)**2 - 2*x*log(x) + exp(x) + log(5) - x**2 - x)**2
+( (4*x**5 - 44*x**4 + 168*x**3 - 216*x**2 - 108*x + 324)*log(x)
+(-2*x**5 + 24*x**4 - 108*x**3 + 216*x**2 - 162*x)*exp(x)
+4*x**6 - 42*x**5 + 144*x**4 - 108*x**3 - 324*x**2 + 486*x
)*log(-log(x)**2 - 2*x*log(x) + exp(x) + log(5) - x**2 - x)
)/(x*exp(x)**2*log(x)**2 + 2*x**2*exp(x)**2*log(x) - x*exp(x)**3
+(-x*log(5) + x**3 + x**2)*exp(x)**2)
F = ((x**4 - 12*x**3 + 54*x**2 - 108*x + 81)*exp(-2*x)
*log(-x**2 - 2*x*log(x) - x + exp(x) - log(x)**2 + log(5))**2)
assert risch_integrate(f, x) == F

View File

@ -0,0 +1,22 @@
from sympy.integrals.singularityfunctions import singularityintegrate
from sympy.core.function import Function
from sympy.core.symbol import symbols
from sympy.functions.special.singularity_functions import SingularityFunction
x, a, n, y = symbols('x a n y')
f = Function('f')
def test_singularityintegrate():
assert singularityintegrate(x, x) is None
assert singularityintegrate(x + SingularityFunction(x, 9, 1), x) is None
assert 4*singularityintegrate(SingularityFunction(x, a, 3), x) == 4*SingularityFunction(x, a, 4)/4
assert singularityintegrate(5*SingularityFunction(x, 5, -2), x) == 5*SingularityFunction(x, 5, -1)
assert singularityintegrate(6*SingularityFunction(x, 5, -1), x) == 6*SingularityFunction(x, 5, 0)
assert singularityintegrate(x*SingularityFunction(x, 0, -1), x) == 0
assert singularityintegrate((x - 5)*SingularityFunction(x, 5, -1), x) == 0
assert singularityintegrate(SingularityFunction(x, 0, -1) * f(x), x) == f(0) * SingularityFunction(x, 0, 0)
assert singularityintegrate(SingularityFunction(x, 1, -1) * f(x), x) == f(1) * SingularityFunction(x, 1, 0)
assert singularityintegrate(y*SingularityFunction(x, 0, -1)**2, x) == \
y*SingularityFunction(0, 0, -1)*SingularityFunction(x, 0, 0)

View File

@ -0,0 +1,636 @@
from sympy.integrals.transforms import (
mellin_transform, inverse_mellin_transform,
fourier_transform, inverse_fourier_transform,
sine_transform, inverse_sine_transform,
cosine_transform, inverse_cosine_transform,
hankel_transform, inverse_hankel_transform,
FourierTransform, SineTransform, CosineTransform, InverseFourierTransform,
InverseSineTransform, InverseCosineTransform, IntegralTransformError)
from sympy.integrals.laplace import (
laplace_transform, inverse_laplace_transform)
from sympy.core.function import Function, expand_mul
from sympy.core import EulerGamma
from sympy.core.numbers import I, Rational, oo, pi
from sympy.core.singleton import S
from sympy.core.symbol import Symbol, symbols
from sympy.functions.combinatorial.factorials import factorial
from sympy.functions.elementary.complexes import re, unpolarify
from sympy.functions.elementary.exponential import exp, exp_polar, log
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.functions.elementary.trigonometric import atan, cos, sin, tan
from sympy.functions.special.bessel import besseli, besselj, besselk, bessely
from sympy.functions.special.delta_functions import Heaviside
from sympy.functions.special.error_functions import erf, expint
from sympy.functions.special.gamma_functions import gamma
from sympy.functions.special.hyper import meijerg
from sympy.simplify.gammasimp import gammasimp
from sympy.simplify.hyperexpand import hyperexpand
from sympy.simplify.trigsimp import trigsimp
from sympy.testing.pytest import XFAIL, slow, skip, raises
from sympy.abc import x, s, a, b, c, d
nu, beta, rho = symbols('nu beta rho')
def test_undefined_function():
from sympy.integrals.transforms import MellinTransform
f = Function('f')
assert mellin_transform(f(x), x, s) == MellinTransform(f(x), x, s)
assert mellin_transform(f(x) + exp(-x), x, s) == \
(MellinTransform(f(x), x, s) + gamma(s + 1)/s, (0, oo), True)
def test_free_symbols():
f = Function('f')
assert mellin_transform(f(x), x, s).free_symbols == {s}
assert mellin_transform(f(x)*a, x, s).free_symbols == {s, a}
def test_as_integral():
from sympy.integrals.integrals import Integral
f = Function('f')
assert mellin_transform(f(x), x, s).rewrite('Integral') == \
Integral(x**(s - 1)*f(x), (x, 0, oo))
assert fourier_transform(f(x), x, s).rewrite('Integral') == \
Integral(f(x)*exp(-2*I*pi*s*x), (x, -oo, oo))
assert laplace_transform(f(x), x, s, noconds=True).rewrite('Integral') == \
Integral(f(x)*exp(-s*x), (x, 0, oo))
assert str(2*pi*I*inverse_mellin_transform(f(s), s, x, (a, b)).rewrite('Integral')) \
== "Integral(f(s)/x**s, (s, _c - oo*I, _c + oo*I))"
assert str(2*pi*I*inverse_laplace_transform(f(s), s, x).rewrite('Integral')) == \
"Integral(f(s)*exp(s*x), (s, _c - oo*I, _c + oo*I))"
assert inverse_fourier_transform(f(s), s, x).rewrite('Integral') == \
Integral(f(s)*exp(2*I*pi*s*x), (s, -oo, oo))
# NOTE this is stuck in risch because meijerint cannot handle it
@slow
@XFAIL
def test_mellin_transform_fail():
skip("Risch takes forever.")
MT = mellin_transform
bpos = symbols('b', positive=True)
# bneg = symbols('b', negative=True)
expr = (sqrt(x + b**2) + b)**a/sqrt(x + b**2)
# TODO does not work with bneg, argument wrong. Needs changes to matching.
assert MT(expr.subs(b, -bpos), x, s) == \
((-1)**(a + 1)*2**(a + 2*s)*bpos**(a + 2*s - 1)*gamma(a + s)
*gamma(1 - a - 2*s)/gamma(1 - s),
(-re(a), -re(a)/2 + S.Half), True)
expr = (sqrt(x + b**2) + b)**a
assert MT(expr.subs(b, -bpos), x, s) == \
(
2**(a + 2*s)*a*bpos**(a + 2*s)*gamma(-a - 2*
s)*gamma(a + s)/gamma(-s + 1),
(-re(a), -re(a)/2), True)
# Test exponent 1:
assert MT(expr.subs({b: -bpos, a: 1}), x, s) == \
(-bpos**(2*s + 1)*gamma(s)*gamma(-s - S.Half)/(2*sqrt(pi)),
(-1, Rational(-1, 2)), True)
def test_mellin_transform():
from sympy.functions.elementary.miscellaneous import (Max, Min)
MT = mellin_transform
bpos = symbols('b', positive=True)
# 8.4.2
assert MT(x**nu*Heaviside(x - 1), x, s) == \
(-1/(nu + s), (-oo, -re(nu)), True)
assert MT(x**nu*Heaviside(1 - x), x, s) == \
(1/(nu + s), (-re(nu), oo), True)
assert MT((1 - x)**(beta - 1)*Heaviside(1 - x), x, s) == \
(gamma(beta)*gamma(s)/gamma(beta + s), (0, oo), re(beta) > 0)
assert MT((x - 1)**(beta - 1)*Heaviside(x - 1), x, s) == \
(gamma(beta)*gamma(1 - beta - s)/gamma(1 - s),
(-oo, 1 - re(beta)), re(beta) > 0)
assert MT((1 + x)**(-rho), x, s) == \
(gamma(s)*gamma(rho - s)/gamma(rho), (0, re(rho)), True)
assert MT(abs(1 - x)**(-rho), x, s) == (
2*sin(pi*rho/2)*gamma(1 - rho)*
cos(pi*(s - rho/2))*gamma(s)*gamma(rho-s)/pi,
(0, re(rho)), re(rho) < 1)
mt = MT((1 - x)**(beta - 1)*Heaviside(1 - x)
+ a*(x - 1)**(beta - 1)*Heaviside(x - 1), x, s)
assert mt[1], mt[2] == ((0, -re(beta) + 1), re(beta) > 0)
assert MT((x**a - b**a)/(x - b), x, s)[0] == \
pi*b**(a + s - 1)*sin(pi*a)/(sin(pi*s)*sin(pi*(a + s)))
assert MT((x**a - bpos**a)/(x - bpos), x, s) == \
(pi*bpos**(a + s - 1)*sin(pi*a)/(sin(pi*s)*sin(pi*(a + s))),
(Max(0, -re(a)), Min(1, 1 - re(a))), True)
expr = (sqrt(x + b**2) + b)**a
assert MT(expr.subs(b, bpos), x, s) == \
(-a*(2*bpos)**(a + 2*s)*gamma(s)*gamma(-a - 2*s)/gamma(-a - s + 1),
(0, -re(a)/2), True)
expr = (sqrt(x + b**2) + b)**a/sqrt(x + b**2)
assert MT(expr.subs(b, bpos), x, s) == \
(2**(a + 2*s)*bpos**(a + 2*s - 1)*gamma(s)
*gamma(1 - a - 2*s)/gamma(1 - a - s),
(0, -re(a)/2 + S.Half), True)
# 8.4.2
assert MT(exp(-x), x, s) == (gamma(s), (0, oo), True)
assert MT(exp(-1/x), x, s) == (gamma(-s), (-oo, 0), True)
# 8.4.5
assert MT(log(x)**4*Heaviside(1 - x), x, s) == (24/s**5, (0, oo), True)
assert MT(log(x)**3*Heaviside(x - 1), x, s) == (6/s**4, (-oo, 0), True)
assert MT(log(x + 1), x, s) == (pi/(s*sin(pi*s)), (-1, 0), True)
assert MT(log(1/x + 1), x, s) == (pi/(s*sin(pi*s)), (0, 1), True)
assert MT(log(abs(1 - x)), x, s) == (pi/(s*tan(pi*s)), (-1, 0), True)
assert MT(log(abs(1 - 1/x)), x, s) == (pi/(s*tan(pi*s)), (0, 1), True)
# 8.4.14
assert MT(erf(sqrt(x)), x, s) == \
(-gamma(s + S.Half)/(sqrt(pi)*s), (Rational(-1, 2), 0), True)
def test_mellin_transform2():
MT = mellin_transform
# TODO we cannot currently do these (needs summation of 3F2(-1))
# this also implies that they cannot be written as a single g-function
# (although this is possible)
mt = MT(log(x)/(x + 1), x, s)
assert mt[1:] == ((0, 1), True)
assert not hyperexpand(mt[0], allow_hyper=True).has(meijerg)
mt = MT(log(x)**2/(x + 1), x, s)
assert mt[1:] == ((0, 1), True)
assert not hyperexpand(mt[0], allow_hyper=True).has(meijerg)
mt = MT(log(x)/(x + 1)**2, x, s)
assert mt[1:] == ((0, 2), True)
assert not hyperexpand(mt[0], allow_hyper=True).has(meijerg)
@slow
def test_mellin_transform_bessel():
from sympy.functions.elementary.miscellaneous import Max
MT = mellin_transform
# 8.4.19
assert MT(besselj(a, 2*sqrt(x)), x, s) == \
(gamma(a/2 + s)/gamma(a/2 - s + 1), (-re(a)/2, Rational(3, 4)), True)
assert MT(sin(sqrt(x))*besselj(a, sqrt(x)), x, s) == \
(2**a*gamma(-2*s + S.Half)*gamma(a/2 + s + S.Half)/(
gamma(-a/2 - s + 1)*gamma(a - 2*s + 1)), (
-re(a)/2 - S.Half, Rational(1, 4)), True)
assert MT(cos(sqrt(x))*besselj(a, sqrt(x)), x, s) == \
(2**a*gamma(a/2 + s)*gamma(-2*s + S.Half)/(
gamma(-a/2 - s + S.Half)*gamma(a - 2*s + 1)), (
-re(a)/2, Rational(1, 4)), True)
assert MT(besselj(a, sqrt(x))**2, x, s) == \
(gamma(a + s)*gamma(S.Half - s)
/ (sqrt(pi)*gamma(1 - s)*gamma(1 + a - s)),
(-re(a), S.Half), True)
assert MT(besselj(a, sqrt(x))*besselj(-a, sqrt(x)), x, s) == \
(gamma(s)*gamma(S.Half - s)
/ (sqrt(pi)*gamma(1 - a - s)*gamma(1 + a - s)),
(0, S.Half), True)
# NOTE: prudnikov gives the strip below as (1/2 - re(a), 1). As far as
# I can see this is wrong (since besselj(z) ~ 1/sqrt(z) for z large)
assert MT(besselj(a - 1, sqrt(x))*besselj(a, sqrt(x)), x, s) == \
(gamma(1 - s)*gamma(a + s - S.Half)
/ (sqrt(pi)*gamma(Rational(3, 2) - s)*gamma(a - s + S.Half)),
(S.Half - re(a), S.Half), True)
assert MT(besselj(a, sqrt(x))*besselj(b, sqrt(x)), x, s) == \
(4**s*gamma(1 - 2*s)*gamma((a + b)/2 + s)
/ (gamma(1 - s + (b - a)/2)*gamma(1 - s + (a - b)/2)
*gamma( 1 - s + (a + b)/2)),
(-(re(a) + re(b))/2, S.Half), True)
assert MT(besselj(a, sqrt(x))**2 + besselj(-a, sqrt(x))**2, x, s)[1:] == \
((Max(re(a), -re(a)), S.Half), True)
# Section 8.4.20
assert MT(bessely(a, 2*sqrt(x)), x, s) == \
(-cos(pi*(a/2 - s))*gamma(s - a/2)*gamma(s + a/2)/pi,
(Max(-re(a)/2, re(a)/2), Rational(3, 4)), True)
assert MT(sin(sqrt(x))*bessely(a, sqrt(x)), x, s) == \
(-4**s*sin(pi*(a/2 - s))*gamma(S.Half - 2*s)
* gamma((1 - a)/2 + s)*gamma((1 + a)/2 + s)
/ (sqrt(pi)*gamma(1 - s - a/2)*gamma(1 - s + a/2)),
(Max(-(re(a) + 1)/2, (re(a) - 1)/2), Rational(1, 4)), True)
assert MT(cos(sqrt(x))*bessely(a, sqrt(x)), x, s) == \
(-4**s*cos(pi*(a/2 - s))*gamma(s - a/2)*gamma(s + a/2)*gamma(S.Half - 2*s)
/ (sqrt(pi)*gamma(S.Half - s - a/2)*gamma(S.Half - s + a/2)),
(Max(-re(a)/2, re(a)/2), Rational(1, 4)), True)
assert MT(besselj(a, sqrt(x))*bessely(a, sqrt(x)), x, s) == \
(-cos(pi*s)*gamma(s)*gamma(a + s)*gamma(S.Half - s)
/ (pi**S('3/2')*gamma(1 + a - s)),
(Max(-re(a), 0), S.Half), True)
assert MT(besselj(a, sqrt(x))*bessely(b, sqrt(x)), x, s) == \
(-4**s*cos(pi*(a/2 - b/2 + s))*gamma(1 - 2*s)
* gamma(a/2 - b/2 + s)*gamma(a/2 + b/2 + s)
/ (pi*gamma(a/2 - b/2 - s + 1)*gamma(a/2 + b/2 - s + 1)),
(Max((-re(a) + re(b))/2, (-re(a) - re(b))/2), S.Half), True)
# NOTE bessely(a, sqrt(x))**2 and bessely(a, sqrt(x))*bessely(b, sqrt(x))
# are a mess (no matter what way you look at it ...)
assert MT(bessely(a, sqrt(x))**2, x, s)[1:] == \
((Max(-re(a), 0, re(a)), S.Half), True)
# Section 8.4.22
# TODO we can't do any of these (delicate cancellation)
# Section 8.4.23
assert MT(besselk(a, 2*sqrt(x)), x, s) == \
(gamma(
s - a/2)*gamma(s + a/2)/2, (Max(-re(a)/2, re(a)/2), oo), True)
assert MT(besselj(a, 2*sqrt(2*sqrt(x)))*besselk(
a, 2*sqrt(2*sqrt(x))), x, s) == (4**(-s)*gamma(2*s)*
gamma(a/2 + s)/(2*gamma(a/2 - s + 1)), (Max(0, -re(a)/2), oo), True)
# TODO bessely(a, x)*besselk(a, x) is a mess
assert MT(besseli(a, sqrt(x))*besselk(a, sqrt(x)), x, s) == \
(gamma(s)*gamma(
a + s)*gamma(-s + S.Half)/(2*sqrt(pi)*gamma(a - s + 1)),
(Max(-re(a), 0), S.Half), True)
assert MT(besseli(b, sqrt(x))*besselk(a, sqrt(x)), x, s) == \
(2**(2*s - 1)*gamma(-2*s + 1)*gamma(-a/2 + b/2 + s)* \
gamma(a/2 + b/2 + s)/(gamma(-a/2 + b/2 - s + 1)* \
gamma(a/2 + b/2 - s + 1)), (Max(-re(a)/2 - re(b)/2, \
re(a)/2 - re(b)/2), S.Half), True)
# TODO products of besselk are a mess
mt = MT(exp(-x/2)*besselk(a, x/2), x, s)
mt0 = gammasimp(trigsimp(gammasimp(mt[0].expand(func=True))))
assert mt0 == 2*pi**Rational(3, 2)*cos(pi*s)*gamma(S.Half - s)/(
(cos(2*pi*a) - cos(2*pi*s))*gamma(-a - s + 1)*gamma(a - s + 1))
assert mt[1:] == ((Max(-re(a), re(a)), oo), True)
# TODO exp(x/2)*besselk(a, x/2) [etc] cannot currently be done
# TODO various strange products of special orders
@slow
def test_expint():
from sympy.functions.elementary.miscellaneous import Max
from sympy.functions.special.error_functions import Ci, E1, Si
from sympy.simplify.simplify import simplify
aneg = Symbol('a', negative=True)
u = Symbol('u', polar=True)
assert mellin_transform(E1(x), x, s) == (gamma(s)/s, (0, oo), True)
assert inverse_mellin_transform(gamma(s)/s, s, x,
(0, oo)).rewrite(expint).expand() == E1(x)
assert mellin_transform(expint(a, x), x, s) == \
(gamma(s)/(a + s - 1), (Max(1 - re(a), 0), oo), True)
# XXX IMT has hickups with complicated strips ...
assert simplify(unpolarify(
inverse_mellin_transform(gamma(s)/(aneg + s - 1), s, x,
(1 - aneg, oo)).rewrite(expint).expand(func=True))) == \
expint(aneg, x)
assert mellin_transform(Si(x), x, s) == \
(-2**s*sqrt(pi)*gamma(s/2 + S.Half)/(
2*s*gamma(-s/2 + 1)), (-1, 0), True)
assert inverse_mellin_transform(-2**s*sqrt(pi)*gamma((s + 1)/2)
/(2*s*gamma(-s/2 + 1)), s, x, (-1, 0)) \
== Si(x)
assert mellin_transform(Ci(sqrt(x)), x, s) == \
(-2**(2*s - 1)*sqrt(pi)*gamma(s)/(s*gamma(-s + S.Half)), (0, 1), True)
assert inverse_mellin_transform(
-4**s*sqrt(pi)*gamma(s)/(2*s*gamma(-s + S.Half)),
s, u, (0, 1)).expand() == Ci(sqrt(u))
@slow
def test_inverse_mellin_transform():
from sympy.core.function import expand
from sympy.functions.elementary.miscellaneous import (Max, Min)
from sympy.functions.elementary.trigonometric import cot
from sympy.simplify.powsimp import powsimp
from sympy.simplify.simplify import simplify
IMT = inverse_mellin_transform
assert IMT(gamma(s), s, x, (0, oo)) == exp(-x)
assert IMT(gamma(-s), s, x, (-oo, 0)) == exp(-1/x)
assert simplify(IMT(s/(2*s**2 - 2), s, x, (2, oo))) == \
(x**2 + 1)*Heaviside(1 - x)/(4*x)
# test passing "None"
assert IMT(1/(s**2 - 1), s, x, (-1, None)) == \
-x*Heaviside(-x + 1)/2 - Heaviside(x - 1)/(2*x)
assert IMT(1/(s**2 - 1), s, x, (None, 1)) == \
-x*Heaviside(-x + 1)/2 - Heaviside(x - 1)/(2*x)
# test expansion of sums
assert IMT(gamma(s) + gamma(s - 1), s, x, (1, oo)) == (x + 1)*exp(-x)/x
# test factorisation of polys
r = symbols('r', real=True)
assert IMT(1/(s**2 + 1), s, exp(-x), (None, oo)
).subs(x, r).rewrite(sin).simplify() \
== sin(r)*Heaviside(1 - exp(-r))
# test multiplicative substitution
_a, _b = symbols('a b', positive=True)
assert IMT(_b**(-s/_a)*factorial(s/_a)/s, s, x, (0, oo)) == exp(-_b*x**_a)
assert IMT(factorial(_a/_b + s/_b)/(_a + s), s, x, (-_a, oo)) == x**_a*exp(-x**_b)
def simp_pows(expr):
return simplify(powsimp(expand_mul(expr, deep=False), force=True)).replace(exp_polar, exp)
# Now test the inverses of all direct transforms tested above
# Section 8.4.2
nu = symbols('nu', real=True)
assert IMT(-1/(nu + s), s, x, (-oo, None)) == x**nu*Heaviside(x - 1)
assert IMT(1/(nu + s), s, x, (None, oo)) == x**nu*Heaviside(1 - x)
assert simp_pows(IMT(gamma(beta)*gamma(s)/gamma(s + beta), s, x, (0, oo))) \
== (1 - x)**(beta - 1)*Heaviside(1 - x)
assert simp_pows(IMT(gamma(beta)*gamma(1 - beta - s)/gamma(1 - s),
s, x, (-oo, None))) \
== (x - 1)**(beta - 1)*Heaviside(x - 1)
assert simp_pows(IMT(gamma(s)*gamma(rho - s)/gamma(rho), s, x, (0, None))) \
== (1/(x + 1))**rho
assert simp_pows(IMT(d**c*d**(s - 1)*sin(pi*c)
*gamma(s)*gamma(s + c)*gamma(1 - s)*gamma(1 - s - c)/pi,
s, x, (Max(-re(c), 0), Min(1 - re(c), 1)))) \
== (x**c - d**c)/(x - d)
assert simplify(IMT(1/sqrt(pi)*(-c/2)*gamma(s)*gamma((1 - c)/2 - s)
*gamma(-c/2 - s)/gamma(1 - c - s),
s, x, (0, -re(c)/2))) == \
(1 + sqrt(x + 1))**c
assert simplify(IMT(2**(a + 2*s)*b**(a + 2*s - 1)*gamma(s)*gamma(1 - a - 2*s)
/gamma(1 - a - s), s, x, (0, (-re(a) + 1)/2))) == \
b**(a - 1)*(b**2*(sqrt(1 + x/b**2) + 1)**a + x*(sqrt(1 + x/b**2) + 1
)**(a - 1))/(b**2 + x)
assert simplify(IMT(-2**(c + 2*s)*c*b**(c + 2*s)*gamma(s)*gamma(-c - 2*s)
/ gamma(-c - s + 1), s, x, (0, -re(c)/2))) == \
b**c*(sqrt(1 + x/b**2) + 1)**c
# Section 8.4.5
assert IMT(24/s**5, s, x, (0, oo)) == log(x)**4*Heaviside(1 - x)
assert expand(IMT(6/s**4, s, x, (-oo, 0)), force=True) == \
log(x)**3*Heaviside(x - 1)
assert IMT(pi/(s*sin(pi*s)), s, x, (-1, 0)) == log(x + 1)
assert IMT(pi/(s*sin(pi*s/2)), s, x, (-2, 0)) == log(x**2 + 1)
assert IMT(pi/(s*sin(2*pi*s)), s, x, (Rational(-1, 2), 0)) == log(sqrt(x) + 1)
assert IMT(pi/(s*sin(pi*s)), s, x, (0, 1)) == log(1 + 1/x)
# TODO
def mysimp(expr):
from sympy.core.function import expand
from sympy.simplify.powsimp import powsimp
from sympy.simplify.simplify import logcombine
return expand(
powsimp(logcombine(expr, force=True), force=True, deep=True),
force=True).replace(exp_polar, exp)
assert mysimp(mysimp(IMT(pi/(s*tan(pi*s)), s, x, (-1, 0)))) in [
log(1 - x)*Heaviside(1 - x) + log(x - 1)*Heaviside(x - 1),
log(x)*Heaviside(x - 1) + log(1 - 1/x)*Heaviside(x - 1) + log(-x +
1)*Heaviside(-x + 1)]
# test passing cot
assert mysimp(IMT(pi*cot(pi*s)/s, s, x, (0, 1))) in [
log(1/x - 1)*Heaviside(1 - x) + log(1 - 1/x)*Heaviside(x - 1),
-log(x)*Heaviside(-x + 1) + log(1 - 1/x)*Heaviside(x - 1) + log(-x +
1)*Heaviside(-x + 1), ]
# 8.4.14
assert IMT(-gamma(s + S.Half)/(sqrt(pi)*s), s, x, (Rational(-1, 2), 0)) == \
erf(sqrt(x))
# 8.4.19
assert simplify(IMT(gamma(a/2 + s)/gamma(a/2 - s + 1), s, x, (-re(a)/2, Rational(3, 4)))) \
== besselj(a, 2*sqrt(x))
assert simplify(IMT(2**a*gamma(S.Half - 2*s)*gamma(s + (a + 1)/2)
/ (gamma(1 - s - a/2)*gamma(1 - 2*s + a)),
s, x, (-(re(a) + 1)/2, Rational(1, 4)))) == \
sin(sqrt(x))*besselj(a, sqrt(x))
assert simplify(IMT(2**a*gamma(a/2 + s)*gamma(S.Half - 2*s)
/ (gamma(S.Half - s - a/2)*gamma(1 - 2*s + a)),
s, x, (-re(a)/2, Rational(1, 4)))) == \
cos(sqrt(x))*besselj(a, sqrt(x))
# TODO this comes out as an amazing mess, but simplifies nicely
assert simplify(IMT(gamma(a + s)*gamma(S.Half - s)
/ (sqrt(pi)*gamma(1 - s)*gamma(1 + a - s)),
s, x, (-re(a), S.Half))) == \
besselj(a, sqrt(x))**2
assert simplify(IMT(gamma(s)*gamma(S.Half - s)
/ (sqrt(pi)*gamma(1 - s - a)*gamma(1 + a - s)),
s, x, (0, S.Half))) == \
besselj(-a, sqrt(x))*besselj(a, sqrt(x))
assert simplify(IMT(4**s*gamma(-2*s + 1)*gamma(a/2 + b/2 + s)
/ (gamma(-a/2 + b/2 - s + 1)*gamma(a/2 - b/2 - s + 1)
*gamma(a/2 + b/2 - s + 1)),
s, x, (-(re(a) + re(b))/2, S.Half))) == \
besselj(a, sqrt(x))*besselj(b, sqrt(x))
# Section 8.4.20
# TODO this can be further simplified!
assert simplify(IMT(-2**(2*s)*cos(pi*a/2 - pi*b/2 + pi*s)*gamma(-2*s + 1) *
gamma(a/2 - b/2 + s)*gamma(a/2 + b/2 + s) /
(pi*gamma(a/2 - b/2 - s + 1)*gamma(a/2 + b/2 - s + 1)),
s, x,
(Max(-re(a)/2 - re(b)/2, -re(a)/2 + re(b)/2), S.Half))) == \
besselj(a, sqrt(x))*-(besselj(-b, sqrt(x)) -
besselj(b, sqrt(x))*cos(pi*b))/sin(pi*b)
# TODO more
# for coverage
assert IMT(pi/cos(pi*s), s, x, (0, S.Half)) == sqrt(x)/(x + 1)
def test_fourier_transform():
from sympy.core.function import (expand, expand_complex, expand_trig)
from sympy.polys.polytools import factor
from sympy.simplify.simplify import simplify
FT = fourier_transform
IFT = inverse_fourier_transform
def simp(x):
return simplify(expand_trig(expand_complex(expand(x))))
def sinc(x):
return sin(pi*x)/(pi*x)
k = symbols('k', real=True)
f = Function("f")
# TODO for this to work with real a, need to expand abs(a*x) to abs(a)*abs(x)
a = symbols('a', positive=True)
b = symbols('b', positive=True)
posk = symbols('posk', positive=True)
# Test unevaluated form
assert fourier_transform(f(x), x, k) == FourierTransform(f(x), x, k)
assert inverse_fourier_transform(
f(k), k, x) == InverseFourierTransform(f(k), k, x)
# basic examples from wikipedia
assert simp(FT(Heaviside(1 - abs(2*a*x)), x, k)) == sinc(k/a)/a
# TODO IFT is a *mess*
assert simp(FT(Heaviside(1 - abs(a*x))*(1 - abs(a*x)), x, k)) == sinc(k/a)**2/a
# TODO IFT
assert factor(FT(exp(-a*x)*Heaviside(x), x, k), extension=I) == \
1/(a + 2*pi*I*k)
# NOTE: the ift comes out in pieces
assert IFT(1/(a + 2*pi*I*x), x, posk,
noconds=False) == (exp(-a*posk), True)
assert IFT(1/(a + 2*pi*I*x), x, -posk,
noconds=False) == (0, True)
assert IFT(1/(a + 2*pi*I*x), x, symbols('k', negative=True),
noconds=False) == (0, True)
# TODO IFT without factoring comes out as meijer g
assert factor(FT(x*exp(-a*x)*Heaviside(x), x, k), extension=I) == \
1/(a + 2*pi*I*k)**2
assert FT(exp(-a*x)*sin(b*x)*Heaviside(x), x, k) == \
b/(b**2 + (a + 2*I*pi*k)**2)
assert FT(exp(-a*x**2), x, k) == sqrt(pi)*exp(-pi**2*k**2/a)/sqrt(a)
assert IFT(sqrt(pi/a)*exp(-(pi*k)**2/a), k, x) == exp(-a*x**2)
assert FT(exp(-a*abs(x)), x, k) == 2*a/(a**2 + 4*pi**2*k**2)
# TODO IFT (comes out as meijer G)
# TODO besselj(n, x), n an integer > 0 actually can be done...
# TODO are there other common transforms (no distributions!)?
def test_sine_transform():
t = symbols("t")
w = symbols("w")
a = symbols("a")
f = Function("f")
# Test unevaluated form
assert sine_transform(f(t), t, w) == SineTransform(f(t), t, w)
assert inverse_sine_transform(
f(w), w, t) == InverseSineTransform(f(w), w, t)
assert sine_transform(1/sqrt(t), t, w) == 1/sqrt(w)
assert inverse_sine_transform(1/sqrt(w), w, t) == 1/sqrt(t)
assert sine_transform((1/sqrt(t))**3, t, w) == 2*sqrt(w)
assert sine_transform(t**(-a), t, w) == 2**(
-a + S.Half)*w**(a - 1)*gamma(-a/2 + 1)/gamma((a + 1)/2)
assert inverse_sine_transform(2**(-a + S(
1)/2)*w**(a - 1)*gamma(-a/2 + 1)/gamma(a/2 + S.Half), w, t) == t**(-a)
assert sine_transform(
exp(-a*t), t, w) == sqrt(2)*w/(sqrt(pi)*(a**2 + w**2))
assert inverse_sine_transform(
sqrt(2)*w/(sqrt(pi)*(a**2 + w**2)), w, t) == exp(-a*t)
assert sine_transform(
log(t)/t, t, w) == sqrt(2)*sqrt(pi)*-(log(w**2) + 2*EulerGamma)/4
assert sine_transform(
t*exp(-a*t**2), t, w) == sqrt(2)*w*exp(-w**2/(4*a))/(4*a**Rational(3, 2))
assert inverse_sine_transform(
sqrt(2)*w*exp(-w**2/(4*a))/(4*a**Rational(3, 2)), w, t) == t*exp(-a*t**2)
def test_cosine_transform():
from sympy.functions.special.error_functions import (Ci, Si)
t = symbols("t")
w = symbols("w")
a = symbols("a")
f = Function("f")
# Test unevaluated form
assert cosine_transform(f(t), t, w) == CosineTransform(f(t), t, w)
assert inverse_cosine_transform(
f(w), w, t) == InverseCosineTransform(f(w), w, t)
assert cosine_transform(1/sqrt(t), t, w) == 1/sqrt(w)
assert inverse_cosine_transform(1/sqrt(w), w, t) == 1/sqrt(t)
assert cosine_transform(1/(
a**2 + t**2), t, w) == sqrt(2)*sqrt(pi)*exp(-a*w)/(2*a)
assert cosine_transform(t**(
-a), t, w) == 2**(-a + S.Half)*w**(a - 1)*gamma((-a + 1)/2)/gamma(a/2)
assert inverse_cosine_transform(2**(-a + S(
1)/2)*w**(a - 1)*gamma(-a/2 + S.Half)/gamma(a/2), w, t) == t**(-a)
assert cosine_transform(
exp(-a*t), t, w) == sqrt(2)*a/(sqrt(pi)*(a**2 + w**2))
assert inverse_cosine_transform(
sqrt(2)*a/(sqrt(pi)*(a**2 + w**2)), w, t) == exp(-a*t)
assert cosine_transform(exp(-a*sqrt(t))*cos(a*sqrt(
t)), t, w) == a*exp(-a**2/(2*w))/(2*w**Rational(3, 2))
assert cosine_transform(1/(a + t), t, w) == sqrt(2)*(
(-2*Si(a*w) + pi)*sin(a*w)/2 - cos(a*w)*Ci(a*w))/sqrt(pi)
assert inverse_cosine_transform(sqrt(2)*meijerg(((S.Half, 0), ()), (
(S.Half, 0, 0), (S.Half,)), a**2*w**2/4)/(2*pi), w, t) == 1/(a + t)
assert cosine_transform(1/sqrt(a**2 + t**2), t, w) == sqrt(2)*meijerg(
((S.Half,), ()), ((0, 0), (S.Half,)), a**2*w**2/4)/(2*sqrt(pi))
assert inverse_cosine_transform(sqrt(2)*meijerg(((S.Half,), ()), ((0, 0), (S.Half,)), a**2*w**2/4)/(2*sqrt(pi)), w, t) == 1/(t*sqrt(a**2/t**2 + 1))
def test_hankel_transform():
r = Symbol("r")
k = Symbol("k")
nu = Symbol("nu")
m = Symbol("m")
a = symbols("a")
assert hankel_transform(1/r, r, k, 0) == 1/k
assert inverse_hankel_transform(1/k, k, r, 0) == 1/r
assert hankel_transform(
1/r**m, r, k, 0) == 2**(-m + 1)*k**(m - 2)*gamma(-m/2 + 1)/gamma(m/2)
assert inverse_hankel_transform(
2**(-m + 1)*k**(m - 2)*gamma(-m/2 + 1)/gamma(m/2), k, r, 0) == r**(-m)
assert hankel_transform(1/r**m, r, k, nu) == (
2*2**(-m)*k**(m - 2)*gamma(-m/2 + nu/2 + 1)/gamma(m/2 + nu/2))
assert inverse_hankel_transform(2**(-m + 1)*k**(
m - 2)*gamma(-m/2 + nu/2 + 1)/gamma(m/2 + nu/2), k, r, nu) == r**(-m)
assert hankel_transform(r**nu*exp(-a*r), r, k, nu) == \
2**(nu + 1)*a*k**(-nu - 3)*(a**2/k**2 + 1)**(-nu - S(
3)/2)*gamma(nu + Rational(3, 2))/sqrt(pi)
assert inverse_hankel_transform(
2**(nu + 1)*a*k**(-nu - 3)*(a**2/k**2 + 1)**(-nu - Rational(3, 2))*gamma(
nu + Rational(3, 2))/sqrt(pi), k, r, nu) == r**nu*exp(-a*r)
def test_issue_7181():
assert mellin_transform(1/(1 - x), x, s) != None
def test_issue_8882():
# This is the original test.
# from sympy import diff, Integral, integrate
# r = Symbol('r')
# psi = 1/r*sin(r)*exp(-(a0*r))
# h = -1/2*diff(psi, r, r) - 1/r*psi
# f = 4*pi*psi*h*r**2
# assert integrate(f, (r, -oo, 3), meijerg=True).has(Integral) == True
# To save time, only the critical part is included.
F = -a**(-s + 1)*(4 + 1/a**2)**(-s/2)*sqrt(1/a**2)*exp(-s*I*pi)* \
sin(s*atan(sqrt(1/a**2)/2))*gamma(s)
raises(IntegralTransformError, lambda:
inverse_mellin_transform(F, s, x, (-1, oo),
**{'as_meijerg': True, 'needeval': True}))
def test_issue_12591():
x, y = symbols("x y", real=True)
assert fourier_transform(exp(x), x, y) == FourierTransform(exp(x), x, y)

View File

@ -0,0 +1,98 @@
from sympy.core import Ne, Rational, Symbol
from sympy.functions import sin, cos, tan, csc, sec, cot, log, Piecewise
from sympy.integrals.trigonometry import trigintegrate
x = Symbol('x')
def test_trigintegrate_odd():
assert trigintegrate(Rational(1), x) == x
assert trigintegrate(x, x) is None
assert trigintegrate(x**2, x) is None
assert trigintegrate(sin(x), x) == -cos(x)
assert trigintegrate(cos(x), x) == sin(x)
assert trigintegrate(sin(3*x), x) == -cos(3*x)/3
assert trigintegrate(cos(3*x), x) == sin(3*x)/3
y = Symbol('y')
assert trigintegrate(sin(y*x), x) == Piecewise(
(-cos(y*x)/y, Ne(y, 0)), (0, True))
assert trigintegrate(cos(y*x), x) == Piecewise(
(sin(y*x)/y, Ne(y, 0)), (x, True))
assert trigintegrate(sin(y*x)**2, x) == Piecewise(
((x*y/2 - sin(x*y)*cos(x*y)/2)/y, Ne(y, 0)), (0, True))
assert trigintegrate(sin(y*x)*cos(y*x), x) == Piecewise(
(sin(x*y)**2/(2*y), Ne(y, 0)), (0, True))
assert trigintegrate(cos(y*x)**2, x) == Piecewise(
((x*y/2 + sin(x*y)*cos(x*y)/2)/y, Ne(y, 0)), (x, True))
y = Symbol('y', positive=True)
# TODO: remove conds='none' below. For this to work we would have to rule
# out (e.g. by trying solve) the condition y = 0, incompatible with
# y.is_positive being True.
assert trigintegrate(sin(y*x), x, conds='none') == -cos(y*x)/y
assert trigintegrate(cos(y*x), x, conds='none') == sin(y*x)/y
assert trigintegrate(sin(x)*cos(x), x) == sin(x)**2/2
assert trigintegrate(sin(x)*cos(x)**2, x) == -cos(x)**3/3
assert trigintegrate(sin(x)**2*cos(x), x) == sin(x)**3/3
# check if it selects right function to substitute,
# so the result is kept simple
assert trigintegrate(sin(x)**7 * cos(x), x) == sin(x)**8/8
assert trigintegrate(sin(x) * cos(x)**7, x) == -cos(x)**8/8
assert trigintegrate(sin(x)**7 * cos(x)**3, x) == \
-sin(x)**10/10 + sin(x)**8/8
assert trigintegrate(sin(x)**3 * cos(x)**7, x) == \
cos(x)**10/10 - cos(x)**8/8
# both n, m are odd and -ve, and not necessarily equal
assert trigintegrate(sin(x)**-1*cos(x)**-1, x) == \
-log(sin(x)**2 - 1)/2 + log(sin(x))
def test_trigintegrate_even():
assert trigintegrate(sin(x)**2, x) == x/2 - cos(x)*sin(x)/2
assert trigintegrate(cos(x)**2, x) == x/2 + cos(x)*sin(x)/2
assert trigintegrate(sin(3*x)**2, x) == x/2 - cos(3*x)*sin(3*x)/6
assert trigintegrate(cos(3*x)**2, x) == x/2 + cos(3*x)*sin(3*x)/6
assert trigintegrate(sin(x)**2 * cos(x)**2, x) == \
x/8 - sin(2*x)*cos(2*x)/16
assert trigintegrate(sin(x)**4 * cos(x)**2, x) == \
x/16 - sin(x) *cos(x)/16 - sin(x)**3*cos(x)/24 + \
sin(x)**5*cos(x)/6
assert trigintegrate(sin(x)**2 * cos(x)**4, x) == \
x/16 + cos(x) *sin(x)/16 + cos(x)**3*sin(x)/24 - \
cos(x)**5*sin(x)/6
assert trigintegrate(sin(x)**(-4), x) == -2*cos(x)/(3*sin(x)) \
- cos(x)/(3*sin(x)**3)
assert trigintegrate(cos(x)**(-6), x) == sin(x)/(5*cos(x)**5) \
+ 4*sin(x)/(15*cos(x)**3) + 8*sin(x)/(15*cos(x))
def test_trigintegrate_mixed():
assert trigintegrate(sin(x)*sec(x), x) == -log(cos(x))
assert trigintegrate(sin(x)*csc(x), x) == x
assert trigintegrate(sin(x)*cot(x), x) == sin(x)
assert trigintegrate(cos(x)*sec(x), x) == x
assert trigintegrate(cos(x)*csc(x), x) == log(sin(x))
assert trigintegrate(cos(x)*tan(x), x) == -cos(x)
assert trigintegrate(cos(x)*cot(x), x) == log(cos(x) - 1)/2 \
- log(cos(x) + 1)/2 + cos(x)
assert trigintegrate(cot(x)*cos(x)**2, x) == log(sin(x)) - sin(x)**2/2
def test_trigintegrate_symbolic():
n = Symbol('n', integer=True)
assert trigintegrate(cos(x)**n, x) is None
assert trigintegrate(sin(x)**n, x) is None
assert trigintegrate(cot(x)**n, x) is None

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,335 @@
from sympy.core import cacheit, Dummy, Ne, Integer, Rational, S, Wild
from sympy.functions import binomial, sin, cos, Piecewise, Abs
from .integrals import integrate
# TODO sin(a*x)*cos(b*x) -> sin((a+b)x) + sin((a-b)x) ?
# creating, each time, Wild's and sin/cos/Mul is expensive. Also, our match &
# subs are very slow when not cached, and if we create Wild each time, we
# effectively block caching.
#
# so we cache the pattern
# need to use a function instead of lamda since hash of lambda changes on
# each call to _pat_sincos
def _integer_instance(n):
return isinstance(n, Integer)
@cacheit
def _pat_sincos(x):
a = Wild('a', exclude=[x])
n, m = [Wild(s, exclude=[x], properties=[_integer_instance])
for s in 'nm']
pat = sin(a*x)**n * cos(a*x)**m
return pat, a, n, m
_u = Dummy('u')
def trigintegrate(f, x, conds='piecewise'):
"""
Integrate f = Mul(trig) over x.
Examples
========
>>> from sympy import sin, cos, tan, sec
>>> 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)
References
==========
.. [1] https://en.wikibooks.org/wiki/Calculus/Integration_techniques
See Also
========
sympy.integrals.integrals.Integral.doit
sympy.integrals.integrals.Integral
"""
pat, a, n, m = _pat_sincos(x)
f = f.rewrite('sincos')
M = f.match(pat)
if M is None:
return
n, m = M[n], M[m]
if n.is_zero and m.is_zero:
return x
zz = x if n.is_zero else S.Zero
a = M[a]
if n.is_odd or m.is_odd:
u = _u
n_, m_ = n.is_odd, m.is_odd
# take smallest n or m -- to choose simplest substitution
if n_ and m_:
# Make sure to choose the positive one
# otherwise an incorrect integral can occur.
if n < 0 and m > 0:
m_ = True
n_ = False
elif m < 0 and n > 0:
n_ = True
m_ = False
# Both are negative so choose the smallest n or m
# in absolute value for simplest substitution.
elif (n < 0 and m < 0):
n_ = n > m
m_ = not (n > m)
# Both n and m are odd and positive
else:
n_ = (n < m) # NB: careful here, one of the
m_ = not (n < m) # conditions *must* be true
# n m u=C (n-1)/2 m
# S(x) * C(x) dx --> -(1-u^2) * u du
if n_:
ff = -(1 - u**2)**((n - 1)/2) * u**m
uu = cos(a*x)
# n m u=S n (m-1)/2
# S(x) * C(x) dx --> u * (1-u^2) du
elif m_:
ff = u**n * (1 - u**2)**((m - 1)/2)
uu = sin(a*x)
fi = integrate(ff, u) # XXX cyclic deps
fx = fi.subs(u, uu)
if conds == 'piecewise':
return Piecewise((fx / a, Ne(a, 0)), (zz, True))
return fx / a
# n & m are both even
#
# 2k 2m 2l 2l
# we transform S (x) * C (x) into terms with only S (x) or C (x)
#
# example:
# 100 4 100 2 2 100 4 2
# S (x) * C (x) = S (x) * (1-S (x)) = S (x) * (1 + S (x) - 2*S (x))
#
# 104 102 100
# = S (x) - 2*S (x) + S (x)
# 2k
# then S is integrated with recursive formula
# take largest n or m -- to choose simplest substitution
n_ = (Abs(n) > Abs(m))
m_ = (Abs(m) > Abs(n))
res = S.Zero
if n_:
# 2k 2 k i 2i
# C = (1 - S ) = sum(i, (-) * B(k, i) * S )
if m > 0:
for i in range(0, m//2 + 1):
res += (S.NegativeOne**i * binomial(m//2, i) *
_sin_pow_integrate(n + 2*i, x))
elif m == 0:
res = _sin_pow_integrate(n, x)
else:
# m < 0 , |n| > |m|
# /
# |
# | m n
# | cos (x) sin (x) dx =
# |
# |
#/
# /
# |
# -1 m+1 n-1 n - 1 | m+2 n-2
# ________ cos (x) sin (x) + _______ | cos (x) sin (x) dx
# |
# m + 1 m + 1 |
# /
res = (Rational(-1, m + 1) * cos(x)**(m + 1) * sin(x)**(n - 1) +
Rational(n - 1, m + 1) *
trigintegrate(cos(x)**(m + 2)*sin(x)**(n - 2), x))
elif m_:
# 2k 2 k i 2i
# S = (1 - C ) = sum(i, (-) * B(k, i) * C )
if n > 0:
# / /
# | |
# | m n | -m n
# | cos (x)*sin (x) dx or | cos (x) * sin (x) dx
# | |
# / /
#
# |m| > |n| ; m, n >0 ; m, n belong to Z - {0}
# n 2
# sin (x) term is expanded here in terms of cos (x),
# and then integrated.
#
for i in range(0, n//2 + 1):
res += (S.NegativeOne**i * binomial(n//2, i) *
_cos_pow_integrate(m + 2*i, x))
elif n == 0:
# /
# |
# | 1
# | _ _ _
# | m
# | cos (x)
# /
#
res = _cos_pow_integrate(m, x)
else:
# n < 0 , |m| > |n|
# /
# |
# | m n
# | cos (x) sin (x) dx =
# |
# |
#/
# /
# |
# 1 m-1 n+1 m - 1 | m-2 n+2
# _______ cos (x) sin (x) + _______ | cos (x) sin (x) dx
# |
# n + 1 n + 1 |
# /
res = (Rational(1, n + 1) * cos(x)**(m - 1)*sin(x)**(n + 1) +
Rational(m - 1, n + 1) *
trigintegrate(cos(x)**(m - 2)*sin(x)**(n + 2), x))
else:
if m == n:
##Substitute sin(2x)/2 for sin(x)cos(x) and then Integrate.
res = integrate((sin(2*x)*S.Half)**m, x)
elif (m == -n):
if n < 0:
# Same as the scheme described above.
# the function argument to integrate in the end will
# be 1, this cannot be integrated by trigintegrate.
# Hence use sympy.integrals.integrate.
res = (Rational(1, n + 1) * cos(x)**(m - 1) * sin(x)**(n + 1) +
Rational(m - 1, n + 1) *
integrate(cos(x)**(m - 2) * sin(x)**(n + 2), x))
else:
res = (Rational(-1, m + 1) * cos(x)**(m + 1) * sin(x)**(n - 1) +
Rational(n - 1, m + 1) *
integrate(cos(x)**(m + 2)*sin(x)**(n - 2), x))
if conds == 'piecewise':
return Piecewise((res.subs(x, a*x) / a, Ne(a, 0)), (zz, True))
return res.subs(x, a*x) / a
def _sin_pow_integrate(n, x):
if n > 0:
if n == 1:
#Recursion break
return -cos(x)
# n > 0
# / /
# | |
# | n -1 n-1 n - 1 | n-2
# | sin (x) dx = ______ cos (x) sin (x) + _______ | sin (x) dx
# | |
# | n n |
#/ /
#
#
return (Rational(-1, n) * cos(x) * sin(x)**(n - 1) +
Rational(n - 1, n) * _sin_pow_integrate(n - 2, x))
if n < 0:
if n == -1:
##Make sure this does not come back here again.
##Recursion breaks here or at n==0.
return trigintegrate(1/sin(x), x)
# n < 0
# / /
# | |
# | n 1 n+1 n + 2 | n+2
# | sin (x) dx = _______ cos (x) sin (x) + _______ | sin (x) dx
# | |
# | n + 1 n + 1 |
#/ /
#
return (Rational(1, n + 1) * cos(x) * sin(x)**(n + 1) +
Rational(n + 2, n + 1) * _sin_pow_integrate(n + 2, x))
else:
#n == 0
#Recursion break.
return x
def _cos_pow_integrate(n, x):
if n > 0:
if n == 1:
#Recursion break.
return sin(x)
# n > 0
# / /
# | |
# | n 1 n-1 n - 1 | n-2
# | sin (x) dx = ______ sin (x) cos (x) + _______ | cos (x) dx
# | |
# | n n |
#/ /
#
return (Rational(1, n) * sin(x) * cos(x)**(n - 1) +
Rational(n - 1, n) * _cos_pow_integrate(n - 2, x))
if n < 0:
if n == -1:
##Recursion break
return trigintegrate(1/cos(x), x)
# n < 0
# / /
# | |
# | n -1 n+1 n + 2 | n+2
# | cos (x) dx = _______ sin (x) cos (x) + _______ | cos (x) dx
# | |
# | n + 1 n + 1 |
#/ /
#
return (Rational(-1, n + 1) * sin(x) * cos(x)**(n + 1) +
Rational(n + 2, n + 1) * _cos_pow_integrate(n + 2, x))
else:
# n == 0
#Recursion Break.
return x