Function Repository Resource:

ParameterizedFunctionIntegrate

Source Notebook

Compute the integral of an expression involving parameters, returning a piecewise result correct for all specializations of the parameters

Contributed by: David R. Stoutemyer (dstout@hawaii.edu) and Paco Jain (Wolfram Research)

ResourceFunction["ParameterizedFunctionIntegrate"][f,x]

gives the indefinite integral .

ResourceFunction["ParameterizedFunctionIntegrate"][f,{x,xmin,xmax}]

gives the definite integral .

ResourceFunction["ParameterizedFunctionIntegrate"][f,{x,xmin,xmax},{y,ymin,ymax}]

gives the definite integral f.

ResourceFunction["ParameterizedFunctionIntegrate"][f,{x,y,}reg]

integrates over the geometric region reg.

Details and Options

ResourceFunction["ParameterizedFunctionIntegrate"] supplements the built-in Wolfram Language function Integrate function by computing more robust antiderivatives of integrands containing symbolic parameters. For example, for the function f(z)=zα, ResourceFunction["ParameterizedFunctionIntegrate"] returns for f'(z) the Piecewise expression rather than the bare returned by Integrate. In general, Integrate returns a result that is generically true for "almost all" values of the symbolic parameters appearing in the integrand, but may be invalid on a set of measure zero in the complex plane (in this case, the set α = -1).
ResourceFunction["ParameterizedFunctionIntegrate"] takes the following options:
Assumptions$Assumptionsassumptions to make about parameters
GenerateConditionsTruewhether to generate answers that involve conditions on parameters
"MostGeneralFirstQ"Truewhether to attempt to order the most generic case first in Piecewise results
"ParameterTreatment""Comprehensive"how to treat free symbolic parameters of the integrand
PrincipalValueFalsewhether to find Cauchy principal values
"SubtaskTimeLimit"4.0the maximum time in seconds allotted for individual integration sub-tasks
"TrueInPiecewiseMeans"Nonewhether to Print a user assistance mesage describing the True case in Piecewise results
The value of the Assumptions option can be an equation, inequality, domain specification, or a list or logical combinations of these.
Possible settings for the GenerateConditions option include:
Allreturn all possible answers using Piecewise
Automaticreturn a condition only if it is not generically satisfied
Truereturn any condition that is needed
Falsenever return any needed conditions
Nonereturn unevaluated if conditions are needed
When "MostGeneralFirstQ" is set to True (default), ResourceFunction["ParameterizedFunctionIntegrate"] tries to order the most general generic case first in comprehensive Piecewise results. Using "MostGeneralFirstQ"False is slightly faster and tries to order the most general generic case last in Piecewise. This often leads to simpler predicates overall and is closer to the way many programmers implement functions.
ResourceFunction["ParameterizedFunctionIntegrate"] uses the built-in Limit function to compute the constant terms in some results. Optionally, if Limit does not succeed, NLimit can be used where applicable; this behaviour is controlled using the option "NLimitUse". Possible settings for this option are None (default), InexactNumberQ, ExactNumberQ and Automatic. The effects of these settings are illustrated in the examples section below. A warning is issued if ResourceFunction["ParameterizedFunctionIntegrate"] returns a result that uses a limit determined via NLimit.
The "ParameterTreatment" options controls how integrand parameters are treated in antiderivatives. Allowed values are "Generic", "Conditional", "Comprehensive" (the default), "Continuous" and "ApartContinuous" that are successively more ambitious and time-consuming. The meaning of these settings is briefly described in the second column of the table below and expanded upon in examples. In the third column of the table, we compare the expressions returned for the antiderivative of thef(z) = zα under the various settings:
"Generic"directly returns the result of Integrate
"Conditional"returns an expression indicating which specializations of a generic antiderivative are valid
"Comprehensive"returns a Piecewise function that is valid for all combinations of parameter values
"Continuous"attempts to return a Piecewise result that is maximally continuous
"ApartContinuous"makes the presence of an intentionally-introduced constant more obvious as a separate term
The default setting PrincipalValueFalse computes ordinary Riemann integrals. Setting PrincipalValue gives finite answers for integrals that have simple pole divergences with PrincipalValueFalse.
The "SubtaskTimeLimit" option sets the maximum allowed seconds for each Limit, Solve, Simplify and FullSimplify call made within ResourceFunction["ParameterizedFunctionIntegrate"]. Timeouts occur most often for "ParameterTreatment""Continuous" and "ParameterTreatment""ApartContinuous".
The option "TrueInPiecewiseMeans" determines whether to Print a user assistance mesage describing the boolean condition for the True clause to hold in Piecewise results. If set to None (default), no messages are printed. If set to All, messages are printed for all Piecewise results. If set to Automatic, a message is printed only when the Piecewise contains more than two clauses.
ResourceFunction["ParameterizedFunctionIntegrate"] directy invokes Integrate for definite integrals specified by a region such as ResourceFunction["ParameterizedFunctionIntegrate"][x2y,{x,y}Disk[{0,3},4].
ResourceFunction["ParameterizedFunctionIntegrate"] internally issues Assert calls to alert the user to certain exceptional cases. Use On[Assert] or Off[Assert] prior to calling ResourceFunction["ParameterizedFunctionIntegrate"] to control whether these warnings are invoked. See Possible Issues in the examples for more details.

Examples

Basic Examples (2) 

Compute the indefinite integral of a trigonometric function containing the parameter a:

In[1]:=
ResourceFunction["ParameterizedFunctionIntegrate"][Sin[a z], z]
Out[1]=

Contrast with the generic result returned by Integrate:

In[2]:=
Integrate[Sin[a x], x]
Out[2]=

A typical incorrect specialization of a generic formula:

In[3]:=
expr = (\[Alpha]^(\[Sigma] z) - \[Alpha]^(\[Lambda] z))^2;
I1 = Integrate[expr, z]
Out[4]=

but, with σ=0:

In[5]:=
% /. \[Sigma] -> 0
Out[5]=

Pre-substitution shows that the original integral was well defined:

In[6]:=
Integrate[expr /. \[Sigma] -> 0, z]
Out[6]=

Get the comprehensize Piecewise result, correct for all values of α:

In[7]:=
ResourceFunction["ParameterizedFunctionIntegrate"][expr, z]
Out[7]=

Scope (2) 

Compute a definite integral:

In[8]:=
ResourceFunction["ParameterizedFunctionIntegrate"][
 Sin[a z], {z, 0, 1}]
Out[8]=

Perform an integral over a Region in the {x,y} plane:

In[9]:=
ResourceFunction["ParameterizedFunctionIntegrate"][
 x^2 y, {x, y} \[Element] Disk[{0, 3}, 4]]
Out[9]=

Options (16) 

Assumptions (2) 

For certain "ParameterTreatment" settings, ParameterizedFunctionIntegrate will return conditions on parameters that ensure convergence:

In[10]:=
ResourceFunction["ParameterizedFunctionIntegrate"][x^n, {x, 0, 1}, "ParameterTreatment" -> "Conditional"]
Out[10]=

With Assumptions, a result valid under the given assumptions is returned:

In[11]:=
ResourceFunction["ParameterizedFunctionIntegrate"][x^n, {x, 0, 1}, Assumptions -> n > 0, "ParameterTreatment" -> "Conditional"]
Out[11]=

It is generally more appropriate and effective to use Assuming[assump,ParameterizedFunctionIntegrate[]] rather than ParameterizedFunctionIntegrate[,Assumptionsassump], as the latter only applies assumptions when computing a generic antiderivative with Integrate, while the former applies assumptions at all stages of the computation.

GenerateConditions (2) 

For certain "ParameterTreatment" settings, ParameterizedFunctionIntegrate will return conditions on parameters that ensure convergence:

In[12]:=
ResourceFunction["ParameterizedFunctionIntegrate"][
 Exp[-a x^2], {x, 0, \[Infinity]}, "ParameterTreatment" -> "Generic"]
Out[12]=

Use GerenateConditionsFalse to suppress conditions in these cases:

In[13]:=
ResourceFunction["ParameterizedFunctionIntegrate"][
 Exp[-a x^2], {x, 0, \[Infinity]}, GenerateConditions -> False, "ParameterTreatment" -> "Generic"]
Out[13]=

The GenerateConditions option is only effectual when the "ParameterTreatment" option is set to "Generic" or "Conditional".


GenerateConditionsFalse can speed up integration:

In[14]:=
ResourceFunction["ParameterizedFunctionIntegrate"][x^n, {x, -1, b}, "ParameterTreatment" -> "Generic"] // Timing
Out[14]=
In[15]:=
ResourceFunction["ParameterizedFunctionIntegrate"][x^n, {x, -1, b}, GenerateConditions -> False, "ParameterTreatment" -> "Generic"] // Timing
Out[15]=

MostGeneralFirstQ (2) 

By default, the first clause in Piecewise results returned by ParameterizedFunctionIntegrate is the one that applies most generically with respect to specializaiton of parameter values:

In[16]:=
ResourceFunction["ParameterizedFunctionIntegrate"][z^b Log[z], z]
Out[16]=

The opposite ordering, with the most generic clause given last, can be obtained using MostGeneralFirstQFalse. This gives predicates that may be easier to understand at a glance:

In[17]:=
ResourceFunction["ParameterizedFunctionIntegrate"][z^b Log[z], z, MostGeneralFirstQ -> False]
Out[17]=

ParameterTreatment (5) 

Using "ParameterTreatment" "Generic" gives the most generic result, equivalent to the result of Integrate:

In[18]:=
generic = ResourceFunction["ParameterizedFunctionIntegrate"] [z^\[Alpha], z, "ParameterTreatment" -> "Generic"]
Out[18]=

However, this generic antiderivative quietly returns an incorrect antiderivative when later specialized to α -1:

In[19]:=
generic /. \[Alpha] -> -1
Out[19]=

For generic antiderivatives, substitution does not necessarily commute with integration:

In[20]:=
ResourceFunction["ParameterizedFunctionIntegrate"] [
 z^\[Alpha] /. \[Alpha] -> -1, z, "ParameterTreatment" -> "Generic"]
Out[20]=

ParameterTreatment"Conditional" attempts to indicate what specializations of a generic antiderivative are valid with ConditionalExpression:

In[21]:=
conditional = ResourceFunction["ParameterizedFunctionIntegrate"] [z^\[Alpha], z, "ParameterTreatment" -> "Conditional"]
Out[21]=

The result of an invalid substitution is now more appropriately given as Undefined rather than ComplexInfinity:

In[22]:=
conditional /. \[Alpha] -> -1
Out[22]=

By default, the built-in Wolfram Language Integrate already returns ConditionalExpressions when appropriate for parametric definite integrals:

In[23]:=
Integrate [z^\[Alpha], {z, 0, 1}]
Out[23]=

But not in the coresponding indefinite case:

In[24]:=
Integrate [z^\[Alpha], z]
Out[24]=

For antiderivatives, ParameterizedFunctionIntegrate[,"ParameterTreatment""Comprehensive"] returns a Piecewise function that is valid for all combinations of parameter values. For parametric integrands, the result is often a Piecewise result wherein one of the consequents is a generic antiderivative :

In[25]:=
comprehensive = ResourceFunction["ParameterizedFunctionIntegrate"] [z^\[Alpha], z, "ParameterTreatment" -> "Comprehensive"]
Out[25]=

Specialization gives a correct result for all α:

In[26]:=
comprehensive /. \[Alpha] -> -1
Out[26]=

The following plot illustrates the discontinuity of this Piecewise result at the parameter value α=-1:

In[27]:=
Options [plotSurfaceAndCurve] = {Exclusions -> All};
plotSurfaceAndCurve [surface_, curve_, integrationVarRange_,
       parameterRange_, surfaceRange_, specialParameterRule_, options : OptionsPattern[]] :=
    Show [
       Plot3D [surface, integrationVarRange, parameterRange, PlotRange -> surfaceRange, AxesLabel -> {First[integrationVarRange], First [parameterRange]}, PlotPoints -> 100,
                MeshStyle -> Gray,
                Exclusions -> OptionValue [Exclusions]],
       ParametricPlot3D[{First[integrationVarRange], Last [specialParameterRule], curve},
                         integrationVarRange,
                         PlotRange -> surfaceRange, PlotStyle -> Black,
                         Exclusions -> OptionValue [Exclusions]]];
In[28]:=
plotSurfaceAndCurve[Re[z^(1 + \[Alpha])/(1 + \[Alpha])], Re[Log[z]], {z, -2, 2}, {\[Alpha], -3, 1}, {-5, 5}, \[Alpha] -> -1]
Out[28]=

At the expense of more computing time, "ParameterTreatment" "Continuous" attempts to return a Piecewise result that is maximally continuous:

In[29]:=
parametricallyContinuous = ResourceFunction["ParameterizedFunctionIntegrate"][z^\[Alpha] , z, "ParameterTreatment" -> "Continuous"]
Out[29]=

The generic first consequent is different from the corresponding in the generic consequent of the merely "Comprehensive" result. To verify that consequent is valid:

In[30]:=
D[(-1 + z^(1 + \[Alpha]))/(1 + \[Alpha]), z]
Out[30]=

The different consequent makes the overall antiderivative continuous with respect to parameter α, as suggested by the following plot:

In[31]:=
Options [plotSurfaceAndCurve] = {Exclusions -> All};
plotSurfaceAndCurve [surface_, curve_, integrationVarRange_,
       parameterRange_, surfaceRange_, specialParameterRule_, options : OptionsPattern[]] :=
    Show [
       Plot3D [surface, integrationVarRange, parameterRange, PlotRange -> surfaceRange, AxesLabel -> {First[integrationVarRange], First [parameterRange]}, PlotPoints -> 100,
                MeshStyle -> Gray,
                Exclusions -> OptionValue [Exclusions]],
       ParametricPlot3D[{First[integrationVarRange], Last [specialParameterRule], curve},
                         integrationVarRange,
                         PlotRange -> surfaceRange, PlotStyle -> Black,
                         Exclusions -> OptionValue [Exclusions]]];
In[32]:=
plotSurfaceAndCurve[Re[(-1 + z^(1 + \[Alpha]))/(1 + \[Alpha])], Re[Log[z]], {z, -2, 2}, {\[Alpha], -3, 1}, {-5, 5}, \[Alpha] -> -1, Exclusions -> All]
Out[32]=

The parametric continuity was accomplished by introducing a particular integration constant that is a function of at most the parameter alone, making its partial derivative with respect to the integration variable z vanish. Although parametric continuity is not necessary for some applications, including definite integration, see "Applications" for a differential equation example where parametric continuity is necessary.


At the expense of more time, and perhaps also more catastrophic cancellation when substituting floating-point numbers near a special case, setting "ParameterTreatment""ApartContinuous" will attempt to make the presence of intentionally-introduced constants more obvious in a separate term:

In[33]:=
apartContinuous = ResourceFunction["ParameterizedFunctionIntegrate"] [z^\[Alpha], z, "ParameterTreatment" -> "ApartContinuous"]
Out[33]=

Contrast with the merely "Continuous" result:

In[34]:=
ResourceFunction["ParameterizedFunctionIntegrate"][z^\[Alpha] , z, "ParameterTreatment" -> "Continuous"]
Out[34]=

PrincipalValue (2) 

Certain ordinary Riemann definite integrals are divergent:

In[35]:=
ResourceFunction["ParameterizedFunctionIntegrate"][Tan[x], {x, 0, Pi}]
Out[35]=

By interpreting instead as a Cauchy principal value integral, we can give meaning to such cases:

In[36]:=
ResourceFunction["ParameterizedFunctionIntegrate"][Tan[x], {x, 0, Pi},
  PrincipalValue -> True]
Out[36]=

TrueInPiecewiseMeans (3) 

Use "TrueInPiecewiseMeans" All to Print a user assistance message which expands the True predicate in Piecewise results into a condition on parameters:

In[37]:=
ResourceFunction[
 "ParameterizedFunctionIntegrate"][\[Alpha]^(\[Sigma] z), z, "TrueInPiecewiseMeans" -> All]
Out[37]=

By default, "TrueInPiecewiseMeans"False and no messages are printed:

In[38]:=
ResourceFunction[
 "ParameterizedFunctionIntegrate"][\[Alpha]^(\[Sigma] z), z]
Out[38]=

When "TrueInPiecewiseMeans" Automatic, a message is printed when the number of Piecewise clauses is greater than two:

In[39]:=
ResourceFunction[
 "ParameterizedFunctionIntegrate"][\[Alpha]^(\[Sigma] z), z, "TrueInPiecewiseMeans" -> Automatic]
Out[39]=

But not otherwise:

In[40]:=
ResourceFunction["ParameterizedFunctionIntegrate"][z^ \[Alpha], z, "TrueInPiecewiseMeans" -> Automatic]
Out[40]=

Properties and Relations (2) 

Using ParameterizedFunctionIntegrate within an enclosing Assuming returns a ConditionalExpression that might or might not contain a Piecewise result:

In[41]:=
Assuming [\[Alpha] > -3, ResourceFunction["ParameterizedFunctionIntegrate"][z^\[Alpha], z, "ParameterTreatment" -> "Comprehensive"]]
Out[41]=
In[42]:=
Assuming [\[Alpha] > -1, ResourceFunction["ParameterizedFunctionIntegrate"][z^\[Alpha], z, "ParameterTreatment" -> "Comprehensive"]]
Out[42]=

ParameterizedFunctionIntegrate is more likely to succeed and to do so quickly if wrapped in Assuming rather than doing a replacement after obtaining a more general result.


As with most Wolfram Language functions, the default domain for the integration variable and parameters is the Complexes. However, you can use Assuming to restrict the integration variable and/or parameters to the Reals:

In[43]:=
Assuming [Element [z | \[Alpha], Reals], ResourceFunction["ParameterizedFunctionIntegrate"] [z^\[Alpha], z, "ParameterTreatment" -> "Comprehensive"]]
Out[43]=

In contrast, for the Complexes:

In[44]:=
ResourceFunction["ParameterizedFunctionIntegrate"] [z^\[Alpha], z, "ParameterTreatment" -> "Comprehensive"]
Out[44]=

As illustrated by this result, restricting parameters or the integration variable to the reals often results in a less concise result, and it usually requires more computing time. Since a result that is valid for the complexes is also valid for the reals, it is recommended that ParameterizedFunctionIntegrate is first used without such assumptions.

You might sometimes benefit from making some parameters be elements of the integers, particularly if they occur in exponents or in subexpressions such as Sin[nπ]. There might even be examples that benefit rather than suffer from declaring some parameters to be Booleans, Primes, Rationals or Algebraics, but for such examples, try first without assumptions because such restrictions often increase the complexity and computing time for no significant benefit.

Neat Examples (4) 

When can continuity matter? (4) 

DSolve returns generic general solutions to ordinary differential equations without boundary conditions:

In[45]:=
FullSimplify [
 DSolve [y''[t] + \[Omega]^2 y[t] == Cos[\[Kappa] t], y[t], t]]
Out[45]=

But the specialization of the particular portion of the above generic solution for the resonance as ω κ is incorrect:

In[46]:=
Limit[-(Cos[
   t \[Kappa]]/(\[Kappa]^2 - \[Omega]^2)), \[Omega] -> \[Kappa]]
Out[46]=

We can instead compute the particular portion of the generic general solution with parametrically-continuous comprehensive antiderivatives, and a result valid at resonance is obtained. The first clause of this Piecewise result is the generic particular solution. The second clause is its specialization to the particular solution for ω = κ:

In[47]:=
y1 = Cos [\[Kappa] t];
y2 = Sin[\[Kappa] t];
Wrongskian = Simplify [y1*D[y2, t] - y2*D[y1, t]];
parametricallyContinuousParticular = FullSimplify[
  y2*ResourceFunction["ParameterizedFunctionIntegrate"] [(
     y1 Cos[\[Omega] t])/Wrongskian, t, "ParameterTreatment" -> "Continuous"] - y1*ResourceFunction["ParameterizedFunctionIntegrate"] [(
     y2 Cos[\[Omega] t])/Wrongskian, t, "ParameterTreatment" -> "Continuous"]]
Out[6]=

Using this method with the built-in Integrate misses the discontinuity at ω = κ:

In[48]:=
y1 = Cos [\[Kappa] t];
y2 = Sin[\[Kappa] t];
Wrongskian = Simplify [y1*D[y2, t] - y2*D[y1, t]];
FullSimplify[
 y2*Integrate [(y1 Cos[\[Omega] t])/Wrongskian, t] - y1*Integrate [(y2 Cos[\[Omega] t])/Wrongskian, t]]
Out[49]=

Version History

  • 1.2.0 – 06 March 2021
  • 1.0.0 – 21 December 2020

Source Metadata

Related Resources

Author Notes

This package works for Mathematica version 11.0 or later. Some of the capability is usable with earlier versions of Mathematica.

ParameterizedFunctionIntegrate["Version"] returns a string containing the internal version of Integrate.m upon which this Resource Function is based. Please include the value of this variable in bug reports and citations.

Ultra permissive “MIT copyright” notice …

Copyright (c) 2017, David R. Stoutemyer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

History and purpose …

As of April 2017, this Mathematica package is under development by David R. Stoutemyer (dstout@hawaii.edu), in support of an article by Robert M. Corless, David J. Jeffrey and David R. Stoutemyer, titled "Integrals of functions containing parameters", for which we plan to post a preprint at arXiv.org . An extended abstract is "Comprehensive anti-derivatives and parametric continuity", ACM Communications in Computer Algebra 52(2):32-33, DOI: 10.1145/3282678.3282680 .

License Information