Re: For Loop and Array related

*To*: mathgroup at smc.vnet.net*Subject*: [mg58103] Re: For Loop and Array related*From*: Maxim <ab_def at prontomail.com>*Date*: Sat, 18 Jun 2005 06:08:03 -0400 (EDT)*References*: <d8oucl$t6q$1@smc.vnet.net> <d8u63h$84q$1@smc.vnet.net>*Sender*: owner-wri-mathgroup at wolfram.com

On Fri, 17 Jun 2005 09:45:21 +0000 (UTC), <danl at wolfram.com> wrote: > > mchangun at gmail.com wrote: >> Hi All, >> >> I have an array with 100 elements, all set to zero initially. Then I >> want to randomly choose one element and increase its value by one, and >> repeat this 16000 times. Here is my code: >> >> Lattice = Table[0, {n, 100}]; >> For[i = 1, i = 16000, i++, Lattice[[Random[Integer, {1, 100}]]]++] >> >> So now if I add all the elements in the list Lattice together, I should >> get 16000 (I use Total[Lattice] to get the sum of the list). But this >> doesn't happen, and strangely, each time I run this, the sum of the >> list is different! What am I doing wrong? >> >> Also I'm aware that a lot of Mathematica newbies try and write code >> like it were C++ and I think i've fallen into this trap as well. So is >> there a different (more Mathematica) way which I can implement the >> above? >> >> Thanks in advanced. > > As several respondants noted, the key step of what you are doing is > equivalent to > > lattice[[Random[Integer,{1,100}]]] = > lattice[[Random[Integer,{1,100}]]]+1 > > This selects different random positions in each invocation, causing the > trouble noted. I wanted to mention that this has come up in this forum > in past: > > http://forums.wolfram.com/mathgroup/archive/2001/Dec/msg00294.html > > Here is a method that is quite fast. If you have len lists and they are > to sum to total, instead of walking and incrementing total times, just > pick len-1 random values from 0 to total, sort them, augment with 0 and > total at the ends, and take successive differences. The code below will > do this. > > randomLattice1[len_,total_] := ListConvolve[{1,-1}, > Join[{0},Sort[Table[Random[Integer,{0,total}], {len-1}]],{total}]] > > In[74]:= Timing[rl = randomLattice[10^5,10^7];] > Out[74]= {0.219967 Second, Null} > > In[75]:= Total[rl1] > Out[75]= 10000000 > > In[76]:= Take[rl,44] > Out[76]= {91, 9, 65, 17, 214, 3, 54, 178, 24, 80, 36, 174, 162, 89, > 350, 52, > 86, 90, 14, 64, 8, 226, 109, 64, 59, 58, 138, 47, 61, 128, 15, 57, > 339, > 61, 45, 61, 93, 19, 240, 15, 27, 41, 19, 147} > > > Daniel Lichtblau > Wolfram Research > This depends on what we want to achieve. randomLattice1 doesn't give the same distribution as incrementing a random bin n times. Suppose that the number of bins len=3 and the number of iterations total=1. randomLattice1 has a higher chance of incrementing the bin number 2: In[2]:= Total@ Table[randomLattice1[3, 1], {10^5}] Out[2]= {24949, 50076, 24975} The probability of the bin number one being incremented is the probability that the first element in the list Sort@ {Random[Integer], Random[Integer]} is 1. This equals 1/4. Similarly, randomLattice1[2, 2] has a higher chance of putting the two 1s into the same bin. Here's a handy procedure for applying chi-square test to the data. The first argument should be the list of the frequences, that is, the number of times each outcome occured. The second argument is the list of the probabilities: In[3]:= chi[Lcnt_, Lp_] := Module[ {n, s, chi}, {n, s} = {Total@ Lcnt, Length@ Lcnt}; chi = Total@ (Lcnt^2/(n*Lp)) - n; 1 - GammaRegularized[(s - 1)/2, 0, chi/2] ] In[4]:= chi[%2, {1/4, 1/2, 1/4}] // N Out[4]= 0.88490056 The result is the probability of the deviation being greater than observed. Thus we see no disagreement with the expected probabilities {1/4, 1/2, 1/4}. Maxim Rytin m.r at inbox.ru