It's hard to know what exactly will help, given the possible variations in the functions. One suggestion is to use GenerateConditions -> False, so that time is not spent on figuring out the complicated conditions for which the value of the integral is valid, as Sjoerd surmises; time will still be spent trying to figure out the limits at infinity (at least, I'm pretty sure that is a complicated calculation if you're going to worry about convergence). Another idea is to use Expectation, which is fast on certain expressions when x is normally distributed. The function int below should work and be fast when all three functions are Gaussian, as in the example. With some more work, one could split a Gaussian mixture pdf into its Gaussian components, integrate, and add. One might have to test what happens when f q / p is not reducible to Gaussians. Expectation might default to Integration such cases. Also, for some inputs the NormalDistribution constructed by int might be invalid.
Timings:
Integrate[integrand, {x, -Infinity, Infinity}]; // AbsoluteTiming
Integrate[integrand, {x, -Infinity, Infinity},
GenerateConditions -> False]; // AbsoluteTiming
int[f[x], p[x], q[x], x]; // AbsoluteTiming
(*
{20.370266, Null}
{5.157397, Null}
{0.001574, Null}
*)
Function:
int::nnormal = "`1` resulted in an invalid normal distribution. Using Integrate.";
int[f_, p_, q_, x_] := Module[{factor, exponent, a, b, c, integrand},
integrand = Simplify[f*q/p];
If[MatchQ[integrand, Power[E, _]],
factor = 1,
If[MatchQ[integrand, _Times],
factor = Times @@ Cases[integrand, Except[Power[E, _]]],
factor = integrand (* fails *)
]];
(*If[Internal`DependsOnQ[factor, x],
Return[Integrate[integrand, {x, -Infinity, Infinity},
GenerateConditions -> False, Assumptions -> Integrate`getAllVariables[integrand, x] ∈ Reals]]
];*)
exponent = Simplify[integrand/factor] /. Power[E, z_] :> z;
{c, b, a} = PadRight[CoefficientList[exponent, x], 3];
If[a =!= 0,
Sqrt[π]/Sqrt[-a] Exp[a (c/a - (b/(2 a))^2)] *
Expectation[factor, x \[Distributed] NormalDistribution[-b/(2 a), Sqrt[-1/(2 a)]]],
Message[int::nnormal, integrand];
Integrate[integrand, {x, -Infinity, Infinity},
GenerateConditions -> False, Assumptions -> Integrate`getAllVariables[integrand, x] ∈ Reals]
]
];
Uncomment the test Internal`DependsOnQ[factor, x] if you want the computation to default to Integrate when the factor is not a constant. In that case,
Expectation[factor, x \[Distributed] NormalDistribution[-b/(2 a), Sqrt[-1/(2 a)]]]
evaluates to factor, and the code could be shortened.
For alternatives to Integrate`getAllVariables[integrand, x], see Extracting variables from an expression and Get all variables in an expression with Variables[]. Sometimes it helps to include x ∈ Reals in assumptions, which is not included in the following:
Integrate`getAllVariables[integrand, x]
(* {a, b, c, x0, x1, x2} *)
Timing[Integrate[integrand, {x, -Infinity, Infinity}]]returns 13.5 s, the same with the assumption:Assumptions -> {a > 0, b > 0, c > 0, b > a, b > c}gives 7.2 s, while if instead I replace the variables within the integrand:Timing[Integrate[ integrand /. {a -> 1, b -> 2, c -> 1}, {x, -Infinity, Infinity}]]it yields 1.3 s. – Alexei Boulbitch Jan 09 '15 at 13:54