4
$\begingroup$

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];
genVotes[punish_, n_] := Module[{},
   votes = {data[[1]]};
   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]]]]];
    ]; Return[votes];
   ];

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?

$\endgroup$
4
  • 2
    $\begingroup$ Please don't post your full-blown code/problem here but just a minimal example for other users to work with. $\endgroup$ Feb 23, 2014 at 21:45
  • $\begingroup$ @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. $\endgroup$
    – orome
    Feb 23, 2014 at 21:48
  • $\begingroup$ 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. $\endgroup$
    – Nasser
    Feb 23, 2014 at 23:14
  • $\begingroup$ @Nasser: Thanks. Fixed (I think). $\endgroup$
    – orome
    Feb 23, 2014 at 23:29

1 Answer 1

3
$\begingroup$

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];

genVotes[punish_, n_] := Module[{},
   votes = {data[[1]]};
   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]]]]]
    ];
   votes
   ];

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]; 
        honestMeans = genVotes[0, 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}
 ]

enter image description here

$\endgroup$
1
  • $\begingroup$ Yeah, sorry: genVotes and the use of data are pretty terrible. I'll fix that. $\endgroup$
    – orome
    Feb 24, 2014 at 1:05

Your Answer

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

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