# How can I selectively trigger computations in Manipulate?

I have a Manipulate that uses RandomVariate and Random that I would like to have redraw and recompute random values selectively, depending on what Manipulate parameters have been changed.

For example, I would like to be able to control redraws and recomputations so that

• new data and honestMeans are only computed if n has changed;
• new punishMeans are computed only when n or punish have changed;
• a redraw is triggered when zoom changes, but without triggering an update to data, honestMeans or punishMeans;
• a redraw triggered when any of data, honestMeans or punishMeans or zoom changes (without triggering a recomputation of data, honestMeans or punishMeans);
• everything updates if an explicit update is requested (somehow)

as indicated in the comments below:

scale = 5;
dist = HypergeometricDistribution[scale, Round[0.7*2*scale], 2*scale];
For[i = 2, i <= n, i++,
If[Random[] < punish,
If[votes[[i - 1]] > data[[i]], vote = 0, vote = scale],
vote = data[[i]]
];
AppendTo[votes, Mean[Append[data[[1 ;; i - 1]], vote]]];
AppendTo[votes, Mean[Append[data[[1 ;; i - 1]], data[[i]]]]];
];

Manipulate[
data = RandomVariate[dist, n];(* Should only change when n changes *)
punishMeans = genVotes[punish, n]; (* Should change when punish or n change *)
honestMeans = genVotes[0, n]; (* Should only change when n changes *)
GraphicsColumn[{ (* Should redraw when any of the above change, or if zoom changes, without triggering recompilation of data, punishMeans or honestMeans *)
Show[
ListPlot[punishMeans,
Joined -> False, PlotStyle -> Gray, PlotMarkers -> Automatic,
PlotRange -> {{0, n}, {(1 - zoom)*#, (1 + zoom)*#} &[Mean[data]]},
Frame -> True, Axes -> None,
Epilog -> {Blue, Line[{{0, Mean[data]}, {n, Mean[data]}}]}],
ListPlot[honestMeans,
Joined -> True, PlotStyle -> Black, PlotMarkers -> None]
],
Show[
Histogram[data, scale, PlotRange -> {{0, scale + 1}, All},
Frame -> True,
FrameTicks -> {{Automatic,
Automatic}, {{# + .5, #, 0} & /@ Range[0, scale], None}},
Axes -> None],
DiscretePlot[n*PDF[dist, x], {x, 0, scale + 1}, Joined -> True,
PlotMarkers -> None, Filling -> None]
]
}],
{{n, 100}, 10, 5000},
{{punish, 0.5}, 0, 1},
Delimiter,
{{zoom, 0.2}, .1, .5},
TrackedSymbols :> {n, punish, zoom}]


Is there a way to do this kind of selective update of elements of a Manipulate?

-
Please don't post your full-blown code/problem here but just a minimal example for other users to work with. – Dr. belisarius Feb 23 '14 at 21:45
@belisarius: That's my MWE. (All interdependencies matter, as near as I can tell.) Don't hesitate to simplify the example if you spot an opportunity to do so. – raxacoricofallapatorius Feb 23 '14 at 21:48
fyi, your code above does not run, it has errors in it, on V 9.01 , here is screen shot !Mathematica graphics may be if you fix these first it will help. – Nasser Feb 23 '14 at 23:14
@Nasser: Thanks. Fixed (I think). – raxacoricofallapatorius Feb 23 '14 at 23:29

This uses the second argument of dynamics, which acts like an event call back. In there, you do the specific action needed when that dynamic changes. This localizes the logic with its own control variable. Makes it easier to manage. If you like more information about this method, see this question

But you really need to fix/improve the way the function genVotes works. It is very inefficient and slow (that is why I made ContinuousAction -> False below for now), and it also uses global data which is not a good way to implement it. I'll leave this for you to fix.

scale = 5;
dist = HypergeometricDistribution[scale, Round[0.7*2*scale], 2*scale];

For[i = 2, i <= n, i++,
If[Random[] < punish,
vote = 0,
vote = scale
],
vote = data[[i]]
];
AppendTo[votes, Mean[Append[data[[1 ;; i - 1]], vote]]];
AppendTo[votes, Mean[Append[data[[1 ;; i - 1]], data[[i]]]]]
];
];

Manipulate[tick;

GraphicsColumn[{

Show[ListPlot[punishMeans, Joined -> False,
PlotStyle -> Gray, PlotMarkers -> Automatic,
PlotRange -> {{0, n}, {(1 - zoom)*#, (1 + zoom)*#} &[Mean[data]]},
Frame -> True, Axes -> None,
Epilog -> {Blue, Line[{{0, Mean[data]}, {n, Mean[data]}}]}],
ListPlot[honestMeans, Joined -> True, PlotStyle -> Black, PlotMarkers -> None]
],

Histogram[data, scale, PlotRange -> {{0, scale + 1}, All}, Frame -> True,
FrameTicks -> {{Automatic, Automatic},
{{# + .5, #, 0} & /@ Range[0, scale], None}}, Axes -> None],
DiscretePlot[n*PDF[dist, x], {x, 0, scale + 1}, Joined -> True,
PlotMarkers -> None, Filling -> None]
}],

Grid[{
{"n",
Manipulator[Dynamic[
n, {n = #; data = RandomVariate[dist, n]; punishMeans = genVotes[punish, n];
tick = Not[tick]} &], {10, 200, 1}, ImageSize -> Tiny], Dynamic[n]
},
{"punish",
Manipulator[Dynamic[punish, {punish = #; punishMeans = genVotes[punish, n];
tick = Not[tick]} &], {0, 1, 0.1}, ImageSize -> Tiny], Dynamic[punish]
},
{"zoom",
Manipulator[Dynamic[zoom, {zoom = #; tick = Not[tick]} &], {.1, .5, 0.1},
ImageSize -> Tiny, ContinuousAction -> True], Dynamic[zoom]
}
}
],

{{zoom, .2}, None},
{{n, 100}, None},
{{punish, .5}, None},
{{tick, False}, None},
SynchronousUpdating -> False,
SynchronousInitialization -> False,
ContinuousAction -> False,
TrackedSymbols :> {tick}
]


-
Yeah, sorry: genVotes and the use of data are pretty terrible. I'll fix that. – raxacoricofallapatorius Feb 24 '14 at 1:05