0

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
  • 309
  • 2
  • 9

2 Answers2

3

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}]

your code works as expected.

Koen
  • 198
  • 4
2

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.

rcollyer
  • 33,976
  • 7
  • 92
  • 191