Path: blob/master/sage/symbolic/integration/integral.py
4079 views
"""1Symbolic Integration2"""34##############################################################################5#6# Copyright (C) 2009 Golam Mortuza Hossain <[email protected]>7# Copyright (C) 2010 Burcin Erocal <[email protected]>8#9# Distributed under the terms of the GNU General Public License (GPL v2+)10# http://www.gnu.org/licenses/11#12##############################################################################1314from sage.symbolic.ring import SR, is_SymbolicVariable15from sage.symbolic.function import BuiltinFunction, Function1617##################################################################18# Table of available integration routines19##################################################################2021# Add new integration routines to the dictionary below. This will make them22# accessible with the 'algorithm' keyword parameter of top level integrate().23available_integrators = {}2425import sage.symbolic.integration.external as external26available_integrators['maxima'] = external.maxima_integrator27available_integrators['sympy'] = external.sympy_integrator28available_integrators['mathematica_free'] = external.mma_free_integrator2930######################################################31#32# Class implementing symbolic integration33#34######################################################3536class IndefiniteIntegral(BuiltinFunction):37def __init__(self):38"""39Class to represent an indefinite integral.4041EXAMPLES::4243sage: from sage.symbolic.integration.integral import indefinite_integral44sage: indefinite_integral(log(x), x) #indirect doctest45x*log(x) - x46sage: indefinite_integral(x^2, x)471/3*x^348sage: indefinite_integral(4*x*log(x), x)492*x^2*log(x) - x^250sage: indefinite_integral(exp(x), 2*x)512*e^x5253"""54# The automatic evaluation routine will try these integrators55# in the given order. This is an attribute of the class instead of56# a global variable in this module to enable customization by57# creating a subclasses which define a different set of integrators58self.integrators = [external.maxima_integrator]5960BuiltinFunction.__init__(self, "integrate", nargs=2)6162def _eval_(self, f, x):63"""64EXAMPLES::6566sage: from sage.symbolic.integration.integral import indefinite_integral67sage: indefinite_integral(exp(x), x) # indirect doctest68e^x69sage: indefinite_integral(exp(x), x^2)702*(x - 1)*e^x71"""72# Check for x73if not is_SymbolicVariable(x):74if len(x.variables()) == 1:75nx = x.variables()[0]76f = f*x.diff(nx)77x = nx78else:79return None8081# we try all listed integration algorithms82for integrator in self.integrators:83res = integrator(f, x)84try:85return integrator(f, x)86except NotImplementedError:87pass88return None8990def _tderivative_(self, f, x, diff_param=None):91"""92EXAMPLES::9394sage: from sage.symbolic.integration.integral import indefinite_integral95sage: f = function('f'); a,b=var('a,b')96sage: h = indefinite_integral(f(x), x)97sage: h.diff(x) # indirect doctest98f(x)99sage: h.diff(a)1000101"""102if x.has(diff_param):103return f*x.derivative(diff_param)104else:105return f.derivative(diff_param).integral(x)106107def _print_latex_(self, f, x):108"""109EXAMPLES::110111sage: from sage.symbolic.integration.integral import indefinite_integral112sage: print_latex = indefinite_integral._print_latex_113sage: var('x,a,b')114(x, a, b)115sage: f = function('f')116sage: print_latex(f(x),x)117'\\int f\\left(x\\right)\\,{d x}'118"""119from sage.misc.latex import latex120if not is_SymbolicVariable(x):121dx_str = "{d \\left(%s\\right)}"%(latex(x))122else:123dx_str = "{d %s}"%(latex(x))124125return "\\int %s\\,%s"%(latex(f), dx_str)126127indefinite_integral = IndefiniteIntegral()128129class DefiniteIntegral(BuiltinFunction):130def __init__(self):131"""132Symbolic function representing a definite integral.133134EXAMPLES::135136sage: from sage.symbolic.integration.integral import definite_integral137sage: definite_integral(sin(x),x,0,pi)1382139"""140# The automatic evaluation routine will try these integrators141# in the given order. This is an attribute of the class instead of142# a global variable in this module to enable customization by143# creating a subclasses which define a different set of integrators144self.integrators = [external.maxima_integrator]145146BuiltinFunction.__init__(self, "integrate", nargs=4)147148def _eval_(self, f, x, a, b):149"""150Returns the results of symbolic evaluation of the integral151152EXAMPLES::153154sage: from sage.symbolic.integration.integral import definite_integral155sage: definite_integral(exp(x),x,0,1) # indirect doctest156e - 1157"""158# Check for x159if not is_SymbolicVariable(x):160if len(x.variables()) == 1:161nx = x.variables()[0]162f = f*x.diff(nx)163x = nx164else:165return None166167args = (f,x,a,b)168169# we try all listed integration algorithms170for integrator in self.integrators:171try:172return integrator(*args)173except NotImplementedError:174pass175return None176177def _evalf_(self, f, x, a, b, parent=None):178"""179Returns numerical approximation of the integral180181EXAMPLES::182183sage: from sage.symbolic.integration.integral import definite_integral184sage: h = definite_integral(sin(x)*log(x)/x^2, x, 1, 2); h185integrate(log(x)*sin(x)/x^2, x, 1, 2)186sage: h.n() # indirect doctest1870.14839875208053...188189TESTS:190191Check if #3863 is fixed::192193sage: integrate(x^2.7 * e^(-2.4*x), x, 0, 3).n()1940.154572952320790195"""196from sage.gsl.integration import numerical_integral197# The gsl routine returns a tuple, which also contains the error.198# We only return the result.199return numerical_integral(f, a, b)[0]200201def _tderivative_(self, f, x, a, b, diff_param=None):202"""203Returns derivative of symbolic integration204205EXAMPLES::206207sage: from sage.symbolic.integration.integral import definite_integral208sage: f = function('f'); a,b=var('a,b')209sage: h = definite_integral(f(x), x,a,b)210sage: h.diff(x) # indirect doctest2110212sage: h.diff(a)213-f(a)214sage: h.diff(b)215f(b)216"""217if not x.has(diff_param):218# integration variable != differentiation variable219ans = definite_integral(f.diff(diff_param), x, a, b)220else:221ans = SR(0)222return ans + f.subs(x==b)*b.diff(diff_param) \223- f.subs(x==a)*a.diff(diff_param)224225def _print_latex_(self, f, x, a, b):226r"""227Returns LaTeX expression for integration of a symbolic function.228229EXAMPLES::230231sage: from sage.symbolic.integration.integral import definite_integral232sage: print_latex = definite_integral._print_latex_233sage: var('x,a,b')234(x, a, b)235sage: f = function('f')236sage: print_latex(f(x),x,0,1)237'\\int_{0}^{1} f\\left(x\\right)\\,{d x}'238sage: latex(integrate(1/(1+sqrt(x)),x,0,1))239\int_{0}^{1} \frac{1}{\sqrt{x} + 1}\,{d x}240"""241from sage.misc.latex import latex242if not is_SymbolicVariable(x):243dx_str = "{d \\left(%s\\right)}"%(latex(x))244else:245dx_str = "{d %s}"%(latex(x))246return "\\int_{%s}^{%s} %s\\,%s"%(latex(a), latex(b), latex(f), dx_str)247248definite_integral = DefiniteIntegral()249250251def _normalize_integral_input(f, v=None, a=None, b=None):252r"""253Validate and return variable and endpoints for an integral.254255INPUT:256257- ``f`` -- an expression to integrate;258259- ``v`` -- a variable of integration or a triple;260261- ``a`` -- (optional) the left endpoint of integration;262263- ``b`` -- (optional) the right endpoint of integration.264265It is also possible to pass last three parameters in ``v`` as a triple.266267OUPUT:268269- a tuple of ``f``, ``v``, ``a``, and ``b``.270271EXAMPLES::272273sage: from sage.symbolic.integration.integral import \274... _normalize_integral_input275sage: _normalize_integral_input(x^2, x, 0, 3)276(x^2, x, 0, 3)277sage: _normalize_integral_input(x^2, [x, 0, 3], None, None)278(x^2, x, 0, 3)279sage: _normalize_integral_input(x^2, [0, 3], None, None)280doctest:...: DeprecationWarning:281Variable of integration should be specified explicitly.282(x^2, x, 0, 3)283sage: _normalize_integral_input(x^2, [x], None, None)284(x^2, x, None, None)285"""286if isinstance(v, (list, tuple)) and a is None and b is None:287if len(v) == 1: # bare variable in a tuple288v = v[0]289elif len(v) == 2: # endpoints only290a, b = v291v = None292elif len(v) == 3: # variable and endpoints293v, a, b = v294else:295raise ValueError("invalid input %s - please use variable, "296"with or without two endpoints" % repr(v))297elif b is None and a is not None:298# two arguments, must be endpoints299v, a, b = None, v, a300if v is None:301from sage.misc.misc import deprecation302deprecation("Variable of integration should be specified explicitly.")303v = f.default_variable()304if isinstance(f, Function): # a bare function like sin305f = f(v)306if (a is None) ^ (b is None):307raise TypeError('only one endpoint was given!')308return f, v, a, b309310def integrate(expression, v=None, a=None, b=None, algorithm=None):311r"""312Returns the indefinite integral with respect to the variable313`v`, ignoring the constant of integration. Or, if endpoints314`a` and `b` are specified, returns the definite315integral over the interval `[a, b]`.316317If ``self`` has only one variable, then it returns the318integral with respect to that variable.319320If definite integration fails, it could be still possible to321evaluate the definite integral using indefinite integration with322the Newton - Leibniz theorem (however, the user has to ensure that the323indefinite integral is continuous on the compact interval `[a,b]` and324this theorem can be applied).325326INPUT:327328- ``v`` - a variable or variable name. This can also be a tuple of329the variable (optional) and endpoints (i.e., ``(x,0,1)`` or ``(0,1)``).330331- ``a`` - (optional) lower endpoint of definite integral332333- ``b`` - (optional) upper endpoint of definite integral334335- ``algorithm`` - (default: 'maxima') one of336337- 'maxima' - use maxima (the default)338339- 'sympy' - use sympy (also in Sage)340341- 'mathematica_free' - use http://integrals.wolfram.com/342343EXAMPLES::344345sage: x = var('x')346sage: h = sin(x)/(cos(x))^2347sage: h.integral(x)3481/cos(x)349350::351352sage: f = x^2/(x+1)^3353sage: f.integral(x)3541/2*(4*x + 3)/(x^2 + 2*x + 1) + log(x + 1)355356::357358sage: f = x*cos(x^2)359sage: f.integral(x, 0, sqrt(pi))3600361sage: f.integral(x, a=-pi, b=pi)3620363364::365366sage: f(x) = sin(x)367sage: f.integral(x, 0, pi/2)3681369370The variable is required, but the endpoints are optional::371372sage: y=var('y')373sage: integral(sin(x), x)374-cos(x)375sage: integral(sin(x), y)376y*sin(x)377sage: integral(sin(x), x, pi, 2*pi)378-2379sage: integral(sin(x), y, pi, 2*pi)380pi*sin(x)381sage: integral(sin(x), (x, pi, 2*pi))382-2383sage: integral(sin(x), (y, pi, 2*pi))384pi*sin(x)385386Constraints are sometimes needed::387388sage: var('x, n')389(x, n)390sage: integral(x^n,x)391Traceback (most recent call last):392...393ValueError: Computation failed since Maxima requested additional394constraints; using the 'assume' command before integral evaluation395*may* help (example of legal syntax is 'assume(n+1>0)', see `assume?`396for more details)397Is n+1 zero or nonzero?398sage: assume(n > 0)399sage: integral(x^n,x)400x^(n + 1)/(n + 1)401sage: forget()402403Usually the constraints are of sign, but others are possible::404405sage: assume(n==-1)406sage: integral(x^n,x)407log(x)408409Note that an exception is raised when a definite integral is410divergent::411412sage: forget() # always remember to forget assumptions you no longer need413sage: integrate(1/x^3,(x,0,1))414Traceback (most recent call last):415...416ValueError: Integral is divergent.417sage: integrate(1/x^3,x,-1,3)418Traceback (most recent call last):419...420ValueError: Integral is divergent.421422But Sage can calculate the convergent improper integral of423this function::424425sage: integrate(1/x^3,x,1,infinity)4261/2427428The examples in the Maxima documentation::429430sage: var('x, y, z, b')431(x, y, z, b)432sage: integral(sin(x)^3, x)4331/3*cos(x)^3 - cos(x)434sage: integral(x/sqrt(b^2-x^2), b)435x*log(2*b + 2*sqrt(b^2 - x^2))436sage: integral(x/sqrt(b^2-x^2), x)437-sqrt(b^2 - x^2)438sage: integral(cos(x)^2 * exp(x), x, 0, pi)4393/5*e^pi - 3/5440sage: integral(x^2 * exp(-x^2), x, -oo, oo)4411/2*sqrt(pi)442443We integrate the same function in both Mathematica and Sage (via444Maxima)::445446sage: _ = var('x, y, z')447sage: f = sin(x^2) + y^z448sage: g = mathematica(f) # optional -- requires mathematica449sage: print g # optional -- requires mathematica450z 2451y + Sin[x ]452sage: print g.Integrate(x) # optional -- requires mathematica453z Pi 2454x y + Sqrt[--] FresnelS[Sqrt[--] x]4552 Pi456sage: print f.integral(x)457y^z*x + 1/8*((I + 1)*sqrt(2)*erf((1/2*I + 1/2)*sqrt(2)*x) + (I - 1)*sqrt(2)*erf((1/2*I - 1/2)*sqrt(2)*x))*sqrt(pi)458459Alternatively, just use algorithm='mathematica_free' to integrate via Mathematica460over the internet (does NOT require a Mathematica license!)::461462sage: _ = var('x, y, z')463sage: f = sin(x^2) + y^z464sage: f.integrate(algorithm="mathematica_free") # optional -- requires internet465sqrt(pi)*sqrt(1/2)*fresnels(sqrt(2)*x/sqrt(pi)) + y^z*x466467We can also use Sympy::468469sage: _ = var('x, y, z')470sage: (x^y-z).integrate(y)471-y*z + x^y/log(x)472sage: (x^y-z).integrate(y,algorithm="sympy")473-y*z + x^y/log(x)474475476We integrate the above function in maple now::477478sage: g = maple(f); g # optional -- requires maple479sin(x^2)+y^z480sage: g.integrate(x) # optional -- requires maple4811/2*2^(1/2)*Pi^(1/2)*FresnelS(2^(1/2)/Pi^(1/2)*x)+y^z*x482483We next integrate a function with no closed form integral. Notice484that the answer comes back as an expression that contains an485integral itself.486487::488489sage: A = integral(1/ ((x-4) * (x^3+2*x+1)), x); A4901/73*log(x - 4) - 1/73*integrate((x^2 + 4*x + 18)/(x^3 + 2*x + 1), x)491492We now show that floats are not converted to rationals493automatically since we by default have keepfloat: true in maxima.494495::496497sage: integral(e^(-x^2),(x, 0, 0.1))4980.0562314580091*sqrt(pi)499500ALIASES: integral() and integrate() are the same.501502EXAMPLES:503504Here is an example where we have to use assume::505506sage: a,b = var('a,b')507sage: integrate(1/(x^3 *(a+b*x)^(1/3)), x)508Traceback (most recent call last):509...510ValueError: Computation failed since Maxima requested additional511constraints; using the 'assume' command before integral evaluation512*may* help (example of legal syntax is 'assume(a>0)', see `assume?`513for more details)514Is a positive or negative?515516So we just assume that `a>0` and the integral works::517518sage: assume(a>0)519sage: integrate(1/(x^3 *(a+b*x)^(1/3)), x)5202/9*sqrt(3)*b^2*arctan(1/3*(2*(b*x + a)^(1/3) + a^(1/3))*sqrt(3)/a^(1/3))/a^(7/3) + 2/9*b^2*log((b*x + a)^(1/3) - a^(1/3))/a^(7/3) - 1/9*b^2*log((b*x + a)^(2/3) + (b*x + a)^(1/3)*a^(1/3) + a^(2/3))/a^(7/3) + 1/6*(4*(b*x + a)^(5/3)*b^2 - 7*(b*x + a)^(2/3)*a*b^2)/((b*x + a)^2*a^2 - 2*(b*x + a)*a^3 + a^4)521522TESTS:523524The following integral was broken prior to Maxima 5.15.0 -525see #3013::526527sage: integrate(sin(x)*cos(10*x)*log(x), x)5281/198*(11*cos(9*x) - 9*cos(11*x))*log(x) + 1/44*Ei(-11*I*x) + 1/44*Ei(11*I*x) - 1/36*Ei(-9*I*x) - 1/36*Ei(9*I*x)529530It is no longer possible to use certain functions without an531explicit variable. Instead, evaluate the function at a variable,532and then take the integral::533534sage: integrate(sin)535Traceback (most recent call last):536...537TypeError538539sage: integrate(sin(x), x)540-cos(x)541sage: integrate(sin(x), x, 0, 1)542-cos(1) + 1543544Check if #780 is fixed::545546sage: _ = var('x,y')547sage: f = log(x^2+y^2)548sage: res = integral(f,x,0.0001414, 1.); res549Traceback (most recent call last):550...551ValueError: Computation failed since Maxima requested additional constraints; using the 'assume' command before integral evaluation *may* help (example of legal syntax is 'assume(50015104*y^2-50015103>0)', see `assume?` for more details)552Is 50015104*y^2-50015103 positive, negative, or zero?553sage: assume(y>1)554sage: res = integral(f,x,0.0001414, 1.); res5552*y*arctan(1/y) - 2*y*arctan(0.0001414/y) - 0.0001414*log(y^2 + 1.999396e-08) + log(y^2 + 1.0) - 1.9997172556sage: nres = numerical_integral(f.subs(y=2), 0.0001414, 1.); nres557(1.4638323264144..., 1.6251803529759...e-14)558sage: res.subs(y=2).n()5591.46383232641443560sage: nres = numerical_integral(f.subs(y=.5), 0.0001414, 1.); nres561(-0.669511708872807, 7.768678110854711e-15)562sage: res.subs(y=.5).n()563-0.669511708872807564565Check if #6816 is fixed::566567sage: var('t,theta')568(t, theta)569sage: integrate(t*cos(-theta*t),t,0,pi)570(pi*theta*sin(pi*theta) + cos(pi*theta))/theta^2 - 1/theta^2571sage: integrate(t*cos(-theta*t),(t,0,pi))572(pi*theta*sin(pi*theta) + cos(pi*theta))/theta^2 - 1/theta^2573sage: integrate(t*cos(-theta*t),t)574(t*theta*sin(t*theta) + cos(t*theta))/theta^2575sage: integrate(x^2,(x)) # this worked before5761/3*x^3577sage: integrate(x^2,(x,)) # this didn't5781/3*x^3579sage: integrate(x^2,(x,1,2))5807/3581sage: integrate(x^2,(x,1,2,3))582Traceback (most recent call last):583...584ValueError: invalid input (x, 1, 2, 3) - please use variable, with or without two endpoints585586Note that this used to be the test, but it is587actually divergent (though Maxima as yet does588not say so)::589590sage: integrate(t*cos(-theta*t),(t,-oo,oo))591integrate(t*cos(t*theta), t, -Infinity, +Infinity)592593Check if #6189 is fixed (which, by the way, also594demonstrates it's not always good to expand)::595596sage: n = N; n597<function numerical_approx at ...>598sage: F(x) = 1/sqrt(2*pi*1^2)*exp(-1/(2*1^2)*(x-0)^2)599sage: G(x) = 1/sqrt(2*pi*n(1)^2)*exp(-1/(2*n(1)^2)*(x-n(0))^2)600sage: integrate( (F(x)-F(x))^2, x, -infinity, infinity).n()6010.000000000000000602sage: integrate( ((F(x)-G(x))^2).expand(), x, -infinity, infinity).n()603-6.26376265908397e-17604sage: integrate( (F(x)-G(x))^2, x, -infinity, infinity).n()605-6.26376265908397e-17606607This was broken before Maxima 5.20::608609sage: exp(-x*i).integral(x,0,1)610I*e^(-I) - I611612Test deprecation warning when variable is not specified::613614sage: x.integral()615doctest:...: DeprecationWarning: Variable of integration should be specified explicitly.6161/2*x^2617618Test that #8729 is fixed::619620sage: t = var('t')621sage: a = sqrt((sin(t))^2 + (cos(t))^2)622sage: integrate(a, t, 0, 2*pi)6232*pi624sage: a.simplify_full().simplify_trig()6251626627Maxima uses Cauchy Principal Value calculations to628integrate certain convergent integrals. Here we test629that this does not raise an error message (see #11987)::630631sage: integrate(sin(x)*sin(x/3)/x^2, x, 0, oo)6321/6*pi633634Maxima returned a negative value for this integral prior to635maxima-5.24 (trac #10923). Ideally we would get an answer in terms636of the gamma function; however, we get something equivalent::637638sage: actual_result = integral(e^(-1/x^2), x, 0, 1)639sage: actual_result.full_simplify()640((e*erf(1) - e)*sqrt(pi) + 1)*e^(-1)641sage: ideal_result = 1/2*gamma(-1/2, 1)642sage: error = actual_result - ideal_result643sage: error.numerical_approx() # abs tol 1e-106440645646We won't get an evaluated answer here, which is better than647the previous (wrong) answer of zero. See :trac:`10914`::648649sage: f = abs(sin(x))650sage: integrate(f, x, 0, 2*pi)651integrate(abs(sin(x)), x, 0, 2*pi)652653Another incorrect integral fixed upstream in Maxima, from654:trac:`11233`::655656sage: a,t = var('a,t')657sage: assume(a>0)658sage: assume(x>0)659sage: f = log(1 + a/(x * t)^2)660sage: F = integrate(f, t, 1, Infinity)661sage: F(x=1, a=7).numerical_approx() # abs tol 1e-106624.32025625668262663664Verify that MinusInfinity works with sympy (:trac:`12345`)::665666sage: integral(1/x^2, x, -infinity, -1, algorithm='sympy')6671668669"""670expression, v, a, b = _normalize_integral_input(expression, v, a, b)671if algorithm is not None:672integrator = available_integrators.get(algorithm)673if not integrator:674raise ValueError, "Unknown algorithm: %s" % algorithm675return integrator(expression, v, a, b)676if a is None:677return indefinite_integral(expression, v)678else:679return definite_integral(expression, v, a, b)680681integral= integrate682683684