Message Boards Message Boards

0
|
4643 Views
|
2 Replies
|
1 Total Likes
View groups...
Share
Share this post:
GROUPS:

RandomVariate puzzle

If I evaluate the following code, I get what I expect - roughly half 1's and a quarter 0's and 2's.

n = 2; p = 0.5; 
item := RandomVariate[BinomialDistribution[n, p]];
Table[item, {1000}] // Tally

However, if I then evaluate the following bit of code, the 0's 1's and 2's are evenly distributed. I can't figure out why. Anyone see my error?

k = 0; on = False;M = 1000;
b = Probability[s == Floor[n p], 
   s \[Distributed] BinomialDistribution[n, p]];
f = Association @@ (Map[# -> 0 &, Range[0, n]]); {{{Button[
    "Start/Stop", on = Not[on]]}, {Button["Reset", 
    f = Association @@ (Map[# -> 0 &, Range[0, n]]); k = 0]}}, 
 Dynamic[If[on && k < M, f[item] += 1; k += 1; 
   BarChart[f, ChartLabels -> Range[0, n], 
    PlotRange -> {-0.1 M, 1.2 M  b}], 
   BarChart[f, ChartLabels -> Range[0, n], 
    PlotRange -> {-0.1 M, 1.2 M  b}]]]}
Attachments:
POSTED BY: Ken Levasseur
2 Replies

It took me a little bit to figure this out. The behavior of "+=" is unintuitive here. I normally wouldn't come across this because I don't program this way.

However, I could tell from the beginning that statefulness was the underlying cause of this (As it is the underlying cause of nearly all problems in life).

Let's look at a really simplified version of that reproduces the problem:

flist = {0, 0, 0};

Do[
 flist[[1 + RandomVariate[BinomialDistribution[2, 0.5]]]] +=1,
 {10000}]

Note that I had to add one to the index since arrays are indexed from 1 to 3 instead of 0 to 2. Why does this cause the problem? Let's use Trace to look at the heart of the Do loop with a flist set to {0,0,0}:

 flist[[1 + RandomVariate[BinomialDistribution[2, 0.5]]]] +=1//Trace

{flist[[1+RandomVariate[BinomialDistribution[2,0.5]]]]++,{{flist,{0,0,0}},{{RandomVariate[BinomialDistribution[2,0.5]],    
{BinomialDistribution[2,0.5][RandomType],RandomInteger},1},1+1,2},{0,0,0}[[2]],0},
{flist[[1+RandomVariate[BinomialDistribution[2,0.5]]]]=1,1},0}

What does this mean? What has happened? RandomVariate is called twice. Not once. First, RandomVariate is called to get the value from flist. That value is incremented by 1. Then, RandomVariate is called again. This time to give a position of where to assign the new value.

The end result is that values are largely swapped just swapped with each other. If you wanted to program this the way you have, you would use With to hold onto the value:

flist = {0, 0, 0};
Do[
 With[{rndval = 1 + RandomVariate[BinomialDistribution[2, 0.5]]}, 
  flist[[rndval]] += 1],
 {10000}]

A Shorter Explanation

x += 1 is defined as being the same as x = x + 1. So:

flist[[1 + RandomVariate[BinomialDistribution[2, 0.5]]]] +=1

is really just syntatic sugar for:

flist[[1 + RandomVariate[BinomialDistribution[2, 0.5]]]] = flist[[1 + RandomVariate[BinomialDistribution[2, 0.5]]]] + 1

This operation takes a random value from the list, adds one to it, and then puts that value randomly back into the list somewhere.

POSTED BY: Sean Clarke

Thanks Sean. The expansion of x +=1 explains it, so this works: replace: f[item]+=1 with i=item;f[i]+=1 :

I had been using an association instead of a list to keep track of frequencies, so there is no need to add one for the offset.

POSTED BY: Ken Levasseur
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract