Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I am trying to make a visualization of random process: coin flip. What I want to visualize is the result of i-th try: 1 or 0 value (the dot) and the mean (line) at i-th step.

My code is as follows:

m = {}; c = {}; k = {}; 
Animate[
 AppendTo[c, RandomInteger[]];
 AppendTo[m, Mean[c]];
 AppendTo[k, i];
 Show[
  ListPlot[Transpose[{k, c}]], 
  ListPlot[Transpose[{k, m}], Joined -> True, 
          PlotRange -> {{1, 100}, {0, 1}}, AxesOrigin -> {1, 0}]
  ]
 , {i, 1, 100, 1}, AnimationRepetitions -> 1,AnimationRunning -> False
]

What I can't figure out is: Why at the very beginnig I get such a plot: I get such a plot:

The line is not a mean value as should be expected.

The second thing: Why there are two points at the moment, despite the fact that I have AnimationRunning->False?

And the third: why k list is filled with ones only? Shouldn't it contain 1 to 100 values?

share|improve this question
1  
One could either try to answer your questions or try to explain why the way the code is written is a bad idea. Which one do you want? I would choose the last one :P –  Rojo Jan 15 '13 at 15:31
    
Of course I would like to see how it should be written :] And with explanation it would be great! –  Misery Jan 15 '13 at 15:33
    
I've done several bad copy-pastes and edits to my answer, sorry if it caused confusion –  Rojo Jan 15 '13 at 17:36
add comment

2 Answers

up vote 3 down vote accepted

What you write inside Animate should follow the same guidelines as what you would put inside a Dynamic, because in the end it transforms to a dynamic box. The same happens for Manipulate.

When you are creating some dynamic output, you should ask yourself "if after running this, it was run again, would the output change?". If it would change, then you are in trouble because Mathematica will evaluate it again and again endlessly.

x=0;Dynamic[++x]

Your case with AppendTo is similar. You are not only not getting the result you want but are getting continuous updates, wasting CPU. And these updates have nothing to do with i being changed from 1 to 100, they are due to your own manual updates on m and k.

Even when, as @MrWizard suggested, you can fix your code by adding TrackedSymbols to prevent the endless recursion, I believe as a general rule it's a workaround you should try not to appeal to, unless other things fail. That is because Mathematica tries not to perform useless dynamic updates, but in general it doesn't guarantee it won't. I often come into dynamic code that does a couple of extra useless updates that I wouldn't expect. If your code's proper functioning depends on those unexpected updates not happening, you can end up with the occasional surprise.

Furthermore, dynamic updates may not happen when the control isn't visible on the screen, but the Animator's i variable will keep on moving forward, missing some udpates. Try minimizing the window in your question or MrWizard's answer while running the animation to see what happens. Also, if one dynamic update ends up taking too long you will also end up missing the next one.

How I'd do it

What do you want to see?

a plot with the coin flip results up to time i and a line with the partial means? Do you want new values in each animation repetition? You want the animation to go to infinity or just to a predefined value? Let's assume you want it to infinity.

So,

whatYouWantToSee[results_List] := 
  Show[ListPlot[results, PlotStyle -> PointSize[Large]], 
   ListLinePlot[cumulativeMeans@results], AxesOrigin -> {1, 0}];

While I was writing this, I got lazy and called cumulativeMeans instead of coding it: let it be a problem for future Rojo. But the future has come

cumulativeMeans[results_List] := Accumulate@results/Range@Length@results // N

Now, how do we generate the result list based on the time? We need to generate a new coin result for every time, but only the first time the function is called for that particular time. That can be achieved through memoization. You can search the forum for more insight, there's a lot

ClearAll[coinResult];
SetAttributes[coinResult, Listable];
coinResult[i_] := coinResult[i] = RandomInteger[];

Finally

Animate[whatYouWantToSee@coinResult@Range@i, {i, 1, Infinity, 1},  AnimationRate -> 1]

See that the output of whatYouWantToSee@coinResult@Range@i won't change whether we run it 1 or 100 times. That's the main difference between the solutions

EDIT

Say you just want to see one repetition of 100 coin tosses. Now you can do without all that memoization and do something simpler. Just generate the list of results

coinResultList = RandomInteger[{0, 1}, 100];

and then

Animate[whatYouWantToSee@coinResultList[[;; i]], {i, 1, 100, 1}, 
 AnimationRate -> 1]

Note that this would be more or less equivalent to using ListAnimate

ListAnimate[Table[whatYouWantToSee@coinResultList[[;; i]], {i, 100}], 
 AnimationRate -> 1]

The moral here is that until i changes, whatYouWantToSee@coinResultList[[;; i]] will always return the same result. Notice that this would have NOT been the case if you had done

Animate[whatYouWantToSee@RandomInteger[{0, 1}, 100][[;; i]], {i, 1, 
  100, 1}, AnimationRate -> 1]
share|improve this answer
    
As my Mathematica programming skills are very low, maybe using ListAnimate would be alternative? –  Misery Jan 16 '13 at 8:40
    
One more thing: how to prepare this document for CDF player? Because at the moment it doesn't display anything except list values. –  Misery Jan 16 '13 at 9:27
    
@Misery see if the last edit helps you further –  Rojo Jan 16 '13 at 15:30
    
@Misery for CDF player, add the option SaveDefinitions->True to Animate (or use ListAnimate). That option takes care to automatically load all the functions the animation needs, like cumulativeMeans, whatYouWantToSee –  Rojo Jan 16 '13 at 15:33
add comment

For the moment ignoring the style of the coding, I believe all you need is TrackedSymbols -> {i}. This is because otherwise every change to c, m, or k causes a refresh that changes the assignments to these symbols, which again causes a refresh, etc., ad infinitum.

m = {}; c = {}; k = {};

Animate[
 AppendTo[c, RandomInteger[]];
 AppendTo[m, Mean[c]];
 AppendTo[k, i];
 Show[ListPlot[Transpose[{k, c}]], 
  ListPlot[Transpose[{k, m}], Joined -> True, PlotRange -> {{1, 100}, {0, 1}}, 
   AxesOrigin -> {1, 0}]],
 {i, 1, 100, 1},
 AnimationRunning -> False,
 TrackedSymbols -> {i}
]

Mathematica graphics

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.