Path: blob/master/src/sage/symbolic/integration/integral.py
8818 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.282See http://trac.sagemath.org/12438 for details.283(x^2, x, 0, 3)284sage: _normalize_integral_input(x^2, [x], None, None)285(x^2, x, None, None)286"""287if isinstance(v, (list, tuple)) and a is None and b is None:288if len(v) == 1: # bare variable in a tuple289v = v[0]290elif len(v) == 2: # endpoints only291a, b = v292v = None293elif len(v) == 3: # variable and endpoints294v, a, b = v295else:296raise ValueError("invalid input %s - please use variable, "297"with or without two endpoints" % repr(v))298elif b is None and a is not None:299# two arguments, must be endpoints300v, a, b = None, v, a301if v is None:302from sage.misc.superseded import deprecation303deprecation(12438, "Variable of integration should be specified explicitly.")304v = f.default_variable()305if isinstance(f, Function): # a bare function like sin306f = f(v)307if (a is None) ^ (b is None):308raise TypeError('only one endpoint was given!')309return f, v, a, b310311def integrate(expression, v=None, a=None, b=None, algorithm=None):312r"""313Returns the indefinite integral with respect to the variable314`v`, ignoring the constant of integration. Or, if endpoints315`a` and `b` are specified, returns the definite316integral over the interval `[a, b]`.317318If ``self`` has only one variable, then it returns the319integral with respect to that variable.320321If definite integration fails, it could be still possible to322evaluate the definite integral using indefinite integration with323the Newton - Leibniz theorem (however, the user has to ensure that the324indefinite integral is continuous on the compact interval `[a,b]` and325this theorem can be applied).326327INPUT:328329- ``v`` - a variable or variable name. This can also be a tuple of330the variable (optional) and endpoints (i.e., ``(x,0,1)`` or ``(0,1)``).331332- ``a`` - (optional) lower endpoint of definite integral333334- ``b`` - (optional) upper endpoint of definite integral335336- ``algorithm`` - (default: 'maxima') one of337338- 'maxima' - use maxima (the default)339340- 'sympy' - use sympy (also in Sage)341342- 'mathematica_free' - use http://integrals.wolfram.com/343344EXAMPLES::345346sage: x = var('x')347sage: h = sin(x)/(cos(x))^2348sage: h.integral(x)3491/cos(x)350351::352353sage: f = x^2/(x+1)^3354sage: f.integral(x)3551/2*(4*x + 3)/(x^2 + 2*x + 1) + log(x + 1)356357::358359sage: f = x*cos(x^2)360sage: f.integral(x, 0, sqrt(pi))3610362sage: f.integral(x, a=-pi, b=pi)3630364365::366367sage: f(x) = sin(x)368sage: f.integral(x, 0, pi/2)3691370371The variable is required, but the endpoints are optional::372373sage: y=var('y')374sage: integral(sin(x), x)375-cos(x)376sage: integral(sin(x), y)377y*sin(x)378sage: integral(sin(x), x, pi, 2*pi)379-2380sage: integral(sin(x), y, pi, 2*pi)381pi*sin(x)382sage: integral(sin(x), (x, pi, 2*pi))383-2384sage: integral(sin(x), (y, pi, 2*pi))385pi*sin(x)386387Constraints are sometimes needed::388389sage: var('x, n')390(x, n)391sage: integral(x^n,x)392Traceback (most recent call last):393...394ValueError: Computation failed since Maxima requested additional395constraints; using the 'assume' command before integral evaluation396*may* help (example of legal syntax is 'assume(n+1>0)', see `assume?`397for more details)398Is n+1 zero or nonzero?399sage: assume(n > 0)400sage: integral(x^n,x)401x^(n + 1)/(n + 1)402sage: forget()403404Usually the constraints are of sign, but others are possible::405406sage: assume(n==-1)407sage: integral(x^n,x)408log(x)409410Note that an exception is raised when a definite integral is411divergent::412413sage: forget() # always remember to forget assumptions you no longer need414sage: integrate(1/x^3,(x,0,1))415Traceback (most recent call last):416...417ValueError: Integral is divergent.418sage: integrate(1/x^3,x,-1,3)419Traceback (most recent call last):420...421ValueError: Integral is divergent.422423But Sage can calculate the convergent improper integral of424this function::425426sage: integrate(1/x^3,x,1,infinity)4271/2428429The examples in the Maxima documentation::430431sage: var('x, y, z, b')432(x, y, z, b)433sage: integral(sin(x)^3, x)4341/3*cos(x)^3 - cos(x)435sage: integral(x/sqrt(b^2-x^2), b)436x*log(2*b + 2*sqrt(b^2 - x^2))437sage: integral(x/sqrt(b^2-x^2), x)438-sqrt(b^2 - x^2)439sage: integral(cos(x)^2 * exp(x), x, 0, pi)4403/5*e^pi - 3/5441sage: integral(x^2 * exp(-x^2), x, -oo, oo)4421/2*sqrt(pi)443444We integrate the same function in both Mathematica and Sage (via445Maxima)::446447sage: _ = var('x, y, z')448sage: f = sin(x^2) + y^z449sage: g = mathematica(f) # optional - mathematica450sage: print g # optional - mathematica451z 2452y + Sin[x ]453sage: print g.Integrate(x) # optional - mathematica454z Pi 2455x y + Sqrt[--] FresnelS[Sqrt[--] x]4562 Pi457sage: print f.integral(x)458x*y^z + 1/8*sqrt(pi)*((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))459460Alternatively, just use algorithm='mathematica_free' to integrate via Mathematica461over the internet (does NOT require a Mathematica license!)::462463sage: _ = var('x, y, z')464sage: f = sin(x^2) + y^z465sage: f.integrate(algorithm="mathematica_free") # optional - internet466sqrt(pi)*sqrt(1/2)*fresnels(sqrt(2)*x/sqrt(pi)) + y^z*x467468We can also use Sympy::469470sage: integrate(x*sin(log(x)), x)471-1/5*x^2*(cos(log(x)) - 2*sin(log(x)))472sage: integrate(x*sin(log(x)), x, algorithm='sympy')473-1/5*x^2*cos(log(x)) + 2/5*x^2*sin(log(x))474sage: _ = var('y, z')475sage: (x^y - z).integrate(y)476-y*z + x^y/log(x)477sage: (x^y - z).integrate(y, algorithm="sympy") # see Trac #14694478Traceback (most recent call last):479...480AttributeError: 'Piecewise' object has no attribute '_sage_'481482We integrate the above function in Maple now::483484sage: g = maple(f); g # optional - maple485sin(x^2)+y^z486sage: g.integrate(x) # optional - maple4871/2*2^(1/2)*Pi^(1/2)*FresnelS(2^(1/2)/Pi^(1/2)*x)+y^z*x488489We next integrate a function with no closed form integral. Notice490that the answer comes back as an expression that contains an491integral itself.492493::494495sage: A = integral(1/ ((x-4) * (x^3+2*x+1)), x); A496-1/73*integrate((x^2 + 4*x + 18)/(x^3 + 2*x + 1), x) + 1/73*log(x - 4)497498We now show that floats are not converted to rationals499automatically since we by default have keepfloat: true in maxima.500501::502503sage: integral(e^(-x^2),(x, 0, 0.1))5040.0562314580091*sqrt(pi)505506ALIASES: integral() and integrate() are the same.507508EXAMPLES:509510Here is an example where we have to use assume::511512sage: a,b = var('a,b')513sage: integrate(1/(x^3 *(a+b*x)^(1/3)), x)514Traceback (most recent call last):515...516ValueError: Computation failed since Maxima requested additional517constraints; using the 'assume' command before integral evaluation518*may* help (example of legal syntax is 'assume(a>0)', see `assume?`519for more details)520Is a positive or negative?521522So we just assume that `a>0` and the integral works::523524sage: assume(a>0)525sage: integrate(1/(x^3 *(a+b*x)^(1/3)), x)5262/9*sqrt(3)*b^2*arctan(1/3*sqrt(3)*(2*(b*x + a)^(1/3) + 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) + 2/9*b^2*log((b*x + a)^(1/3) - a^(1/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)527528TESTS:529530The following integral was broken prior to Maxima 5.15.0 -531see #3013::532533sage: integrate(sin(x)*cos(10*x)*log(x), x)534-1/198*(9*cos(11*x) - 11*cos(9*x))*log(x) + 1/44*Ei(11*I*x) - 1/36*Ei(9*I*x) - 1/36*Ei(-9*I*x) + 1/44*Ei(-11*I*x)535536It is no longer possible to use certain functions without an537explicit variable. Instead, evaluate the function at a variable,538and then take the integral::539540sage: integrate(sin)541Traceback (most recent call last):542...543TypeError544545sage: integrate(sin(x), x)546-cos(x)547sage: integrate(sin(x), x, 0, 1)548-cos(1) + 1549550Check if #780 is fixed::551552sage: _ = var('x,y')553sage: f = log(x^2+y^2)554sage: res = integral(f,x,0.0001414, 1.); res555Traceback (most recent call last):556...557ValueError: 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)558Is 50015104*y^2-50015103 positive, negative, or zero?559sage: assume(y>1)560sage: res = integral(f,x,0.0001414, 1.); res561-2*y*arctan(0.0001414/y) + 2*y*arctan(1/y) + log(y^2 + 1.0) - 0.0001414*log(y^2 + 1.999396e-08) - 1.9997172562sage: nres = numerical_integral(f.subs(y=2), 0.0001414, 1.); nres563(1.4638323264144..., 1.6251803529759...e-14)564sage: res.subs(y=2).n()5651.46383232641443566sage: nres = numerical_integral(f.subs(y=.5), 0.0001414, 1.); nres567(-0.669511708872807, 7.768678110854711e-15)568sage: res.subs(y=.5).n()569-0.669511708872807570571Check if #6816 is fixed::572573sage: var('t,theta')574(t, theta)575sage: integrate(t*cos(-theta*t),t,0,pi)576(pi*theta*sin(pi*theta) + cos(pi*theta))/theta^2 - 1/theta^2577sage: integrate(t*cos(-theta*t),(t,0,pi))578(pi*theta*sin(pi*theta) + cos(pi*theta))/theta^2 - 1/theta^2579sage: integrate(t*cos(-theta*t),t)580(t*theta*sin(t*theta) + cos(t*theta))/theta^2581sage: integrate(x^2,(x)) # this worked before5821/3*x^3583sage: integrate(x^2,(x,)) # this didn't5841/3*x^3585sage: integrate(x^2,(x,1,2))5867/3587sage: integrate(x^2,(x,1,2,3))588Traceback (most recent call last):589...590ValueError: invalid input (x, 1, 2, 3) - please use variable, with or without two endpoints591592Note that this used to be the test, but it is593actually divergent (though Maxima as yet does594not say so)::595596sage: integrate(t*cos(-theta*t),(t,-oo,oo))597integrate(t*cos(t*theta), t, -Infinity, +Infinity)598599Check if #6189 is fixed::600601sage: n = N; n602<function numerical_approx at ...>603sage: F(x) = 1/sqrt(2*pi*1^2)*exp(-1/(2*1^2)*(x-0)^2)604sage: G(x) = 1/sqrt(2*pi*n(1)^2)*exp(-1/(2*n(1)^2)*(x-n(0))^2)605sage: integrate( (F(x)-F(x))^2, x, -infinity, infinity).n()6060.000000000000000607sage: integrate( ((F(x)-G(x))^2).expand(), x, -infinity, infinity).n()608-6.26376265908397e-17609sage: integrate( (F(x)-G(x))^2, x, -infinity, infinity).n()# abstol 1e-66100611612This was broken before Maxima 5.20::613614sage: exp(-x*i).integral(x,0,1)615I*e^(-I) - I616617Test deprecation warning when variable is not specified::618619sage: x.integral()620doctest:...: DeprecationWarning:621Variable of integration should be specified explicitly.622See http://trac.sagemath.org/12438 for details.6231/2*x^2624625Test that #8729 is fixed::626627sage: t = var('t')628sage: a = sqrt((sin(t))^2 + (cos(t))^2)629sage: integrate(a, t, 0, 2*pi)6302*pi631sage: a.simplify_full().simplify_trig()6321633634Maxima uses Cauchy Principal Value calculations to635integrate certain convergent integrals. Here we test636that this does not raise an error message (see #11987)::637638sage: integrate(sin(x)*sin(x/3)/x^2, x, 0, oo)6391/6*pi640641Maxima returned a negative value for this integral prior to642maxima-5.24 (trac #10923). Ideally we would get an answer in terms643of the gamma function; however, we get something equivalent::644645sage: actual_result = integral(e^(-1/x^2), x, 0, 1)646sage: actual_result.simplify_radical()647(sqrt(pi)*(erf(1)*e - e) + 1)*e^(-1)648sage: ideal_result = 1/2*gamma(-1/2, 1)649sage: error = actual_result - ideal_result650sage: error.numerical_approx() # abs tol 1e-106510652653We won't get an evaluated answer here, which is better than654the previous (wrong) answer of zero. See :trac:`10914`::655656sage: f = abs(sin(x))657sage: integrate(f, x, 0, 2*pi) # long time (4s on sage.math, 2012)658integrate(abs(sin(x)), x, 0, 2*pi)659660Another incorrect integral fixed upstream in Maxima, from661:trac:`11233`::662663sage: a,t = var('a,t')664sage: assume(a>0)665sage: assume(x>0)666sage: f = log(1 + a/(x * t)^2)667sage: F = integrate(f, t, 1, Infinity)668sage: F(x=1, a=7).numerical_approx() # abs tol 1e-106694.32025625668262670671Verify that MinusInfinity works with sympy (:trac:`12345`)::672673sage: integral(1/x^2, x, -infinity, -1, algorithm='sympy')6741675676Check that :trac:`11737` is fixed::677678sage: N(integrate(sin(x^2)/(x^2), x, 1, infinity))6790.285736646322858680681"""682expression, v, a, b = _normalize_integral_input(expression, v, a, b)683if algorithm is not None:684integrator = available_integrators.get(algorithm)685if not integrator:686raise ValueError, "Unknown algorithm: %s" % algorithm687return integrator(expression, v, a, b)688if a is None:689return indefinite_integral(expression, v)690else:691return definite_integral(expression, v, a, b)692693integral= integrate694695696