12

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.

Noon Silk
  • 523
  • 3
  • 11
  • 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. – Leonid Shifrin Sep 26 '12 at 13:42
  • @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. – Mr.Wizard Feb 22 '17 at 13:50
  • @Mr.Wizard Well, this is now water under the bridge, anyway. But thanks :) – Leonid Shifrin Feb 22 '17 at 13:56

3 Answers3

10

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}]
]
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • 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. – Noon Silk Jul 23 '12 at 12:43
  • 1
    @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. – Mr.Wizard Jul 23 '12 at 12:52
  • 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? – Noon Silk Jul 23 '12 at 13:11
  • 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. – Noon Silk Jul 23 '12 at 13:13
  • 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. – Noon Silk Jul 23 '12 at 13:14
  • @NoonSilk I don't have time to fully address the question of program structuring, and I would like to get some more details from you in Chat before I do anyway (not now). Know that f[x_] := Evaluate @ g[x] is equivalent to f[x_] = g[x] -- usually when using this form one should consider protecting against global values as described here but in your application that may not be a problem. – Mr.Wizard Jul 23 '12 at 13:34
4

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.

Verbeia
  • 34,233
  • 9
  • 109
  • 224
  • 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). – Noon Silk Jul 23 '12 at 12:51
  • 1
    @NoonSilk actually, it is: add option Evaluated -> True to Plot. – Mr.Wizard Jul 23 '12 at 12:55
  • 1
    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). – Noon Silk Jul 23 '12 at 12:59
1

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]
Rojo
  • 42,601
  • 7
  • 96
  • 188
Sjoerd C. de Vries
  • 65,815
  • 14
  • 188
  • 323
  • That doesn't work on my system. -1 Sorry. :-/ – Mr.Wizard Jul 23 '12 at 12:57
  • @mr.wizard perhaps an explicit assignment is necessary. Could you test this? – Sjoerd C. de Vries Jul 23 '12 at 13:00
  • What do you mean? – Mr.Wizard Jul 23 '12 at 13:00
  • @mr.wizard something like a={x,y} or perhaps a+={x,y}. – Sjoerd C. de Vries Jul 23 '12 at 13:05
  • 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? – Mr.Wizard Jul 23 '12 at 13:09
  • @Mr.Wizard I'm convinced some variant of this should work, but I'm deleting for now and come back to this after my vacation. This is getting a bit awkward. – Sjoerd C. de Vries Jul 23 '12 at 13:13
  • @Mr.Wizard, the scoping is With-like, but the dynamic tracking is Block-like. So explicit evaluation of the variables can make a difference – Rojo Jul 23 '12 at 13:59
  • @Mr.Wizard It does work for me though... – sebhofer Jul 23 '12 at 14:08
  • @Rojo with LocalizeVariables -> False you are contaminating the Global namespace, which given (my understanding of) the OP's existing code is a particularly bad idea. (Me today I guess.) – Mr.Wizard Jul 23 '12 at 14:16
  • @Mr.Wizard I just thougth he meant he wanted that from his first comment to your answer: "I understand the risk about global assignments; arguably that's actually the feature I want - the variables are sensibly named". Is my English betraying me and he means that he actually doesn't want globals? – Rojo Jul 23 '12 at 14:19
  • @Rojo I think if he is actively making definitions like foo = Exp[2 x+y] the Global symbols need to remain clear. I don't think it's a matter of English comprehension, just a slightly vague programming style. – Mr.Wizard Jul 23 '12 at 14:22
  • Point taken. Can't think of how to fix that without ending up with a totally different approach – Rojo Jul 23 '12 at 14:32