1

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]
dabd
  • 839
  • 4
  • 13

2 Answers2

5

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.

Michael E2
  • 235,386
  • 17
  • 334
  • 747
  • 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? – dabd Apr 28 '13 at 17:16
  • 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. – dabd Apr 28 '13 at 18:17
  • @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. – Michael E2 Apr 28 '13 at 19:02
2

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.

bill s
  • 68,936
  • 4
  • 101
  • 191
  • 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? – dabd Apr 28 '13 at 14:33