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 &)]
          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

  • 1
    $\begingroup$ @ PeMa: avoid using the name x. This works out fine: Plot[Max[z[t]], {t, 0, 3}] $\endgroup$ – Dr. Wolfgang Hintze Oct 23 '14 at 12:44
  • $\begingroup$ @ PeMa: the construct Rule -> (#2&) is also new to me. $\endgroup$ – Dr. Wolfgang Hintze Oct 23 '14 at 12:50
  • 1
    $\begingroup$ @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. $\endgroup$ – rcollyer Oct 23 '14 at 12:58
  • $\begingroup$ The trick is found here mathematica.stackexchange.com/questions/3175/… $\endgroup$ – PeMa Oct 23 '14 at 13:00
  • 1
    $\begingroup$ @PeMa yes, Mr. Wizard is a good source of tricks. [[All]], though, is not necessary as that is what is returned by default. $\endgroup$ – 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 &)]
Plot[Max[z[xx]], {xx, 0, 3}]

your code works as expected.


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.

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.

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.