# Plot function the uses Solve

Can someone tell me why I get an error (and how I get around it) from Solve while I try to Plot a function like:

In[119]:= z[y_] := Max[Solve[x^2 == y, {x}][[All]] /. Rule -> (#2 &)]
z[3]
Plot[Max[z[x]], {x, 0, 3}]

Out[120]= Sqrt[3]

During evaluation of In[119]:= Solve::ivar: 0.00006128571428571428 is not a valid variable. >>

During evaluation of In[119]:= Solve::ivar: 0.06128577551020408 is not a valid variable. >>

During evaluation of In[119]:= Solve::ivar: 0.12251026530612244 is not a valid variable. >>

During evaluation of In[119]:= General::stop: Further output of Solve::ivar will be suppressed during this calculation. >>


What I do: I solve an equation (x^2=y) where y is my variable. I store this in an array and take the maximum value as my function z. This works, as shown (z[3]=sqrt[3]). But I can't use this togther with the Plot function.

I can of course create a list and use ListPlot. But this isn't so useful in the real Problem that has poles and is thus not well described by an equidistant mesh or similar

• @ PeMa: avoid using the name x. This works out fine: Plot[Max[z[t]], {t, 0, 3}] – Dr. Wolfgang Hintze Oct 23 '14 at 12:44
• @ PeMa: the construct Rule -> (#2&) is also new to me. – Dr. Wolfgang Hintze Oct 23 '14 at 12:50
• @Dr.WolfgangHintze that is unusual, and it's being used instead of :>. But, it works like q[r,s] /. q -> f where q is replaced by f which in this case is a pure function, so it evaluates. Different, but effective. – rcollyer Oct 23 '14 at 12:58
• The trick is found here mathematica.stackexchange.com/questions/3175/… – PeMa Oct 23 '14 at 13:00
• @PeMa yes, Mr. Wizard is a good source of tricks. [[All]], though, is not necessary as that is what is returned by default. – rcollyer Oct 23 '14 at 13:02

The key is in the use of the variable x, which is used as a dummy variable in both the function z[y] and in the function Plot. When you rename one of them, e.g.

z[y_] := Max[Solve[x^2 == y, {x}][[All]] /. Rule -> (#2 &)]
z[3]
Plot[Max[z[xx]], {xx, 0, 3}]


The issue is that Solve is not HoldAll

In[42]:= Attributes@Solve
Out[42]= {Protected}


so that the plot variable, x, is being substituted into Solve in the variable specification. There are a couple of ways to prevent this, but the most effective in the long term is to uniquely rename x in z, as follows

z[y_] := Module[{x}, Max[Solve[x^2 == y, {x}][[All]] /. Rule -> (#2 &)]]


Module internally renames its variables so they are always unique, even between different executions. Block would work here as well.

For this particular example, though, I would use neither. I would have Solve do its job first, and then wrap it in a function, e.g.

Clear[z]
z[y_] = Max[Solve[x^2 == y, {x}] /. Rule[_,b_] :> b]


The difference is I used = (Set) not := (SetDelayed), so that the right hand side is executed prior to it being turned into a function. In general, Solve` will take a long time to execute, so this form is often superior in terms of performance.

• Nice solution, thanks! – PeMa Oct 23 '14 at 13:11