Ask Your Question
2

plot issue with a self-defined piecewise function

asked 2012-01-18 16:10:48 +0200

calc314 gravatar image

The following code produces an error:

def f(x):
   if x>3:
       return(x^2)
   if x<=3:
       return(3*x)

plot(f(x),(x,0,5))

BUT, the code below works.

def f(x):
   if x>3:
       return(x^2)
   if x<=3:
       return(3*x)

plot(lambda x: f(x),(x,0,5))

So, my questions are: (1) why do you need the lambda function? and (2) when do you have to do this?

edit retag flag offensive close merge delete

4 Answers

Sort by ยป oldest newest most voted
6

answered 2012-01-18 16:22:35 +0200

Jason Grout gravatar image

The problem in your first example is that when you do f(x), it is actually calling f and returning a value. However, you want to plot the function, not the return value from one call. So you should do this:

def f(x):
   if x>3:
       return(x^2)
   if x<=3:
       return(3*x)

plot(f,(x,0,5))

Notice that now, I haven't called the function. Instead, I'm just passing the function into plot, and plot will call the function with different values.

Your lambda function trick works because it is passing a function into plot. plot then calls the lambda function, which in turn calls the f function. But I think it's easier to what I did above.

edit flag offensive delete link more

Comments

Hmm, @calc314 originally asked me to answer this offline ... But good answer, and it should be available to all.

kcrisman gravatar imagekcrisman ( 2012-01-18 16:28:31 +0200 )edit

Thanks for all of the help! I think I get it now.

calc314 gravatar imagecalc314 ( 2012-01-18 16:39:32 +0200 )edit

I asked Jeff to post these to ask.sagemath.org so that others could see the answers.

Jason Grout gravatar imageJason Grout ( 2012-01-18 18:12:15 +0200 )edit

Sorry, I meant that @calc314 asked me to answer them, and I said to put it on this site so *I* could answer it ;-)

kcrisman gravatar imagekcrisman ( 2012-01-18 20:22:06 +0200 )edit

I have a follow up question, since I know that I will be asked this by students and colleagues. Why does a self-defined function attempt to evaluate f(x) when you give the command plot(f(x), (x,0,5)), but yet when you define a function as below it works? f(x) = x^2 plot(f(x),(x,-3,3))

calc314 gravatar imagecalc314 ( 2012-01-19 10:52:42 +0200 )edit
2

answered 2012-01-18 16:35:17 +0200

kcrisman gravatar image

Another option is to use the (not very powerful) Piecewise class. You could at least do some basic calculus with it as well, then. However, you'd have to define endpoints.

sage: g = Piecewise([[(-10,1),x], [(1,10),x^2]], x)
sage: derivative(g)
Piecewise defined function with 2 parts, [[(-10, 1), x |--> 1], [(1, 10), x |--> 2*x]]
sage: integrate(g)
Piecewise defined function with 2 parts, [[(-10, 1), x |--> 1/2*x^2 - 50], [(1, 10), x |--> 1/3*x^3 - 299/6]]
sage: plot(g)

So it works. But see ticket 11225 for a nice list of ways in which piecewise plotting could be improved. For instance, with infinite endpoints, although it does math, it won't plot. Perhaps that makes sense, since we wouldn't see infinity anyway...

sage: f = Piecewise([[(-oo,1),x], [(1,oo),x^2]], x)
sage: f(-10^6)
-1000000
sage: plot(f)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
ValueError: cannot convert float NaN to integer
edit flag offensive delete link more
1

answered 2012-01-31 13:46:41 +0200

Jason Grout gravatar image

To answer the 3d plot question, again, you need to make the functions calculate their values when the plotting routine is actually getting points, not before the plotting routine is called:

Y=parametric_plot3d([lambda s,t: (2+sin(s))*sin(t*f(s)),lambda s,t: cos(s),lambda s,t: (2+sin(s))*cos(t*f(s))],(s,0,2*pi),(t,-1,1))
edit flag offensive delete link more
0

answered 2012-01-29 18:58:41 +0200

updated 2012-01-31 13:40:54 +0200

Jason Grout gravatar image

Toward a related issue - how do I incorporate such a conditional in a 3d plot? Consider the following.

s,t=var('s,t')
def f(x):
    if x<pi:
        return(arccos(-2/(2+sin(x))))
    if x>=pi:
        return(pi)

plot(f,(x,0,2*pi)) --- to check that the function is properly defined

X=parametric_plot3d([(2+sin(s))*sin(t),cos(s),(2+sin(s))*cos(t)],(s,0,2*pi),(t,0,2*pi))  --- to produce a torus
X.show(aspect_ratio=[1,1,1])

Y=parametric_plot3d([(2+sin(s))*sin(t*f(s)),cos(s),(2+sin(s))*cos(t*f(s))],(s,0,2*pi),(t,-1,1))  --- to produce the part of the torus above the z=-2 plane
Y.show(aspect_ratio=[1,1,1])

This fails. Any hints?

edit flag offensive delete link more

Comments

To post code, highlight the code and click the "code" button (the button that has 1010 on it). Or just indent each line 4 spaces or so.

Jason Grout gravatar imageJason Grout ( 2012-01-31 13:41:26 +0200 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

Stats

Asked: 2012-01-18 16:10:48 +0200

Seen: 2,277 times

Last updated: Jan 31 '12