1
$\begingroup$

I'd like combine Dynamic and Manipulate, cause Manipulate required for Wolfram Demonstrations Project !

I have difficulty with this. Found such an answer, but there is a rather complicated example.
Here’s a very simple example. I want the results of long series calculations to be displayed smoothly and dynamically, and start from the beginning if the manipulator changes.

Manipulate[
 x = 0;
 Do[(*Some long calculations*)
  [email protected];
  x += n,
  {5}];
 Dynamic@x
 , {n, 1, 3, 1}]

But the behaviour of this code is weird and unstable.

$\endgroup$
4
  • $\begingroup$ Take a look at this answer. $\endgroup$
    – Alan
    Aug 3, 2023 at 17:44
  • $\begingroup$ @Alan, I've fixed question. Only Manipulate as wrapper is possible! $\endgroup$
    – lesobrod
    Aug 3, 2023 at 17:48
  • 1
    $\begingroup$ it is better to either Manipulate with no explicit dynamics inside it (note that Manipulate itself is Dynamic module) or just use DynamicModule directly. Mixing and matching is recipes for bugs. Unless you enjoy debugging. $\endgroup$
    – Nasser
    Aug 4, 2023 at 5:25
  • $\begingroup$ @Nasser I've found answer by myself, but thank you for the right idea! $\endgroup$
    – lesobrod
    Aug 4, 2023 at 15:16

3 Answers 3

3
$\begingroup$

I think mixing Manipulate and Dynamic is as fine as nesting Dynamic with itself in whatever environment. Sometimes it is necessary for good performance. When I run into problems is when I expect Dynamic to do something complicated.

The basic structure that Manipulate[<body>, <vars & stuff>] creates is something like the following:

DynamicModule[{<vars & other Manipulate vars>},
 Dynamic[
  <Manipulate stuff>
  ]
 ]

The <Manipulate stuff> creates the paneled grid of controls & display pane that you see. Of course that is very complicated, but somewhere amid the mess something like Dynamic[Refresh[<body>, <options>], <options>] appears. The refactoring in creating this structure that Manipulate[] does sometimes creates problems. It is easier to deal with bugs in DynamicModule[], where pretty much the things that happen are the documented effects of visible choices made by the programmer. Well, mostly documented.

Here's a refactoring of the OP's answer that takes advantage of the DynamicModule[] created by Manipulate. (I'm not sure why the OP's DynamicModule[] has the unused variable m. Or rather, I know why it doesn't work without it, but unused variables that have an effect seem very mysterious. I omit the unnecessary variables below, and create the needed Dynamic[] dependencies another way.)

Manipulate[
 (* create dependencies of body on {step, max} as in original *)
 step; max;
 (* initialize u *)
 u = 0; (* does not depend on u *)
 (* the following code text updated independently *)
 Dynamic[Refresh[
   If[u > max, u, u = u + step]],
  TrackedSymbols :> {step, max}, UpdateInterval -> .5],
 {step, 1, 5, 1}, {max, 10, 20, 1},
 (* None is syntactic sugar for ControlType -> None *)
 {{u, 0}, None}]

The code topography looks like this:

enter image description here

The whole body (the outside CompoundExpression) depends only on the symbols that are evaluated in the white region. The symbols in the green housed inside the Dynamic are considered independent.

So for instance, u is not evaluated in the white code region; its value is written but not read. So the whole body does not depend on u. However, u is evaluated (or can potentially be evaluated depending on If[]) in the green code region. So the green region depends on u (and max and step) and can be dynamically evaluated separately if u changes.

Note that when the whole body is evaluated, the whole, both white and green regions are evaluated. Another way to look at it is that only complete subtrees can be reevaluated (and then only if wrapped in Dynamic[]).

It is perhaps worth pointing out that it is probably bad to have two independent Dynamic subtrees that update variables on which the other depends. You cannot control the order of evaluation of the independent dynamic updates (as far as I know). And you may get into an infinite loop, where one update triggers the other and vice versa. Note also that controls are in effect independent Dynamic subtrees (that usually update only themselves and only in response to a user event, so that's fine).

To explain the OP's original code, first note that x += n is effectively the same as x = x + n: in particular, it depends on x. So when the Do[] loop is finished, the whole body will be reevaluated. When you click on the control for n, we have two Dynamic[] processes going on. When is the value of n changed? Does it preempt the Do[] loop and happen while it is executing? I don't really know.

Bugginess

Since interaction with the computer's OS is important in Dynamic, the following was tested on V13.3.0 on a Mac ARM. Perhaps it is different on other systems.

I really don't know what happens with Do[] when n is changed and suspect a bug. @Nasser commented that mixing Manipulate and Dynamic is buggy and, when needed, one should use DynamicModule instead. I'm not sure I buy that, so let's take that as disputed. Making buggy code with Dynamic is itself not too hard, and I would be slow to blame Manipulate as well as to bet on DynamicModule fixing it.

Case in point: Removing Dynamic from the OP's original Manipulate[] leaves the bug intact. It appears not to be the source of the bug. It only reveals the bug.

If you're patient and don't look away, this shows x occasionally exceeding 5*n, which should not happen (the first update seems to often be wrong, and then x is overwritten with the correct 5 n):

Manipulate[
 x = 0;
 Do[(*Some long calculations*)
  [email protected];
  x += n, {5}];
 x,
 {n, 1, 3, 1}]

If you're impatient, just a few clicks to change n should record that x exceeds 5*n for all n fairly often:

xMax = <||>;
Manipulate[
 x = 0;
 Do[(*Some long calculations*)
  [email protected];
  x += n, {5}];
 If[x > 5*n,
  xMax[n] = {x, Lookup[xMax, n, Nothing]}];
 x,
 {n, 1, 3, 1}]

This seems like a bug to report to WRI. Maybe someone has an explanation why this sort of randomness should be expected.

The above behavior lends some support to @Nasser's point that Manipulate with (or without) Dynamic is buggy. How does DynamicModule fare? I could not reproduce the bug, but I would assert it's behavior is worse. Here is a straightforward translation:

DynamicModule[{n = 1},
 (*Dynamic@*)Column[{
   Manipulator[Dynamic@n, {1, 3, 1}],
   Dynamic[Refresh[
     x = 0;
     Do[(*Some long calculations*)
      [email protected];
      x += n, {i, 5}];
     Dynamic@x (* also tried without Dynamic@ *)
     ]]}]
 ]

I tried it with and without the commented out Dynamic and the Refresh. Manipulate wraps the body with Refresh it seems, so I thought it would be fairer to put it in. However, the code performs equally bad in all variations. The front end becomes nearly unusable. I took 16 seconds between the time I clicked on the output cell and the time the cell was selected. It took 12 seconds between the time I pressed "delete" and the time the cell was deleted. Further the Dynamic@x was never updated during the execution of the Do[] loop. The output always displayed 5 n.

The behavior is bad for no reason I can see. This also seems a bug to report to WRI, even if only to get an explanation why the behavior is to be expected; and if expected, what is the bad coding practice that leads to the bad behavior. (Of course, maybe some site user might know. I could ask another question, if it needs to be separate.)

$\endgroup$
0
$\begingroup$

Without knowing the nature of your calculations, nor what you expect in terms of "smoothly and dynamically", all I can do is make guesses and make generic guidance. You might start with something like this:

Manipulate[
  {n, f[x]},
  {n, 1, 3, 1},
  {x, 0, 5 n, n}]

The {n, f[x]} is just for demonstration purposes. The f would be your complicated calculation (presumably dependent on x). Once the Manipulate is displayed, you can start set the x controller to run (by pressing "Play"). Once you have this working, you can tweak the appearance and any autorun sequencing you want to do.

Another approach would be to use ListAnimate or something similar inside of the Manipulate. Then, instead of managing the state of x, you'd just do your calculation on the appropriate range of values and animate the results.

$\endgroup$
0
$\begingroup$
Manipulate[
 DynamicModule[{u = 0, h = step, m = max},
  Dynamic[Refresh[
    If[u > max, u = u, u = u + h]
    ], TrackedSymbols :> {}, UpdateInterval -> .5]
  ]
 , {step, 1, 5, 1}, {max, 10, 20, 1}]
$\endgroup$

Your Answer

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

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