Re: easy question about random numbers
- To: mathgroup at smc.vnet.net
- Subject: [mg53516] Re: easy question about random numbers
- From: "Ray Koopman" <koopman at sfu.ca>
- Date: Sat, 15 Jan 2005 01:44:18 -0500 (EST)
- References: <crqb7f$cak$1@smc.vnet.net><200501110631.BAA00684@smc.vnet.net> <cs5bag$3t5$1@smc.vnet.net>
- Sender: owner-wri-mathgroup at wolfram.com
DrBob wrote:
> Wow, PieceWise and Compile really do the job; that's quite a bit
> faster than the alias method, even when ranfun is used to get only
> one sample at a time. For a Histogram of 100000 samples: [...]
The alias method, too, runs faster as compiled vector-generating code.
(I apologize for the absence of indentation in what follows, but I'm
posting via Google, which now removes all indentation.)
In[1]:=
<<Statistics`DiscreteDistributions`
<<Graphics`Graphics`
In[3]:=
MakeDiscreteRandomFunction[probs_, vals_] := With[{fun = Block[{x},
Function @@ {x, Piecewise@Transpose[{vals, x <= # & /@
(Rest@FoldList[Plus, 0, probs])}]}]},
Compile[{{n, _Integer}}, fun /@ Table[Random[], {n}]]]
MakeDiscreteRandomFunction[probs_] :=
MakeDiscreteRandomFunction[probs,Range[Length[probs]]]
In[5]:=
k = 7;
dist = BinomialDistribution[k, 3/10];
Timing[ranfun = MakeDiscreteRandomFunction@Table[PDF[dist,i],{i,0,k}];]
Timing@Histogram@Flatten@Array[ranfun@1&,1*^5] (* one sample at a time
*)
Timing@Histogram@ranfun@1*^5 (* all the samples at once *)
Out[7]= {0. Second, Null}
Out[8]= {1.19 Second, -Graphics-}
Out[9]= {0.29 Second, -Graphics-}
In[10]:=
setal[p_]:=Block[{n=Length[p],a,b,c,i,j,tol},
a=Range[n];b=n*p-1;c=Table[1,{n}];tol=2*n*$MachineEpsilon;
While[{i,j}=Ordering[b][[{1,-1}]];b[[j]]>b[[i]]+tol,
a[[i]]=j;c[[i]]=1+b[[i]];b[[j]]+=b[[i]];b[[i]]=0]; {n,a,N[c]}]
Clear@alias
alias[___] := (-1+If[Random[]>c[[#]],a[[#]],#]&)[Random[Integer,{1,n}]]
Clear@alii
alii[samples_] := -1 + Table[(If[Random[] >
c[[#]],a[[#]],#]&)[Random[Integer,{1,n}]],{samples}]
Clear@calii
calii = Compile[{{n,_Integer},{a,_Integer,1},{c,_Real,1},
{samples,_Integer}}, -1 + Table[(If[Random[] >
c[[#]],a[[#]],#]&)[Random[Integer,{1,n}]],{samples}]]
In[17]:=
Timing[{n, a, c} = setal@Table[PDF[dist, i], {i, 0, k}];]
Timing@Histogram@Array[alias, {1*^5}] (* one at a time *)
Timing@Histogram@alii@1*^5 (* all at once *)
Timing@Histogram@calii[n,a,c,1*^5] (* all at once, compiled *)
Out[17]= {0. Second, Null}
Out[18]= {1.74 Second, -Graphics-}
Out[19]= {0.31 Second, -Graphics-}
Out[20]= {0.27 Second, -Graphics-}
- Follow-Ups:
- Re: Re: easy question about random numbers
- From: DrBob <drbob@bigfoot.com>
- Re: Re: easy question about random numbers
- References:
- Re: easy question about random numbers
- From: Mark Fisher <mark@markfisher.net>
- Re: easy question about random numbers