Mathematica 9 is now available
Services & Resources / Wolfram Forums / MathGroup Archive
-----

MathGroup Archive 2008

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: A Dynamic mess

  • To: mathgroup at smc.vnet.net
  • Subject: [mg92993] Re: A Dynamic mess
  • From: chandler.seth at gmail.com
  • Date: Wed, 22 Oct 2008 05:38:50 -0400 (EDT)
  • References: <gdjq6j$mtj$1@smc.vnet.net>

On Oct 21, 12:43 am, John Fultz <jfu... at wolfram.com> wrote:
> On Mon, 20 Oct 2008 07:32:31 -0400 (EDT), chandler.s... at gmail.com wrote:
> > There has just got to be an easier way to do the following. The
> > example is somewhat silly, but if I could understand how to do this
> > competently, I would learn a lot.
>
> > Suppose I want to compute the sum of an integer  (z) and a value
> > chosen from some uniform distribution on the interval 0 to a. I want
> > to do this interactively and I do NOT want the draw from the random
> > distribution to change when I change z, just when I change the
> > parameter a. So, we create the number z as follows:
>
> > z=6;SetterBar[Dynamic[z],{6,7,8}]
>
> > If I do the following, it does not work as expected because, I
> > suppose, Dynamic[z] is a FrontEnd object in its heart of hearts (a
> > DynamicBox) and thus does not add to 2 the way an integer would.
>
> Correct.  The thing to keep in mind is that Dynamic[z] evaluates to Dyn=
amic[z].  
> If you do...
>
> Dynamic[z]//InputForm
>
> you'll see that.  In StandardForm, it displays as something else, in pr=
ecisely
> the same way that a/b looks like "a/b" in InputForm, but displays as some=
thing
> else (i.e. a FractionBox) in StandardForm.  Any further evaluations are=
 a side
> effect of that display, and not a principal effect of evaluating Dynamic[=
].
>
>
>
> > Dynamic[z]+2
>
> > So, this can be fixed with Dynamic[z+2]
>
> > OK, now instead of adding 2, let's add some random value
>
> > a=0.5;Slider[Dynamic[a]];
>
> > Dynamic[z+RandomReal[{0,Setting@Dynamic[a]}]] (* setting is added
> > because if one just uses Dynamic[a] one is referencing a front end
> > object rather than an actual number*)
>
> Are you hoping that the internal Dynamic will somehow freeze the RandomRe=
al[]
> unless 'a' has been explicitly changed?  This won't happen for two reas=
ons. One
> is that an outer Dynamic reevaluates its contents entirely, including inn=
er
> Dynamics, whenever it's triggered (as it will be by the change in 'z'). =
 But the
> more important reason is that the inner Dynamic doesn't actually have any
> Dynamic functionality.  Observe...
>
> In[12]:= Setting[Dynamic[a]] // InputForm
>
> Out[12]//InputForm= 0.5
>
> Recall that I said that Dynamic[] evaluates to itself.  But Setting of =
Dynamic[]
> evaluates not to a dynamic result, but to the contents of the Dynamic.
>
> So your statement is effectively the same as...
>
> Dynamic[z + RandomReal[{0, a}]]
>
> Keep reading for the solution...
>
>
>
> > This evaluates, but it does not have the desired behavior. Now, when I
> > change z I also get a new draw from the random distribution. I thought
> > of trying to blocking the redraw by wrapping Dynamic around the
> > RandomReal, like this.
>
> > Dynamic[z+Dynamic@RandomReal[{0,Setting@Dynamic[a]}]]
>
> > But that doesn't work at all. It still redraws when I change z and the
> > addition no longer works in the desired way since the Dynamic
> > expression is not "really" a number but just a box.
>
> > I can solve the latter problem by wrapping a Setting in front of the
> > Dynamic
>
> > Dynamic[z + Setting@Dynamic[RandomReal[{0, Setting@Dynamic[a]}]]]
>
> > Now it adds properly but it still refreshes the random draw every time
> > I change z.
>
> > This doesn't work either and the expression is getting awfully
> > complicated
>
> > Dynamic[z +
> > Refresh[Setting@Dynamic[RandomReal[{0, Setting@Dynamic[a]}]],
> > TrackedSymbols -> {a}]]
>
> > And this doesn't work either
>
> > Dynamic[Setting@Dynamic[z] +
> > Setting@Dynamic[RandomReal[{0, Setting@Dynamic[a]}]]]
>
> > Can someone help!
>
> Yes.  Many evaluation ordering issues with Dynamic can be solved using =
With[],
> including this one.  Here's my code that does what you want...
>
> Dynamic[With[{draw = RandomReal[{0, a}]}, Dynamic[z + draw]]]
>
> Some important points here.  Note that both Dynamics actually display. =
 The
> outer Dynamic will obviously display the result of With[], and the result=
 of
> With[] is another Dynamic[].  If I had hidden the inner Dynamic behind =
a
> semicolon or Setting, this would not have worked.
>
> So, in the front end, this is represented as two nested DynamicBox object=
s. The
> outer Dynamic will trigger anytime 'a' is changed, and will reevaluate it=
s
> contents entirely, including the inner Dynamic. The inner Dynamic will on=
ly
> change if 'z' has changed, and its reevaluation will never cascade into a
> reevaluation of the outer Dynamic.
>
> In summary, Setting[] won't help you with the kind of problems you're hav=
ing,
> but you'll find With[] very useful.  In my Mathematica programs, I almo=
st never
> used With[] until Dynamic[] came along, at which point I found it an inva=
luable
> tool for controlling precisely how things will evaluate.
>
> Sincerely,
>
> John Fultz
> jfu... at wolfram.com
> User Interface Group
> Wolfram Research, Inc.

Thank you John for an extremely helpful answer. I thought I would
amplify your response by showing two pieces of successful code that
implement your idea.

using DynamicModule

DynamicModule[{a = 0.3, b = 0.04, years = 10, insureds = 5,
  dist = WeibullDistribution, func = f},
 Column[{Manipulator[Dynamic[a], {0.01, 3}],
   Manipulator[Dynamic[b], {0.01, 3}],
   SetterBar[Dynamic[years], Table[10^i, {i, 0, 2}]],
Slider[Dynamic[insureds],{1,20,1}],
   SetterBar[
    Dynamic[dist], {WeibullDistribution, GammaDistribution,
     LogNormalDistribution}], SetterBar[Dynamic[func], {f, g}],
   Dynamic[With[{draw =
       RandomReal[
        dist @@ {a, b}, {insureds,
         years}](*change the draw if any of the symbols in this \
section change *)}, Dynamic[func[draw]]]]}]]

using Manipulate

Manipulate[
 Dynamic[With[{draw =
     RandomReal[
      dist @@ {a, b}, {insureds,
       years}](*change the draw if any of the symbols in this section
\
change *)}, Dynamic[func[draw]]]],
 {{a, 0.3}, 0.01, 3},
 {{b, 0.04}, 0.01, 3},
 {{years, 10}, Table[10^i, {i, 0, 2}], ControlType -> SetterBar},
 {{insureds, 5}, 1, 20, 1, ControlType -> SetterBar},
 {{dist, WeibullDistribution}, {WeibullDistribution,
   GammaDistribution, LogNormalDistribution},
  ControlType -> SetterBar}, {{func, f}, {f, g}}]

When you change dist, a, b, insureds or years a new draw occurs
When you change func, no new draw occurs

This is precisely the behavior I want and it seems to be a pretty
clean way of going about it.

Suggestions: (1) Add examples something like this to the Advanced
Dynamic and/or Advanced Manipulate tutorials. (2) Clarify
documentation on Setting and DynamicSetting.


  • Prev by Date: Re: Is there a simple way to transform 1.1 to 11/10?
  • Next by Date: Re: initialize cells
  • Previous by thread: Re: A Dynamic mess
  • Next by thread: Re: Pi Formula