7
$\begingroup$

I am new to Mathematica and was experimenting with a simply problem of plotting a tangent to a curve and being able to move the point at which the tangent is drawn using Manipulate. When I run the following, the cell flickers a lot and it also seems to consume a lot of CPU? Is there a way to avoid this?

Manipulate[
  Module[{f, x, y, dx, dy},
    dx = dy = 1;
    f[x_] := x^2;
    tangent[x_, y_] := {{x - dx, y - f'[x] dy}, {x + dx, y + f'[x] dy}};
    g = Graphics[Line @ tangent[x0, f[x0]], PlotRange -> {{-5, 5}, {-5, 5}}];
    p = Plot[f[x], {x, -5, 5}];
    Show[p, g]],
  {{x0, 2}, -4, 4}]
$\endgroup$
7
  • 2
    $\begingroup$ You might want to look at this $\endgroup$
    – m_goldberg
    Commented Feb 17, 2013 at 17:09
  • $\begingroup$ Thanks but doesn't explain why the above doesn't work ? In my example it should just evaluate the function f[x] & tangent[] when i move the slider but clearly its doing something different. $\endgroup$ Commented Feb 17, 2013 at 17:15
  • 1
    $\begingroup$ The link shows one correct approach to doing what you want and answers your question "how to avoid this?" If your question is really: how do I debug this? -- well, this isn't a debugging service. I will say this -- defining a Module inside a Manipulate is not a good idea, nor is evaluating the derivative of a simple function over and over. $\endgroup$
    – m_goldberg
    Commented Feb 17, 2013 at 17:23
  • $\begingroup$ Thanks. But why is evaluating a function inside a manipulate a bad idea ? $\endgroup$ Commented Feb 17, 2013 at 17:29
  • $\begingroup$ Nothing wrong with evaluating a function in a Manipulate, but taking the derivative of x^2 many times when it could done once is not good. $\endgroup$
    – m_goldberg
    Commented Feb 17, 2013 at 17:33

4 Answers 4

7
$\begingroup$

I hope you'll forgive my changing one thing that's been bugging me about the code: If $y=f(x)$, then $dy = f'(x)\; dx$, not $f'(x)\; dy$. (The original code works because dy is set equal to dx.)

tangent[x_, dx_, f_] := {{x - dx, f[x] - f'[x] dx}, {x + dx, f[x] + f'[x] dx}};
f[x_] := x^2;
Manipulate[With[{dx = 1},
  p = Plot[f[x], {x, -5, 5}, Epilog -> Dynamic@Line@tangent[x0, dx, f]]],
 {{x0, 2}, -4, 4}, SaveDefinitions -> True]

I also wrapped the tangent line in Dynamic. The tangent line is the only thing that changes, and adding Dynamic makes it the only thing recalculated when x0 changes. The plot of f[x] is not recalculated, which lowers CPU usage even more. That savings is unimportant in this example, but the principle illustrated is useful.

$\endgroup$
1
  • $\begingroup$ Thanks. Wasn't aware of Dynamic so useful. Thanks for spotting the typo in dy. $\endgroup$ Commented Feb 17, 2013 at 19:41
5
$\begingroup$

Well, while your (David McHarg's) current solution is much better, sometimes one can not avoid some heavy recalculation inside Manipulate. For such cases TrackedSymbols is indispensable. This tells manipulate which symbols to monitor for change. So this works as expected:

Manipulate[DynamicModule[{f, x, y, dx, dy}, dx = dy = 1;
  f[x_] := x^2;
  tangent[x_, y_] := {{x - dx, y - f'[x] dy}, {x + dx, y + f'[x] dy}};
  g = Graphics[Line@tangent[x0, f[x0]], 
    PlotRange -> {{-5, 5}, {-5, 5}}];
  p = Plot[f[x], {x, -5, 5}];
  Show[p, g]], {{x0, 2}, -4, 4}, TrackedSymbols :> {x0}]
$\endgroup$
1
  • 1
    $\begingroup$ Thanks. Exactly what i was looking for. Always good to understand different approaches. $\endgroup$ Commented Feb 17, 2013 at 17:52
5
$\begingroup$

TrackedSymbols is not needed if one just localizes all variables in Modules (which is what one should do in the first place). Many like to use global variables all over the place and this causes such problems.

Manipulate[

 Module[{x, y, dx, dy, g, p},

  dx = dy = 1;
  g = Graphics[Line@tangent[x, x0, dx, dy, f],PlotRange -> {{-5, 5}, {-5, 5}}];
  p = Plot[f[x], {x, -5, 5}];
  Show[p, g]
 ],

 {{x0, 2}, -4, 4},

 Initialization :>
  {
   tangent[var_Symbol, x0_, dx_, dy_, f_]:= Module[{der = D[f, var] /. var -> x0},
     {{x0 - dx, f[x0] - der dy}, {x0 + dx, f[x0] + der dy}}
   ];

   f[x_] := x^2;
   }
 ]
$\endgroup$
4
$\begingroup$

Solved the problem by changing things around a little. This resolves the flickering and CPU usage.

Module[{f,x,y,dx,dy},
dx=dy=1;
f[x_]:=x^2;
tangent[x_,y_]:={{x-dx,y-f'[x] dy},{x+dx,y+f'[x] dy}};
p=Plot[f[x],{x,-5,5}];
tangent[x_]:=Graphics[Line@tangent[x,f[x]],PlotRange->{{-5,5},{-5,5}}];
Manipulate[Show[p,tangent[x0]],{{x0,2},-4,4}]
]

Regards David.

$\endgroup$
0

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.