1
$\begingroup$

I am new to Mathematica so my question might sound a bit silly, but I hope you help me.

While learning ContourPlot, I have learned that when I use the previously defined expressions as inputs onto it, it doesn't seem to work, and only putting them in manually seems to work.

For example, defining

f1 = x^2/9 + y^2/4 == 1
f2 = x^2 - 1 == y

and then evaluating

ContourPlot[{f1, f2}, {x, -3, 3}, {y, -3, 8}] 

results in empty plot, while putting the expressions manually inside such as

ContourPlot[{x^2/9 + y^2/4 == 1, x^2 - 1 == y}, {x, -3, 3}, {y, -3, 8}]

results in what I want...

What's more is, this also seems to occur when using NSolve... Can anyone tell me what's going on?

$\endgroup$
  • 1
    $\begingroup$ I think it has something to do with the HoldAll attribute of ContourPlot... It works with ContourPlot[Evaluate[{f1, f2}], {x, -3, 3}, {y, -3, 8}]. $\endgroup$ – MelaGo Oct 15 '19 at 5:44
  • $\begingroup$ Thank you! Could you specify what you mean by that? $\endgroup$ – Danny Han Oct 15 '19 at 7:57
  • 1
    $\begingroup$ @DannyHan As @MelaGo noted, ContourPlot has attribute HoldAll. Before evaluating anything (in particular, before inserting the definitions of f1 and f2), ContourPlot will look at the first argument and decide what type of plot you want - whether you're giving it a single curve or a list and whether you are giving it a function or an equation. (continued...) $\endgroup$ – Lukas Lang Oct 15 '19 at 8:25
  • 1
    $\begingroup$ (...continued) Here, it sees {f1, f2} and decides to plot two functions. When it starts evaluating f1 and f2 for given x and y, it doesn't get a number, but True and False, so it doesn't plot anything (non-numerical results are simply ignored by all/most plotting functions). Evaluate forces evaluation to occur before ContourPlot, so ContourPlot sees a list of equations, which it can then correctly plot. $\endgroup$ – Lukas Lang Oct 15 '19 at 8:25
  • $\begingroup$ @LukasLang Great explanation! Worth posting as an answer. $\endgroup$ – Alexey Popkov Oct 15 '19 at 10:24
2
$\begingroup$

As suggested, I'm expanding my comment into an answer

The problem here is the HoldAll attribute of ContourPlot. Like Plot and similar functions the process goes something like this:

  • Look at the first argument, and decide what form it has:
    • If it's a list, the user wants to plot multiple functions
    • If it's an equation with ==, the user wants to plot the solution to that equation
  • Start the evaluation at different points (this part is done recursively on many points)
    • Set the values of the variables (second and third argument) to the correct values (similar to Block, as noted in the details section of ContourPlot)
    • Evaluate the first argument and use the result

Now we see what the problem in your case is:

ContourPlot[{f1, f2}, {x, -3, 3}, {y, -3, 8}] 

When ContourPlot decides on the type of plot you want, it decides on "plot contours for two functions", since all it sees at that point is {f1, f2}. Now, values like e.g. x=0,y=0 are assigned and f1,f2 are evaluated. The problem is that this results in e.g.

          {f1, f2}
(* --> *) {x^2/9 + y^2/4 == 1,x^2 - 1 == y}
(* --> *) {0^2/9 + 0^2/4 == 1,0^2 - 1 == 0}
(* --> *) {0 == 1,- 1 == 0}
(* --> *) {False, False}

And like most plotting functions, non-numeric results (like the False above, are simply discarded).

It is now also clear why Evaluate fixes the issue: It forces the first argument of ContourPlot to be evaluated before ContourPlot has a chance to look at it. So now the evaluation sequence goes like this:

          ContourPlot[Evaluate[{f1, f2}], {x, -3, 3}, {y, -3, 8}]
(* --> *) ContourPlot[{x^2/9 + y^2/4 == 1,x^2 - 1 == y}, {x, -3, 3}, {y, -3, 8}]

At this point ContourPlot examines the first argument and decides on "plot the solutions of two equations", which is what we want.

It should be noted that the only thing that ContourPlot needs to see are the lists (when multiple things are to be plotted) and the equations - everything else can be evaluated later. This means the following will also work:

g1 = x^2/9 + y^2/4
g2 = x^2 - 1

ContourPlot[{g1 == 1, g2 == y}, {x, -3, 3}, {y, -3, 8}]

TL;DR;

To summarise, force evaluation of the first argument of ContourPlot using Evaluate to ensure that the right type of plot is chosen:

ContourPlot[Evaluate[{f1, f2}], {x, -3, 3}, {y, -3, 8}]

enter image description here

|improve this answer|||||
$\endgroup$
  • $\begingroup$ OMG thank you so much! Now I understand :) $\endgroup$ – Danny Han Oct 15 '19 at 12:29

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.