MathGroup Archive 2000

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Re: need little help - no longer!

  • To: mathgroup at smc.vnet.net
  • Subject: [mg23589] Re: [mg23548] Re: [mg23530] need little help - no longer!
  • From: Andrzej Kozlowski <andrzej at tuins.ac.jp>
  • Date: Sun, 21 May 2000 18:12:56 -0400 (EDT)
  • Sender: owner-wri-mathgroup at wolfram.com

on 00.5.20 4:10 PM, Wagner Truppel at wtruppel at uci.edu wrote:

> "Thank you!" to both Johannes Ludsteck and Kenneth Levasseur, who
> supplied me with solutions to my query.
> 
> As Johannes pointed out, the Statistics`MultiDiscreteStatistics`
> package has facilities for drawing random numbers from a multinomial
> probability distribution. However, I personally prefer Ken's solution:
> 
> RandomIndex[m_] :=
> (m /. {{a__, b___} :> Length[{a}] /; Plus[a] >= #}) &[Random[]]
> 
> Once again, thank you both.
> Wagner
> 


I agree that Ken's solution is very elegant and surprisingly a lot faster
than the one derived from the MultiDiscreteDistributions package, but if you
mainly care about efficiency than it is still pretty inefficient. The reason
is that each time the function RandomIndex is run, first a random number is
chosen (using uniform distribution) and then repeated pattern matchings have
to be made before an index is chosen (this time with multinomial
distribution). This can be considerably speeded up if one first makes a list
of indices containing each with required frequency and then just chooses one
of them using Random[] (with uniform distribution). Here is one way to do
this.

As always we have:

In[1]:=
m = {0.2, 0.4, 0.1, 0.3}

Out[1]=
{0.2, 0.4, 0.1, 0.3}

This makes a list of indices containing each index with required frequency:

indices[m_] := 
  Module[{l = Map[Rationalize, m]},
    Flatten[Table @@@
        Transpose[{Range[Length[m]],
            Partition[LCM @@ Map[Denominator, l]*l, 1]}]]]

In this case the list of indices with frequencies becomes:

In[6]:=
ind = indices[m]

Out[6]=
{1, 1, 2, 2, 2, 2, 3, 4, 4, 4}

Given such a list we can now define  RandomIndex as

RandomIndex := ind[[Random[Integer, {1, Length[ind]}]]]

Now 

In[7]:=
N[Count[Table[RandomIndex, {1000}], #] & /@ Range[1, 4]/1000]

Out[7]=
{0.201, 0.406, 0.103, 0.309}

In[8]:=
Timing[Table[RandomIndex, {1000}]] // First
Out[8]=
0.05 Second

(On a 233 mghz Mac PowerBook).


This is much faster than all the solutions proposed so far except Ted
Ersek's one which, however, in the form he sent it, could not be applied to
a case with a large number of possible outcomes. (It can of course be
modified to work for arbitrary number of outcomes and then, I think, it may
well be the fastest one, but I have not tried doing so and testing it).

-- 
Andrzej Kozlowski
Toyama International University
JAPAN

http://platon.c.u-tokyo.ac.jp/andrzej/
http://sigma.tuins.ac.jp/







  • Prev by Date: Re: sending notebooks as attatchments with microsoft OutlookExpress...
  • Next by Date: Re: sending notebooks as attatchments with microsoft OutlookExpress...
  • Previous by thread: Re: need little help - no longer!
  • Next by thread: Re: need little help - no longer!