Re: Fixed Typo in Code---> Re: updating a simulation within Manipulate.
- To: mathgroup at smc.vnet.net
- Subject: [mg130101] Re: Fixed Typo in Code---> Re: updating a simulation within Manipulate.
- From: "Nasser M. Abbasi" <nma at 12000.org>
- Date: Sat, 9 Mar 2013 05:26:43 -0500 (EST)
- Delivered-to: l-mathgroup@mail-archive0.wolfram.com
- Delivered-to: l-mathgroup@wolfram.com
- Delivered-to: mathgroup-newout@smc.vnet.net
- Delivered-to: mathgroup-newsend@smc.vnet.net
- References: <9C229A0A-D12F-4D3E-9B5F-7FA8B918CFE6@mit.edu> <khbn00$cd5$1@smc.vnet.net>
- Reply-to: nma at 12000.org
On 3/7/2013 9:47 PM, W Craig Carter wrote: > On previous message, there is a typo in the example code, please use this instead: > > randomStep[bias_, stepList_] := > Module[{angle = RandomVariate[NormalDistribution[bias, 1]]}, > Join[stepList, {Last[stepList] + {Cos[angle], Sin[angle]}}]] > > walkerGraphic[stepList_, range_] := > Graphics[GraphicsComplex[stepList, Disk /@ Range[Length[stepList]]], > PlotRange -> range {{-1, 1}, {-1, 1}}] > > DynamicModule[{walkerPath = {{0, 0}}}, > Manipulate[ > If[keepWalking,(*kludge warning---testing for If[ True...] seems inefficient*) > walkerPath = randomStep[bias, walkerPath]]; > If[reset, reset = False; keepWalking = False; > walkerPath = {{0, 0}}]; > walkerGraphic[walkerPath, > range], {{keepWalking, False}, {True, False}}, {{reset, > False}, {True, False}}, Delimiter, {{range, 20}, 0, 100}, > {{bias, 0}, -Pi, Pi, > AngularGauge[##, ImageSize -> 160, > ScaleOrigin -> {{-4 Pi, 4 Pi}, 1}] &}]] > > > > W Craig Carter > Professor of Materials Science, MIT The best way that I found after to do all these things in Mathematica is to use a finite state machine type setup to control the overall state of simulation. There will be a "running" state, "pause" state, "reset" state and so on. Then the whole simulation will be controlled by one ticklish dynamic, called `tick` which acts like the heart beat of the simulation. Only one TrackedSymbol in the whole simulation. Next, we will use the second argument of Dynamic to act as the callback. Each time a control is changed, in the callback we adjust the state of simulation as needed, then tickle the heart beat so that the main display is refreshed. When the main display does not need to refresh, then the heart beat is not updated in the callback. Other house keeping logic can be there if needed. So, this is the whole idea. This works now as traditional simulation loops work and as traditional GUI callbacks work, but with the advntage of having Dynamics as well. No need now to worry about where to do what, and have the logic spread in many different locations in the code. The logic of the simulation now is more organized and it is possible to make the simulation as complex as needed without losing track of things. In the callback (i.e. second argument of Dynamic), only work relating to this control is done. In the main display area, is where the main logic of the state machine is, which updates the display, and if needed tickle the heart beat again, so that the loop continue again and again. No trigers are needed, no clocks, etc... Just one tickle when needed, and the use of the second argument of Dynamics and adding TrackedSymbols on the tick. I wrote a note on this method sometime ago here http://12000.org/my_notes/event_driven_GUI_with_Manipulate/event_driven_manipulate.htm Using this method of doing simulation, here is your simulation now. I put the notebook here also in case the paste does not work: http://12000.org/tmp/030813/ ---------------------------------------------- DynamicModule[{walkerPath = {{0, 0}}, state = "running", tick = 0, result, del = $MachineEpsilon, range = 40, bias = 0, btnControls, rangeControl, biasControl, stepSizeControl, stepSize = 0.21}, stepSizeControl = Row[{Text@"step size", Spacer[5], Manipulator[Dynamic[stepSize, {stepSize = #} &], {0.01, 1, 0.01}, ImageSize -> Tiny, ContinuousAction -> True], Spacer[5], Dynamic[AccountingForm[stepSize, {3, 2}, NumberSigns -> {"", ""}, NumberPadding -> {"0", "0"}]]}]; btnControls = Grid[{{ Button[Text[Style["run", 12]], If[state == "running", walkerPath = {{0, 0}}]; state = "running"; tick += del, ImageSize -> {50, 35}], Button[Text[Style["pause", 12]], state = "paused"; tick += del, ImageSize -> {50, 35}], Button[Text[Style["step", 12]], state = "step"; tick += del, ImageSize -> {50, 35}], Button[Text[Style["reset", 12]], state = "reset"; walkerPath = {{0, 0}}; result = walkerGraphic[walkerPath, range]; tick = 0, ImageSize -> {50, 35}] }}, Spacings -> {0.2, .1} ]; rangeControl = Row[{Text@"range", Spacer[5], Manipulator[Dynamic[range, {range = #} &], {0, 100, 1}, ImageSize -> Tiny, ContinuousAction -> True], Spacer[5], Dynamic[range]}]; biasControl = AngularGauge[Dynamic[bias, {bias = #; tick += del} &], {-Pi, Pi}, ImageSize -> {260, 100}, ScaleOrigin -> {{-4 Pi, 4 Pi}, 1}]; Labeled[Grid[{ {Grid[{{btnControls}, {stepSizeControl}, {rangeControl}, {biasControl} }], Dynamic[ tick; Which[state == "running" || state == "step", walkerPath = randomStep[bias, walkerPath, stepSize]; result = walkerGraphic[walkerPath, range]; If[state == "running", tick += del] ]; result, TrackedSymbols :> {tick} ] } }, Frame -> All] , Text[Style["version 3/8/2013", 10]]] , Initialization :> { randomStep[bias_, stepList_, stepSize_] := Module[{angle = RandomVariate[NormalDistribution[bias, 1]]}, Join[stepList, {Last[stepList] + stepSize {Cos[angle], Sin[angle]}}] ]; walkerGraphic[stepList_, range_] := Graphics[{Gray, PointSize[.04], Point@Most@stepList, Blue, Point@Last@stepList}, PlotRange -> range {{-1, 1}, {-1, 1}}, ImageSize -> 200]; } ] -------------------------------------------------- --Nasser