For a school project we were asked to do a accept-reject method, which can calculate the mean for functions that are not very easy to solve analytically. This I did in Mathematica 12.1 and it worked, however quite slow. If i code the same principle in python it takes 6 times less time, making the ego of my python using friend way too big. Is there a way to make the following "Acceptance-Rejection" code run significantly faster?
(*Initiating a random seed for reproducibilty together with some parameters*)
ceiling = 0.3582061533158414; w=20.; h = 1.05*ceiling;
SeedRandom[4242424242];
(*the function ar will generate 2 random points x and y in the perimeter of a triangle enclosing
f[x] = 0.453*Exp[-1.036*x]*Sinh[Sqrt[2.29*x]]. if y<f[x], the point falls in the graph and x is
returned. if not, the function will run itself again until a x,y pair is found that is
enclosed by f[x]*)
ar := (
y = h*(1.-Sqrt[RandomReal[]]);
x = RandomReal[{0.,w*(h-y)/h}];
If[y<=0.453*Exp[-1.036*x]*Sinh[Sqrt[2.29*x]],Return[x]];
ar
)
(*generate n points using the accept reject method and add this value ei to the sumAR. also add ei^2 to the sumAR2 for calculating the variance.*)
n = 10^6; sumAR = 0; sumAR2 = 0; x = 0; y = 0;
Timing[
Do[
ei = ar; sumAR += ei; sumAR2 += ei^2
,n]
]
mean = sumAR/n
variance = sumAR2/n - mean^2
deviation = Sqrt[variance]
PS: I first had f[x] defined and then would run y<=f[x] since it is easier to read, but not having to call f[x] saves around 2 seconds in total and i only use f[x] once so yea.