12
$\begingroup$

It took me a while today to figure out that Manipulate (used with Plot) requires that the variable I'm manipulating be an actual parameter of the thing that I'm manipulating.

That is, if I have something like:

foo = Exp[2 x+y]
Manipulate[Plot[foo, {x, 0, 10}], {y, 0, 10}]

It will not work as desired, but if I have:

ffoo[x_, y_] := Exp[2 x+y]
Manipulate[Plot[ffoo[x, y], {x, 0, 10}], {y, 0, 10}]

It will.

I can't help but wonder; what is the general correct approach here? To me it feels slightly "wrong" that I should need to declare all the free variables for my statements as arguments. But maybe this is just something I should get over. In my case, it means I need to change, say, an arbitrary amount of places where I might call these to get various things (like eigenvectors with free parameters) and do a bunch of work converting them into function calls? Just because I want to use them in plots?

My actual approach was to write little "plot functions" for the particular bits I wanted to plot, and I then I did a little probably-inappropriate trick of just sneaking them into functions:

foofunc[a_, b_, c_] := Evalulate[foo]

(Knowing that foo contains free variables named as "a", "b", etc...).

It seems, though, that there must be a better way of just asking Manipulate to consider implicit parameters (or whatever their formal name is; I tried a bit of searching and wasn't able to find anything about this; though I imagine it's fairly common).

Thanks for any advice.

$\endgroup$
3
  • $\begingroup$ I wonder why my comment with this link was deleted, I find it very relevant here and not linked to by other answers. Anyway, making another one. $\endgroup$ Commented Sep 26, 2012 at 13:42
  • $\begingroup$ @LeonidShifrin Pardon the reply to a very old comment but according to the post history no comments under this question have ever been deleted. I think there must have been a software glitch. $\endgroup$
    – Mr.Wizard
    Commented Feb 22, 2017 at 13:50
  • $\begingroup$ @Mr.Wizard Well, this is now water under the bridge, anyway. But thanks :) $\endgroup$ Commented Feb 22, 2017 at 13:56

3 Answers 3

10
$\begingroup$

In my opinion once you start passing objects as functions like this it makes sense to use the named argument form: ffoo[x_, y_] := Exp[2 x + y] Otherwise you risk conflicts with global assignments to x and y.

Nevertheless there are ways to do what you want more directly I believe, e.g.

foo = Exp[2 x + y];

With[{foo = foo},
  Manipulate[Plot[foo, {x, 0, 10}], {y, 0, 10}]
]
$\endgroup$
6
  • $\begingroup$ Okay, thanks. (I understand the risk about global assignments; arguably that's actually the feature I want - the variables are sensibly named). My problem, really, was getting results back from other functions with these free variables in them (i.e. eigenvectors/values). And also, it seems slightly "semantically" confusing, because my function really only has one actual parameter, but the system itself has these free parameters. I still feel like I'm missing something. $\endgroup$
    – Noon Silk
    Commented Jul 23, 2012 at 12:43
  • 1
    $\begingroup$ @NoonSilk I wonder if I'm missing something in your application. Would you consider adding another example to your question, perhaps with the eigenvectors usage that you mention? At a stretch, perhaps this method may be tangentially of interest to you. $\endgroup$
    – Mr.Wizard
    Commented Jul 23, 2012 at 12:52
  • $\begingroup$ I'm new to Mathematica, so I'm likely wrong. I'm suggesting that, at some point I have a matrix, which has free variables in it (say x and y). So if I solve for Eigenvalues, I clearly get these free params in the result. So at some point I'll need to write something exactly like f[H_, x_] := ... Evaluate @ Eigensystem[H] ... to get the result appropriately back from Eigensystem for use further down the line? Then, I will need to "functionalise" all future things, say a density matrix which is formally a fn only of t, to be fn's of the somewhat arbitrary free variables from earlier? $\endgroup$
    – Noon Silk
    Commented Jul 23, 2012 at 13:11
  • $\begingroup$ It seems weird to do so, to me, because I might at some point say "Okay, this variable is no longer free, it is now 10". I'd need to change a random number of function params to fully reflect this, or just now pass a constant around. I guess I'm differentiating "system" variables (by allowing them to be global) from function variables. And this Manipulate question has forced me to reconsider how I do that, because it doesn't play nicely with it, with my minimal knowledge. I actually think converting them to functions is probably correct, but only far latter; essentially as I'm doing. $\endgroup$
    – Noon Silk
    Commented Jul 23, 2012 at 13:13
  • $\begingroup$ But the Evalulate in there to play the trick of using the same variable name as the function parameter seems like it will get me into trouble at some point. $\endgroup$
    – Noon Silk
    Commented Jul 23, 2012 at 13:14
4
$\begingroup$

An alternative method to get the effect you want is to use a replacement rule:

Manipulate[Plot[foo /. {y -> b}, {x, 0, 10}], {b, 0, 10}]

The issue is that if you write:

Manipulate[Plot[foo, {x, 0, 10}], {y, 0, 10}]

then you have the y that is an expression within the expression foo, and the y that is a variable local to the Manipulate[] expression. They aren't the same thing.

Using the replacement rule ensures that you are inserting a variable that the Manipulate is actually manipulating, into the expression foo.

$\endgroup$
3
  • $\begingroup$ You're right; this seems to work in this trivial case. This is actually the very first thing I tried, and I actually had to stop using it because of the confusion it caused when I tried to plot a list of graphs {foo1, foo2} and replace them all at once: {foo1, foo2} /. {y -> b}. (It's no longer possible to colour them uniquely in this case). $\endgroup$
    – Noon Silk
    Commented Jul 23, 2012 at 12:51
  • 1
    $\begingroup$ @NoonSilk actually, it is: add option Evaluated -> True to Plot. $\endgroup$
    – Mr.Wizard
    Commented Jul 23, 2012 at 12:55
  • 1
    $\begingroup$ Ah! Thanks Mr. Wizard; you are right! This might be the simplest approach then (though I think the essential idea about reconsidering how I approach the general structure of my programs is a good one). $\endgroup$
    – Noon Silk
    Commented Jul 23, 2012 at 12:59
1
$\begingroup$

Manipulate needs to see the parameters. This is mentioned in the 'Potential issues' part of its doc page. However, I think (but currently can't test this) that including a dummy statement using the parameters may work:

foo = Exp[2 x + y]
Manipulate[
 {x, y};Plot[foo, {x, 0, 10}], {y, 0, 10}, 
 LocalizeVariables -> False]
$\endgroup$
12
  • $\begingroup$ That doesn't work on my system. -1 Sorry. :-/ $\endgroup$
    – Mr.Wizard
    Commented Jul 23, 2012 at 12:57
  • $\begingroup$ @mr.wizard perhaps an explicit assignment is necessary. Could you test this? $\endgroup$ Commented Jul 23, 2012 at 13:00
  • $\begingroup$ What do you mean? $\endgroup$
    – Mr.Wizard
    Commented Jul 23, 2012 at 13:00
  • $\begingroup$ @mr.wizard something like a={x,y} or perhaps a+={x,y}. $\endgroup$ Commented Jul 23, 2012 at 13:05
  • $\begingroup$ I tried both without result, and frankly I cannot see why that would do anything. Isn't the scoping in Manipulate akin to With rather than Block? $\endgroup$
    – Mr.Wizard
    Commented Jul 23, 2012 at 13:09

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.