1
$\begingroup$

I made a notebook with the following code, but for some reason when I evaluate it it keeps replaying repeatedly. What is causing this?

Thanks.

RandomWalk[n_, roi_, bi_, 
  rake_] := (pwin = bi (1 + roi)/(2 (bi - rake)); 
  NestWhileList[# + 
     RandomChoice[{pwin, 1 - pwin} -> {1 - 2 rake/bi, -1}] &, 
   0, True &, 0, n])

Manipulate[(data = RandomWalk[nrTournaments, roi, bi, rake]; 
  dollarWon = biWon bi; biWon = Last[data]; 
  ListPlot[data, Joined -> True]), {{nrTournaments, 10000, 
   "tournaments"}, 0, 100000, 100}, {{roi, 0.015, "ROI"}, 0, 20, 
  0.001}, {{bi, 60, "BI ($)"}, 0, 10000, 
      1}, {{rake, 1.26, "rake ($)"}, 0, 500, 0.01}, 
     Panel[Grid[{{Dynamic[
          Row[{"BI won: ", ToString[biWon], " (", 
            Style["$" <> ToString[dollarWon], 
         If[dollarWon >= 0, Darker[Green], Red]], ")"}]]}}, 
   Alignment -> Left]], SaveDefinitions -> True]
$\endgroup$
1
  • $\begingroup$ This related question gives several approaches to this problem. $\endgroup$
    – Michael E2
    Commented Apr 28, 2013 at 16:42

2 Answers 2

5
$\begingroup$

The issue is that by default, whenever a symbol in the Manipulate change value, the Manipulate expression is reevaluated. This means that when data, dollarWon etc. are changed in a given evaluation, their changes trigger another reevaluation and you get an infinite loop.

The way around this is to control the tracked symbols with the TrackedSymbols option.

Manipulate[data = RandomWalk[nrTournaments, roi, bi, rake];
 dollarWon = biWon bi; biWon = Last[data];
 Dynamic@ListPlot[data, Joined -> True],

 {{nrTournaments, 10000, "tournaments"}, 0, 100000, 100},
 {{roi, 0.015, "ROI"}, 0, 20, 0.001},
 {{bi, 60, "BI ($)"}, 0, 10000, 1},
     {{rake, 1.26, "rake ($)"}, 0, 500, 0.01},

 Panel[Grid[{{Dynamic[
      Row[{"BI won: ", ToString[biWon], " (", 
        Style["$" <> ToString[dollarWon], 
         If[dollarWon >= 0, Darker[Green], Red]], ")"}]]}}, 
   Alignment -> Left]],
 SaveDefinitions -> True, TrackedSymbols :> True]

Setting the option to True means only the control variables are tracked. It is equivalent in this case to the setting TrackedSymbols :> {nrTournaments, roi, bi, rake}.

With only the TrackedSymbols option, the Manipulate is initially evaluated twice, and once there after for every change of inputs. To fix this, put the ListPlot inside a Dynamic.


To run more trials on the same input, one way is to track a dummy variable. (I haven't discovered a better way. Update does not seem applicable. I can't figure out how to force updating without an actual change.)

trial = 0;
Manipulate[trial;
 data = RandomWalk[nrTournaments, roi, bi, rake];
 dollarWon = biWon bi; biWon = Last[data];
 Dynamic@ListPlot[data, Joined -> True],
 {{nrTournaments, 10000, "tournaments"}, 0, 100000, 100},
 {{roi, 0.015, "ROI"}, 0, 20, 0.001},
 {{bi, 60, "BI ($)"}, 0, 10000, 1},
     {{rake, 1.26, "rake ($)"}, 0, 500, 0.01},
     Panel[Grid[{{Dynamic[
          Row[{"BI won: ", ToString[biWon], " (", 
            Style["$" <> ToString[dollarWon], 
         If[dollarWon >= 0, Darker[Green], Red]], ")"}]]}}, 
   Alignment -> Left]],
 Button["Run again", trial++],
 SaveDefinitions -> True, 
 TrackedSymbols :> {nrTournaments, roi, bi, rake, trial}]

You can also make trial a Manipulate variable with a slider. Add the following to the variable declarations:

{trial, 1, 10^6, 1}

If trial at the beginning of the Manipulate expression is replaced by SeedRandom[trial]. then trials with the same inputs will be reproducible.

$\endgroup$
3
  • $\begingroup$ Thanks for the help. I would like to add a button to recalculate without changing the inputs. I tried to add a button like this: Button["Run again", (nrTournaments = nrTournaments + 1; nrTournaments = nrTournaments - 1)] but it doesn't work very well. What is the correct way to achieve this? $\endgroup$
    – dabd
    Commented Apr 28, 2013 at 17:16
  • $\begingroup$ Thank you very much this was very helpful. I was looking at ControlType -> None as a way to add a dummy control but it didn't work. $\endgroup$
    – dabd
    Commented Apr 28, 2013 at 18:17
  • $\begingroup$ @dabd You could try something like {{trial, 0}, Button["Run again", trial++] &} as the variable declaration. ControlType -> None adds the variable without a control; you would still need a way to change its value to trigger an update. The variable will be localized in the DynamicModule that the Manipulate creates. $\endgroup$
    – Michael E2
    Commented Apr 28, 2013 at 19:02
2
$\begingroup$

The problem is you told it to simulate 10000 times at initialization. Change this to something more reasonable (like 10) and it will only do 10.

$\endgroup$
1
  • $\begingroup$ My intention is for it to generate a list with nrTournaments elements and then to plot the result. It looks like it is generating nrTournaments lists and plotting each one instead. How can I change it to do what I want? $\endgroup$
    – dabd
    Commented Apr 28, 2013 at 14:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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