# Time differences between code using user-defined probability distribution and code using built-in distribution

Why is the reponse time of of kernel significantly different when I use the first code rather than the second? Shouldn it not be the same? Is there any way that the response time can be made smaller without having to use probability distributions built into Mathematica?

Code 1:

triangular = TriangularDistribution[{0, 12}, 6];
Manipulate[
Plot[{
PDF[triangular, x]*If[x <= Quantile[triangular, p], 1, 0],
CDF[triangular, x],
PDF[triangular, x]},
{x, 0, 12},
PlotRange -> All, Filling -> {1 -> Axis}, ImageSize -> Large, AxesLabel -> {x, ""}],
{p, .6, "Percentil"}, 0, 1, .001, Appearance -> "Labeled"}]


Code 2:

D = ProbabilityDistribution[
Piecewise[{{
x/36, 0 <= x <= 6},
{(12 - x)/36, 6 < x <= 12}}],
{x, 0,12}];
Manipulate[
Plot[{
PDF[D, x]*If[x <= Quantile[D, p], 1, 0],
CDF[D, x],
PDF[D, x]},
{x, 0, 12},
PlotRange -> All, Filling -> {1 -> Axis}, ImageSize -> Large, AxesLabel -> {x, ""}],
{p, .6, "Percentil"}, 0, 1, .001, Appearance -> "Labeled"}]

• Usually a piece of software incorporates features because it's convenient to use them. I think I don't fully understand your question, but in Mathematica the situation of having an internal construct to perform better than your own code is quite common. Think for example about pre-compiled constructs – Dr. belisarius Aug 18 '13 at 16:43

As @belisarius comments, the answer is usually, No, you can't do things faster by-passing built-in functions. (Sometimes the answer is yes.) Here, with the particular distribution of the OP, one can do as well by getting the explicit formula and compiling it.

d = ProbabilityDistribution[Piecewise[{{x/36, 0 <= x <= 6}, {(12 - x)/36, 6 < x <= 12}}],
{x, 0, 12}];

fn = Compile[{{x, _Real}, {p, _Real}},
Evaluate[PDF[d, x] If[x <= Simplify[Quantile[d, p], 0 <= p <= 1], 1, 0]]];
pdf = Compile[x, Evaluate@PDF[d, x]];
cdf = Compile[x, Evaluate@CDF[d, x]];

Manipulate[
Plot[{fn[x, p], cdf[x], pdf[x]},
{x, 0, 12}, PlotRange -> All, Filling -> {1 -> Axis},
ImageSize -> Large, AxesLabel -> {x, ""}],
{{p, .6, "Percentil"}, 0, 1, .001, Appearance -> "Labeled"}]


My fear is that this is a simplified example for which this happens to work. In this case, I'm not sure why using the optimized, built-in functions would be avoided.

Aside. Note considerable speed-up can be obtained by evaluating the arguments to Plot:

Manipulate[
Plot[
Evaluate @ {PDF[d, x]*If[x <= Quantile[d, p], 1, 0], CDF[d, x], PDF[d, x]},
{x, 0, 12}, PlotRange -> All,
Filling -> {1 -> Axis}, ImageSize -> Large, AxesLabel -> {x, ""}] ,
{{p, .6, "Percentil"}, 0, 1, .001, Appearance -> "Labeled"}]


The reason this helps is that in the original, the PDF, CDF, and Quantile have to be recalculated from d for each value of x that is plotted; using Evaluate substitutes the formulas for these before they are passed to Plot (because Plot is HoldAll). This saves some steps, but it is still noticeably slower than the compiled version.

This is not a solution or a full answer, but a hint where the slow down is. (too small to put as comment).

First, I do not know probability well. I struggled to get a B in my engineering probability class (I think I should have got a B+ but that is another story).

I am taking your word that TriangularDistribution[{0, 12}, 6] is exactly the same as saying probabilityDistribution[Piecewise[{{x/36, 0 <= x <= 6}, {(12 - x)/36, 6 < x <= 12}}], {x, 0, 12}]

Given that, the slow down is from mostly Quantile applied your home grown probabilityDistribution This can be seen by using triangular in the second case in place of your own d distribution. (btw, not good idea to use D or any UpperCase letter in Mathematica).

So, the problem comes down from using your own definition for a TriangularDistribution and asking why is my own definition does not work as fast as Mathematica build-in definition. Well, I think Belisarius comment already answers this part, but may be there is more to it. Here is the updated code. This still does not run as fast as using the build-in definition, but it is much faster than what you had before, since now Quantile is using the build-in definition of the distribution. If you can somehow optimize your definition, you should be able to do much better than this:

Manipulate[
Plot[{
PDF[d, x]*If[x <= Quantile[triangular, p], 1, 0],
CDF[d, x]}, {x, 0, 12}, PlotRange -> All, Filling -> {1 -> Axis},
ImageSize -> Large, AxesLabel -> {x, ""}],
{{p, .6, "Percentil"}, 0, 1, .001, Appearance -> "Labeled"},
ContinuousAction -> False,
SynchronousInitialization -> False, (*need that so not to time out *)
Initialization :>
(
d = ProbabilityDistribution[
Piecewise[{{x/36, 0 <= x <= 6}, {(12 - x)/36, 6 < x <= 12}}], {x,
0, 12}];
triangular = TriangularDistribution[{0, 12}, 6]
)
]